Поворот изображения вокруг центра
СОДЕРЖАНИЕ
ВВЕДЕНИЕ. ПОСТАНОВКА ЗАДАЧИ.
. ОПИСАНИЕ АЛГОРИТМА ПОВОРОТА ИЗОБРАЖЕНИЯ
. РАЗРАБОТКА ПРИЛОЖЕНИЯ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ C#
.1 Описание приложения
.2 Тестирование приложения
ЗАКЛЮЧЕНИЕ
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
ПРИЛОЖЕНИЕ А
ВВЕДЕНИЕ. ПОСТАНОВКА ЗАДАЧИ
В рамках изучения дисциплины «Получение и обработка изображений» в
качестве контрольной работы поставлена задача описать алгоритм и реализовать
функцию поворота изображения вокруг центра на заданный пользователем угол.
Косинус и синус угла вычислять единожды. Все исходные параметры задавать
произвольно, осуществлять проверку на соответствие диапазону допустимых
значений.
1. Описание алгоритма поворота изображения
Для поворота изображения на заданный в градусах угол используется функция
private Bitmap RotateImage(Bitmap Image, int angle).
Входные параметры:Image - изображение для поворота;angle - угол поворота
в градусах.
Функция возвращает повёрнутое на заданный угол изображение.
Алгоритм работы функции:
) На вход подаётся изображение и угол поворота в градусах;
) Вычисление синуса и косинуса угла поворота (единожды). Угол
поворота задан в радианах;
) Вычисление новой ширины и высоты изображения, используя
вычисленный синус и косинус угла поворота;
) Инициализация массива структур тира Point (Point [] points = new Point [3]), которые определяют
параллелограмм.
) В зависимости от угла поворота (в какой четверти он лежит в
радианах) происходит вычисление координат трёх точек для построения нового
изображения. Вычисление координат происходит на основе пункта (3) данного
алгоритма (новая ширина и высота - пересчет координат Х и У точек);
) Отрисовка повёрнутого изображения по трём точкам (левый верхний,
правый верхний и левый нижний углы параллелограмма. Четвёртая точка
экстраполируется на основе первых трёх).
g.DrawImage(Image, points); - функция прорисовки.
7) Возвращение повёрнутого изображения для использования вне данной
функции.
Центрирование изображения осуществляется свойством элемента
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
2. РАЗРАБОТКА
ПРИЛОЖЕНИЯ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ C#
В качестве инструмента разработки приложения по обработке изображения
была выбрана среда MS Visual Studio 2012. Языком программирования выбран C#. Данный инструментарий
предоставляет достаточный спектр возможностей по работе с графикой.
Разработано приложение согласно поставленной задаче.
2.1 Описание приложения
поворот изображение угол диапазон
В основе приложения лежит класс frmRotationForm.
В данном классе реализованы следующие методы:
Метод private void btnRotateImage_Click(object sender, EventArgs e)
обрабатывает нажатие на кнопку «повернуть изображение». После нажатия
происходит попытка преобразования содержимого текстового поля в число (для
дальнейшего использования в качестве переменной ang, которая предназначена для хранения угла поворота в
градусах). Также в данном методе осуществляется обработка исключений, запуск
функции RotateImage, которая и осуществляет поворот
изображения.
Метод private Bitmap RotateImage(Bitmap Image, int angle) осуществляет
поворот изображения на заданный угол. Возвращает повёрнутое изображение.
Метод private void btnLoadImage_Click(object sender, EventArgs e)
загружает изображение с диска в PictureBox с оригинальным изображением.
Метод
private void timer1_Tick(object sender, EventArgs e) выполняется на каждый такт таймера. В данном приложении частота установлена в 50 миллисекунд (для
более «гладкой» работы в режиме «анимации»).
2.2 Тестирование приложения
Разработанное приложение тестировалось в среде Microsoft Windows 7 64-bit с
установленным .NET Framework 4.5. Результат запуска исполняемого
файла Image_Rotation.exe представлен на рисунке 2.1.
Рисунок 2.1 - Окно приложения при запуске
При запуске в приложении «зашито» выбранное мной изображение по
умолчанию. Его можно сменить, нажав кнопку «Загрузить изображение». Результат
выбора собственного изображения представлен на рисунке 2.2.
Рисунок 2.2 - Выбор собственного изображения для поворота
Дальнейшие действия рассматриваются на изображении по умолчанию. Выбрав
угол поворота в соответствующем текстовом поле в верхнем левом углу формы
следует нажать кнопку «повернуть изображение». (см. рисунок 2.3).
Рисунок 2.3 - Результат поворота изображения на 8 градусов
Описанные прямоугольники на рисунке являются вспомогательным
инструментом, выводятся для собственного удобства и показывают центр
изображения.
В приложении реализована «защита от дурака», а именно: при попытке ввести
угол больше 360 градусов, либо меньше -360 градусов, а также текст, выводится
предупреждение и изображение не будет обработано:
Рисунок 2.4 - Попытка повернуть изображение на -361 градус
В приложении реализована возможность «анимированного вращения» по\против
часовой стрелки, а также «зум» (увеличение картинки по размеру контейнера PictureBox).
Рисунок 2.5 - Анимированное вращение
ЗАКЛЮЧЕНИЕ
Задача, поставленная в техническом задании к контрольной работе,
реализована.
Изучены приёмы обработки изображений, используя язык программирования C#.
Исходный код приложения представлен в «Приложении А».
СПИСОК
ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1 Старовойтов
В.В. Цифровые изображения: от получения до
обработки /
В.В. Старовойтов, Ю.И. Голуб - Минск: ОИПИ НАН Беларуси, 2014. - 202 с. - ISBN
978-985-6744-80-1.
Кристиан
Нейгел, Билл Ивьен и др. C# 2008 и платформа .NET 3.5 для профессионалов -
Professional C# 2008. - М.: Диалектика, 2008. - ISBN 978-5-8459-1458-3.
3 Разработка приложений на
платформе Microsoft. MSDN [Электронный ресурс]:
<http://msdn.microsoft.com/ru-ru/library/4f9s3at1(v=vs.110).aspx> . -
Дата обращения 25.10.2014.
ПРИЛОЖЕНИЕ А
Листинг класса «frmRotationForm»
using
System;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Threading.Tasks;System.Windows.Forms;System.Drawing.Drawing2D;Image_Rotation
{partial class frmRotationForm : Form
{int jj;//угол в градусахfrmRotationForm()
{();.Text =
pictureBox3.Image.Width.ToString();.Text =
pictureBox3.Image.Height.ToString();= Convert.ToInt32(textBox1.Text);
}void btnRotateImage_Click(object sender,
EventArgs e)
{.Image = pictureBox3.Image;ang = 0 ;
{= Convert.ToInt32(textBox1.Text);
if (ang < -360 || ang > 360)
{.Show("Разрешено использовать углы от 0 до 360.
\nДопустается использование знака \'-\' для поворота против часовой стрелки.");;
}
}(Exception ex)
return;
}i = new Bitmap(pictureBox1.Image);.Image =
this.RotateImage(i, ang);
//this.Controls.Add(pictureBox1);
}Bitmap RotateImage(Bitmap Image, int angle)
{pi2 = Math.PI/2;//ПИ на два
int oldWidth = Image.Width;oldHeigth =
Image.Height;theta = angle * Math.PI / 180.0;//перевод в радианыlocked_theta =
theta;(locked_theta < 0.0) locked_theta += 2 * Math.PI;newWidth,
newHeigth;nWidth, nHeigth;adjacentTop, oppositeTop;adjacentBottom,
oppositeBottom;
#region Вычисление новой ширины и высоты
double SINUS =
Math.Abs(Math.Sin(locked_theta));COSINUS =
Math.Abs(Math.Cos(locked_theta));((locked_theta >= 0.0 &&
locked_theta < pi2) || (locked_theta >= Math.PI && locked_theta
< (Math.PI + pi2)))
{// Угол (>= 0 и < Pi/2) или (>= ПИ и < ПИ +
Пи/2)
adjacentTop = COSINUS * oldWidth;= SINUS *
oldWidth;= COSINUS * oldHeigth;= SINUS * oldHeigth;
}
{= SINUS * oldHeigth;= COSINUS * oldHeigth;=
SINUS * oldWidth;= COSINUS * oldWidth;
}= adjacentTop + oppositeBottom;=
adjacentBottom + oppositeTop;= (int)(Math.Ceiling(newWidth));//округление до целых вверх=
(int)(Math.Ceiling(newHeigth));
#endregion Вычисление новой ширины и высоты
Bitmap rotatedBmp = new
Bitmap(nWidth,nHeigth);g = Graphics.FromImage(rotatedBmp);
Point [] points = new Point [3];//массив из 3 структур
типа Point, которые определяют параллелограмм
//Три точки обозначают: верхний левый, верхний правый,
нижний левый углы параллелограмма.
//Четвёртая точка экстраполируется из первых трёх
//точка отсчёта (0,0) - левый верхний угол(locked_theta
>= 0.0 && locked_theta < pi2) //90
{[0] = new Point((int)oppositeBottom, 0);[1]
= new Point(nWidth, (int)(oppositeTop));[2] = new Point(0,
(int)(adjacentBottom));
}if (locked_theta >= pi2 &&
locked_theta < Math.PI) //90-180
{[0] = new Point(nWidth,
(int)(oppositeTop));[1] = new Point((int)(adjacentTop), nHeigth);[2] = new
Point((int)(oppositeBottom), 0);
}if (locked_theta >= Math.PI &&
locked_theta < (Math.PI + pi2))//180-270
{[0] = new Point((int)(adjacentTop),
nHeigth);[1] = new Point(0, (int)(adjacentBottom));[2] = new Point(nWidth,
(int)(oppositeTop));
}
{[0] = new Point(0,
(int)(adjacentBottom));[1] = new Point((int)(oppositeBottom), 0);[2] = new
Point((int)(adjacentTop), nHeigth);
}.Text = "Центр ИСХОДНЫЙ х="+
(oldWidth / 2.0f).ToString() + ", у=" + (oldHeigth /
2.0f).ToString();.Text = "Центр ПОВЕРНУТЫЙ х=" + (nWidth / 2.0f).ToString() + ", у=" +
(nHeigth / 2.0f).ToString();.DrawImage(Image, points);.DrawRectangle(new
Pen(Color.Red, 0.1f),new Rectangle(0,0,nWidth/2,nHeigth/2));.DrawRectangle(new
Pen(Color.Red, 0.1f), new Rectangle(nWidth/2, nHeigth/2, nWidth/2-1,
nHeigth/2-1));.Dispose();.Dispose();rotatedBmp;
}void btnLoadImage_Click(object sender,
EventArgs e)
{dlg = new OpenFileDialog();
.Title = "Open Image";.Filter =
"jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";(dlg.ShowDialog() ==
DialogResult.OK)
{.Image = new Bitmap(dlg.OpenFile());.Image
= pictureBox3.Image;
}.Text =
pictureBox1.Image.Width.ToString();.Text =
pictureBox1.Image.Height.ToString();.Dispose();
}void timer1_Tick(object sender, EventArgs
e)
{(checkBox2.Checked)
{//изменение режима пкчербокса на ЗУМ.SizeMode =
PictureBoxSizeMode.Zoom;
}
//если не отмечено, то изображение центрируется
else {.SizeMode =
PictureBoxSizeMode.CenterImage;
}(checkBox1.Checked)
{//реализация "анимации"-вращения картинки
вокруг своей оси по/против часовой
radioButton1.Visible = true;.Visible = true;(radioButton1.Checked)
{ //по часовой.btnRotateImage_Click(this,
e);.textBox1.Text = jj++.ToString();
if (jj == 360) jj = 0;
}
{//против часовой
this.btnRotateImage_Click(this,
e);.textBox1.Text = jj--.ToString();(jj == 0) jj = 359;
}
}
{.Visible = false;.Visible = false;
}
}
}
}