C# конвертировать шаг / буфер / ширину / высоту в растровое изображение
У меня есть ширина изображения / высота / шаг и буфер.
Как мне преобразовать эту информацию в System.Drawing.Bitmap? Могу ли я вернуть исходное изображение, если у меня есть эти 4 вещи?
2 ответа
E сть Bitmap
перегрузка конструктора, которая требует всего, что у вас есть (плюс PixelFormat
):
public Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);
Это может сработать (если args.Buffer
является массивом типа Blittable, как byte
например):
Bitmap bitmap;
var gch = System.Runtime.InteropServices.GCHandle.Alloc(args.Buffer, GCHandleType.Pinned);
try
{
bitmap = new Bitmap(
args.Width, args.Height, args.Stride,
System.Drawing.Imaging.PixelFormat.Format24bppRgb,
gch.AddrOfPinnedObject());
}
finally
{
gch.Free();
}
Обновить:
Вероятно, лучше скопировать байты изображения во вновь созданный Bitmap
вручную, потому что кажется, что конструкторы этого не делают, и если byte[]
массив данных изображений получает мусор, собирает все виды плохих вещей, которые могут произойти.
var bitmap = new Bitmap(args.Width, args.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
var data = bitmap.LockBits(
new Rectangle(0, 0, args.Width, args.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
if(data.Stride == args.Stride)
{
Marshal.Copy(args.Buffer, 0, data.Scan0, args.Stride * args.Height);
}
else
{
int arrayOffset = 0;
int imageOffset = 0;
for(int y = 0; y < args.Height; ++y)
{
Marshal.Copy(args.Buffer, arrayOffset, (IntPtr)(((long)data.Scan0) + imageOffset), data.Stride);
arrayOffset += args.Stride;
imageOffset += data.Stride;
}
}
bitmap.UnlockBits(data);
Это должно работать, если у вас есть буфер как byte[], ширина и высота + формат пикселя (шаг)
public Bitmap CreateBitmapFromRawDataBuffer(int width, int height, PixelFormat imagePixelFormat, byte[] buffer)
{
Size imageSize = new Size(width, height);
Bitmap bitmap = new Bitmap(imageSize.Width, imageSize.Height, imagePixelFormat);
Rectangle wholeBitmap = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
// Lock all bitmap's pixels.
BitmapData bitmapData = bitmap.LockBits(wholeBitmap, ImageLockMode.WriteOnly, imagePixelFormat);
// Copy the buffer into bitmapData.
System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bitmapData.Scan0, buffer.Length);
// Unlock all bitmap's pixels.
bitmap.UnlockBits(bitmapData);
return bitmap;
}