Статья опубликована в рамках: XLII Международной научно-практической конференции «Научное сообщество студентов XXI столетия. ТЕХНИЧЕСКИЕ НАУКИ» (Россия, г. Новосибирск, 31 мая 2016 г.)
Наука: Информационные технологии
Скачать книгу(-и): Сборник статей конференции
дипломов
Реализация алгоритма поворота изображения средствами .NET Framework для Windows Phone 8.1
При программировании прикладных приложений часто возникают проблемы, касающиеся обработки изображений. Одна из таких проблем - поворот заданного изображения на произвольный угол.
Сформулируем условия к задаче так: необходимо повернуть заданное изображение относительно его центра с изменением размера, так, чтобы повернутое изображение помещалось целиком (т.е. углы не выходили за рамки изображения). Решим эту задачу для платформы Windows Phone 8.1 средствами .NET Framework и подключаемых библиотек.
Рассмотрим операцию поворота с точки зрения линейной алгебры. В общем случае вращение около произвольной точки может быть выполнено путем переноса центра вращения в начало координат, поворотом относительно начала координат, а затем переносом точки вращения в исходное положение. Таким образом, поворот вектора положения (x,y,1) около точки (m,n) на произвольный угол может быть выполнен с помощью преобразования
Выполнив две операции умножения матриц, можно записать матрицу поворота на угол относительно точки (m,n)
Для решения поставленной задачи воспользуемся библиотекой Win2D, которая обеспечивает набор классов для двумерной графики и в частности для рисования. Класс CanvasRenderTarget используется для рендеринга изображений. С помощью него можно получить экземпляр CanvasDrawingSession – непосредственно изобразительной сессии. С помощью метода DrawImage этого класса можно нарисовать необходимое изображение. Кроме того, можно задать некоторые параметры рисования.
Теперь рассмотрим свойство Transform класса CanvasDrawingSession. Оно представлено типом Matrix3x2. Это суть квадратная матрица преобразования 3х3, третий столбец которой всегда равен (0,0,1), т.к. преобразование двумерно. С помощью этой матрицы можно задать некоторое преобразование для отрисовки изображения: поворот, растягивание, перенос по координатам осей или некоторую комбинацию этих преобразований. Воспользуемся полученной выше матрицей и зададим свойству Transfrom следующее значение:
где точка (m,n) – середина изображения. Если ширина исходного изображения равна w, а высота – h, тогда m = w/2, n = h/2.
Осталось решить еще одну подзадачу, которая касается размера результирующего изображения. Размеры для CanvasRenderTarget задаются вручную. Следовательно, нужно рассчитать такие ширину и высоту для него, чтобы повернутое изображение помещалось целиком.
Рисунок 1. Схематичный чертеж поворота изображения.
Построим схематичный чертеж. На рисунке 1 пунктиром обозначена область исходного изображения, а сплошными линиями – повернутое изображение и его новые границы. Отметим на чертеже угол и обратим внимание на прямоугольные треугольники, «незанятые» изображением. Их гипотенузы – это ширина и высота исходного изображения. Нужно найти катеты этих треугольников, что несложно, т.к. в треугольниках известны гипотенуза и острый угол. Тогда ширина и высота нового изображения:
Приведем реализацию функции RotateAsync.
private async Task<WriteableBitmap> RotateAsync(WriteableBitmap inputBmp, float angleDegree) {
angleDegree = (float)(angleDegree* 3.14 / 180);
var w = inputBmp.PixelWidth;
var h = inputBmp.PixelHeight;
CanvasDevice device = CanvasDevice.GetSharedDevice();
var wnew = h * Math.Sin(angleDegree) + w * Math.Cos(angleDegree);
var hnew = h * Math.Cos(angleDegree) + w * Math.Sin(angleDegree);
CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (float) wnew, (float) hnew, 96);
CanvasBitmap c = CanvasBitmap.CreateFromBytes(device, inputBmp.PixelBuffer.ToArray(), w, h, Microsoft.Graphics.Canvas.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized);
using (CanvasDrawingSession drawingSession = renderTarget.CreateDrawingSession()) {
var transform = new Matrix3x2();
transform.M11 = (float)Math.Cos(angleDegree);
transform.M12 = -(float)Math.Sin(angleDegree);
transform.M21 = (float)Math.Sin(angleDegree);
transform.M22 = (float)Math.Cos(angleDegree);
transform.M31 = (float)(-(w/2)*(Math.Cos(angleDegree) - 1) + (h / 2) * Math.Sin(angleDegree) + wnew/2-w/2);
transform.M32 = (float)(-(w / 2) * Math.Sin(angleDegree) - (originalheight / 2) * (Math.Cos(angleDegree)-1) + hnew / 2 - h / 2);
drawingSession.Transform = transform;
drawingSession.DrawImage(c);
drawingSession.Flush();
}
WriteableBitmap result = new WriteableBitmap(wnew, hnew);
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) {
await renderTarget.SaveAsync(stream, CanvasBitmapFileFormat.Png, 1);
await result.SetSourceAsync(stream)
}
return result;
}
Список литературы:
- Каменева А.Е., Горбунова А.В. Градационные преобразования матрицы изображения [Текст] / Каменева А.Е., Горбунова А.В. // Электронный научный журнал № 3 (3): сб. статей. – Москва, 2016. – С. 12-15.
- Пугачев С.В. Разработка приложений для Windows 8 на языке C# / С. В. Пугачев, А. М. Шериев, К. А. Кичинский. — СПб.: БХВ-Петербург, 2013. — 416 с.
- Рихтер Дж. CLR via C#. Программирование на платформе Microsoft .NET Framework 2.0 на языке C#. Мастер-класс. / Пер. с англ. — 2-е изд., исправ. — М.: Издательство «Русская Редакция»; СПб.: Питер , 2008. — 656 стр.: ил.
дипломов
Оставить комментарий