Поворот изображения вокруг центра
Метод private void btnRotateImage_Click (object sender, EventArgs e) обрабатывает нажатие на кнопку «повернуть изображение». После нажатия происходит попытка преобразования содержимого текстового поля в число (для дальнейшего использования в качестве переменной ang, которая предназначена для хранения угла поворота в градусах). Также в данном методе осуществляется обработка исключений, запуск… Читать ещё >
Поворот изображения вокруг центра (реферат, курсовая, диплом, контрольная)
ВВЕДЕНИЕ
ПОСТАНОВКА ЗАДАЧИ.
1. ОПИСАНИЕ АЛГОРИТМА ПОВОРОТА ИЗОБРАЖЕНИЯ
2. РАЗРАБОТКА ПРИЛОЖЕНИЯ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ C#
2.1 Описание приложения
2.2 Тестирование приложения ЗАКЛЮЧЕНИЕ СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ПРИЛОЖЕНИЕ А
ВВЕДЕНИЕ
ПОСТАНОВКА ЗАДАЧИ В рамках изучения дисциплины «Получение и обработка изображений» в качестве контрольной работы поставлена задача описать алгоритм и реализовать функцию поворота изображения вокруг центра на заданный пользователем угол. Косинус и синус угла вычислять единожды. Все исходные параметры задавать произвольно, осуществлять проверку на соответствие диапазону допустимых значений.
1. Описание алгоритма поворота изображения
Для поворота изображения на заданный в градусах угол используется функция private Bitmap RotateImage (Bitmap Image, int angle).
Входные параметры:
Bitmap Image — изображение для поворота;
int angle — угол поворота в градусах.
Функция возвращает повёрнутое на заданный угол изображение.
Алгоритм работы функции:
1) На вход подаётся изображение и угол поворота в градусах;
2) Вычисление синуса и косинуса угла поворота (единожды). Угол поворота задан в радианах;
3) Вычисление новой ширины и высоты изображения, используя вычисленный синус и косинус угла поворота;
4) Инициализация массива структур тира Point (Point [] points = new Point [3]), которые определяют параллелограмм.
5) В зависимости от угла поворота (в какой четверти он лежит в радианах) происходит вычисление координат трёх точек для построения нового изображения. Вычисление координат происходит на основе пункта (3) данного алгоритма (новая ширина и высота — пересчет координат Х и У точек);
6) Отрисовка повёрнутого изображения по трём точкам (левый верхний, правый верхний и левый нижний углы параллелограмма. Четвёртая точка экстраполируется на основе первых трёх).
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.
2 Кристиан Нейгел, Билл Ивьен и др. 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;
using System.Collections.Generic;
using System. ComponentModel;
using System. Data;
using System. Drawing;
using System. Linq;
using System. Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace Image_Rotation
{
public partial class frmRotationForm: Form
{
private int jj;//угол в градусах
public frmRotationForm ()
{
InitializeComponent ();
w.Text = pictureBox3.Image.Width.ToString ();
h.Text = pictureBox3.Image.Height.ToString ();
jj = Convert. ToInt32(textBox1.Text);
}
private void btnRotateImage_Click (object sender, EventArgs e)
{
pictureBox1.Image = pictureBox3. Image;
int ang = 0 ;
try
{
ang = Convert. ToInt32(textBox1.Text);
if (ang < -360 || ang > 360)
{
MessageBox.Show («Разрешено использовать углы от 0 до 360. nДопустается использование знака '-' для поворота против часовой стрелки.»);
return;
}
}
catch (Exception ex)
{
MessageBox.Show («Разрешено использовать углы от 0 до 360. nДопустается использование знака '-' для поворота против часовой стрелки.»);
return;
}
Bitmap i = new Bitmap (pictureBox1.Image);
pictureBox1.Image = this. RotateImage (i, ang);
//this.Controls.Add (pictureBox1);
}
private Bitmap RotateImage (Bitmap Image, int angle)
{
var pi2 = Math. PI/2;//ПИ на два
int oldWidth = Image. Width;
int oldHeigth = Image. Height;
var theta = angle * Math. PI / 180.0;//перевод в радианы
var locked_theta = theta;
if (locked_theta < 0.0) locked_theta += 2 * Math. PI;
double newWidth, newHeigth;
int nWidth, nHeigth;
double adjacentTop, oppositeTop;
double adjacentBottom, oppositeBottom;
#region Вычисление новой ширины и высоты
double SINUS = Math. Abs (Math.Sin (locked_theta));
double COSINUS = Math. Abs (Math.Cos (locked_theta));
if ((locked_theta >= 0.0 && locked_theta < pi2) || (locked_theta >= Math. PI && locked_theta < (Math.PI + pi2)))
{// Угол (>= 0 и < Pi/2) или (>= ПИ и < ПИ + Пи/2)
adjacentTop = COSINUS * oldWidth;
oppositeTop = SINUS * oldWidth;
adjacentBottom = COSINUS * oldHeigth;
oppositeBottom = SINUS * oldHeigth;
}
else
{
adjacentTop = SINUS * oldHeigth;
oppositeTop = COSINUS * oldHeigth;
adjacentBottom = SINUS * oldWidth;
oppositeBottom = COSINUS * oldWidth;
}
newWidth = adjacentTop + oppositeBottom;
newHeigth = adjacentBottom + oppositeTop;
nWidth = (int)(Math.Ceiling (newWidth));//округление до целых вверх
nHeigth = (int)(Math.Ceiling (newHeigth));
#endregion Вычисление новой ширины и высоты
Bitmap rotatedBmp = new Bitmap (nWidth, nHeigth);
Graphics g = Graphics. FromImage (rotatedBmp);
Point [] points = new Point [3]; //массив из 3 структур типа Point, которые определяют параллелограмм
//Три точки обозначают: верхний левый, верхний правый, нижний левый углы параллелограмма.
//Четвёртая точка экстраполируется из первых трёх
//точка отсчёта (0,0) — левый верхний угол
if (locked_theta >= 0.0 && locked_theta < pi2) //90
{
points[0] = new Point ((int)oppositeBottom, 0);
points[1] = new Point (nWidth, (int)(oppositeTop));
points[2] = new Point (0, (int)(adjacentBottom));
}
else if (locked_theta >= pi2 && locked_theta < Math. PI) //90−180
{
points[0] = new Point (nWidth, (int)(oppositeTop));
points[1] = new Point ((int)(adjacentTop), nHeigth);
points[2] = new Point ((int)(oppositeBottom), 0);
}
else if (locked_theta >= Math. PI && locked_theta < (Math.PI + pi2))//180−270
{
points[0] = new Point ((int)(adjacentTop), nHeigth);
points[1] = new Point (0, (int)(adjacentBottom));
points[2] = new Point (nWidth, (int)(oppositeTop));
}
else
{
points[0] = new Point (0, (int)(adjacentBottom));
points[1] = new Point ((int)(oppositeBottom), 0);
points[2] = new Point ((int)(adjacentTop), nHeigth);
}
label6.Text = «Центр ИСХОДНЫЙ х="+ (oldWidth / 2.0f).ToString () + «, у=» + (oldHeigth / 2.0f).ToString ();
label7.Text = «Центр ПОВЕРНУТЫЙ х=» + (nWidth / 2.0f).ToString () + «, у=» + (nHeigth / 2.0f).ToString ();
g.DrawImage (Image, points);
g.DrawRectangle (new Pen (Color.Red, 0.1f), new Rectangle (0,0,nWidth/2,nHeigth/2));
g.DrawRectangle (new Pen (Color.Red, 0.1f), new Rectangle (nWidth/2, nHeigth/2, nWidth/2−1, nHeigth/2−1));
g.Dispose ();
Image.Dispose ();
return rotatedBmp;
}
private void btnLoadImage_Click (object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog ();
dlg.Title = «Open Image» ;
dlg.Filter = «jpg files (*.jpg)|*.jpg|All files (*.*)|*.*» ;
if (dlg.ShowDialog () == DialogResult. OK)
{
pictureBox3.Image = new Bitmap (dlg.OpenFile ());
pictureBox1.Image = pictureBox3. Image;
}
w.Text = pictureBox1.Image.Width.ToString ();
h.Text = pictureBox1.Image.Height.ToString ();
dlg.Dispose ();
}
private void timer1_Tick (object sender, EventArgs e)
{
if (checkBox2.Checked)
{//изменение режима пкчербокса на ЗУМ
pictureBox1.SizeMode = PictureBoxSizeMode. Zoom;
}
//если не отмечено, то изображение центрируется
else {
pictureBox1.SizeMode = PictureBoxSizeMode. CenterImage;
}
if (checkBox1.Checked)
{//реализация «анимации» -вращения картинки вокруг своей оси по/против часовой
radioButton1.Visible = true;
radioButton2.Visible = true;
if (radioButton1.Checked)
{ //по часовой
this.btnRotateImage_Click (this, e);
this.textBox1.Text = jj++.ToString ();
if (jj == 360) jj = 0;
}
else
{//против часовой
this.btnRotateImage_Click (this, e);
this.textBox1.Text = jj—.ToString ();
if (jj == 0) jj = 359;
}
}
else
{
radioButton1.Visible = false;
radioButton2.Visible = false;
}
}
}
}