Поворот изображения на 90 градусов в C#
Здесь я приведу функцию поворота изображения на 90 градусов, но не отображения pictureBox под определённым углом, а именно трансформации изображения при котором на входе имеем одно изображение а на выходе абсолютно другое идентичное первому — но повёрнутое на 90 градусов.
В функции используется тот же принцип что и в предыдущей публикации (изменяем область памяти где содержится картинка). За счёт этого скорость работы этой функции довольно высокая.
Итак, пример функции:
//Трансформация изображения (поворотом на 90 градусов).
public static Bitmap MakeTurn(Bitmap bmp)
{
//Создаём пустую картинку - с шириной как высота исходной
//и высотой как ширина исходной
Bitmap bmp90 = new Bitmap(bmp.Height,bmp.Width);
// Задаём формат Пикселя.
PixelFormat pxf = PixelFormat.Format24bppRgb;
//Для удобства ширину и высоту вынес в переменные.
int X = bmp.Width;
int Y = bmp.Height;
// Получаем данные картинки.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
//Аналогично поступаем с пустой картинкой.
Rectangle rect1 = new Rectangle(0, 0, bmp90.Width, bmp90.Height);
//Блокируем набор данных изображения в памяти (для обеих картинок)
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, pxf);
BitmapData bmpData1 = bmp90.LockBits(rect1, ImageLockMode.ReadWrite, pxf);
// Получаем адрес первой линии (для обеих картинок).
IntPtr ptr = bmpData.Scan0;
IntPtr ptr1 = bmpData1.Scan0;
// Задаём массив из Byte и помещаем в него набор данных.
// int numBytes = bmp.Width * bmp.Height * 3;
//На 3 умножаем - поскольку RGB цвет кодируется 3-мя байтами
//Либо используем вместо Width - Stride
int numBytes = bmpData.Stride * bmp.Height;
int widthBytes = bmpData.Stride;
byte[] rgbValues = new byte[numBytes];
//Аналогично для пустой (пока пустой) картинки.
int numBytes1 = bmpData1.Stride * bmp90.Height;
int widthBytes1 = bmpData1.Stride;
byte[] rgbValues1 = new byte[numBytes1];
// Копируем значения в массив (для обеих картинок).
Marshal.Copy(ptr, rgbValues, 0, numBytes);
Marshal.Copy(ptr1, rgbValues1, 0, numBytes1);
// Перебираем исходное изображение по линиям и перестраиваем его в пустое
for (int counter = 0; counter < Y; counter += 1)
{
for (int counter1 = 0; counter1 < X; counter1 += 1)
{
//Абсолютная позиция точки в иходнике.
int position = ((counter) * X + counter1) * 3;
//Абсолютная позиция точки в приёмнике.
int position1 = ((X - counter1 - 1) * Y + counter) * 3;
//Копируем 3 байта цвета точки.
rgbValues1[position1] = rgbValues[position];
rgbValues1[position1 + 1] = rgbValues[position+1];
rgbValues1[position1 + 2] = rgbValues[position+2];
}
}
// Копируем набор данных обратно в изображения
Marshal.Copy(rgbValues, 0, ptr, numBytes);
Marshal.Copy(rgbValues1, 0, ptr1, numBytes1);
// Разблокируем набор данных изображений в памяти.
bmp.UnlockBits(bmpData);
bmp90.UnlockBits(bmpData1);
//Возвращаем готовую картинку.
return bmp90;
}
Разумеется для работы процедуры необходимо подключить:
System.Drawing.Imaging;
System.Runtime.InteropServices;
Вот и всё.