Хочу отметить, что в решении, предоставленном @ isaias-b, есть ошибка.
В этом решении предполагается, что stride
равно длине строки.Но это не всегда так.Из-за выравнивания памяти, выполняемого GDI, шаг может быть больше, чем длина строки.Это необходимо учитывать.В противном случае будет сгенерировано неверное смещенное изображение.Байты заполнения в каждой строке будут игнорироваться.
Шаг - это ширина одного ряда пикселей (строки развертки), округленная до четырехбайтовой границы.
Фиксированный код:
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
public static class ImageExtensions
{
public static Image ImageFromRawBgraArray(this byte[] arr, int width, int height, PixelFormat pixelFormat)
{
var output = new Bitmap(width, height, pixelFormat);
var rect = new Rectangle(0, 0, width, height);
var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);
// Row-by-row copy
var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
var ptr = bmpData.Scan0;
for (var i = 0; i < height; i++)
{
Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
ptr += bmpData.Stride;
}
output.UnlockBits(bmpData);
return output;
}
}
Чтобы проиллюстрировать, к чему это может привести, давайте сгенерируем PixelFormat.Format24bppRgb
градиентное изображение 101x101:
var width = 101;
var height = 101;
var gradient = new byte[width * height * 3 /* bytes per pixel */];
for (int i = 0, pixel = 0; i < gradient.Length; i++, pixel = i / 3)
{
var x = pixel % height;
var y = (pixel - x) / width;
gradient[i] = (byte)((x / (double)(width - 1) + y / (double)(height - 1)) / 2d * 255);
}
Если мы скопируем весь массив как естьпо адресу, указанному bmpData.Scan0
, мы получим следующее изображение.Смещение изображения, потому что часть изображения была записана в байты заполнения, что было проигнорировано.Также, поэтому последняя строка является неполной:
Но если мы будем копировать строковый указатель смещения по строке на значение bmpData.Stride
, допустимобудет сгенерировано изображение:
Шаг также может быть отрицательным:
Если шаг является положительным, битовая картанизходящий.Если шаг отрицательный, растровое изображение идет снизу вверх.
Но я не работал с такими изображениями, и это выходит за рамки моей заметки.
Соответствующий ответ: C # - RGB-буфер из Bitmap, отличный от C ++