[英]Generate 16-bit grayscale BitmapData and save to file
I am trying to generate 16bit grayscale Bitmap in C# from a random data.But it crashed on Marshal.Copy. 我试图用随机数据在C#中生成16位灰度位图,但在Marshal.Copy上崩溃了。
Here is my code: 这是我的代码:
Bitmap b16bpp;
private void GenerateDummy16bitImage()
{
b16bpp = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
var rect = new Rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
var bitmapData = b16bpp.LockBits(rect, ImageLockMode.WriteOnly, b16bpp.PixelFormat);
// Calculate the number of bytes required and allocate them.
var numberOfBytes = bitmapData.Stride * IMAGE_HEIGHT * 2;
var bitmapBytes = new short[numberOfBytes];
// Fill the bitmap bytes with random data.
var random = new Random();
for (int x = 0; x < IMAGE_WIDTH; x++)
{
for (int y = 0; y < IMAGE_HEIGHT; y++)
{
var i = ((y * IMAGE_WIDTH) + x) * 2; // 16bpp
// Generate the next random pixel color value.
var value = (short)random.Next(5);
bitmapBytes[i] = value; // BLUE
bitmapBytes[i + 1] = value; // GREEN
bitmapBytes[i + 2] = value; // RED
// bitmapBytes[i + 3] = 0xFF; // ALPHA
}
}
// Copy the randomized bits to the bitmap pointer.
var ptr = bitmapData.Scan0;
Marshal.Copy(bitmapBytes, 0, ptr, numberOfBytes);//crashes here
// Unlock the bitmap, we're all done.
b16bpp.UnlockBits(bitmapData);
b16bpp.Save("random.bmp", ImageFormat.Bmp);
Debug.WriteLine("saved");
}
The exception is: 例外是:
An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll mscorlib.dll中发生了类型为'System.AccessViolationException'的未处理异常
This is not my code.I found it in relation to 32bit Bitmaps and modified.But I guess I have missed something as I am pretty new to C#. 这不是我的代码,我发现它与32位位图有关并已修改,但我想我已经错过了一些东西,因为我对C#相当陌生。
Basically,all I need is to wrap into BitmapData an arrays of shorts. 基本上,我所需要做的就是将短裤数组包装到BitmapData中。
This works for System.Drawing.Imaging.PixelFormat.Format16bppGrayScale: 这适用于System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:
private static void SaveBmp(Bitmap bmp, string path)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
var pixelFormats = ConvertBmpPixelFormat(bmp.PixelFormat);
BitmapSource source = BitmapSource.Create(bmp.Width,
bmp.Height,
bmp.HorizontalResolution,
bmp.VerticalResolution,
pixelFormats,
null,
bitmapData.Scan0,
bitmapData.Stride * bmp.Height,
bitmapData.Stride);
bmp.UnlockBits(bitmapData);
FileStream stream = new FileStream(path, FileMode.Create);
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.Zip;
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(stream);
stream.Close();
}
private static System.Windows.Media.PixelFormat ConvertBmpPixelFormat(System.Drawing.Imaging.PixelFormat pixelformat)
{
System.Windows.Media.PixelFormat pixelFormats = System.Windows.Media.PixelFormats.Default;
switch (pixelformat)
{
case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
pixelFormats = PixelFormats.Bgr32;
break;
case System.Drawing.Imaging.PixelFormat.Format8bppIndexed:
pixelFormats = PixelFormats.Gray8;
break;
case System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:
pixelFormats = PixelFormats.Gray16;
break;
}
return pixelFormats;
}
I have corrected some of your mistakes (mostly wrong sizes). 我已纠正了您的一些错误(大多数是错误的尺寸)。 But it will still crash on b16bpp.Save()
, because GDI+ does not support saving 16bit grayscale images . 但是它仍然会在b16bpp.Save()
上崩溃,因为GDI +不支持保存16位灰度图像 。
Bitmap b16bpp;
private void GenerateDummy16bitImage()
{
b16bpp = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
var rect = new Rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
var bitmapData = b16bpp.LockBits(rect, ImageLockMode.WriteOnly, b16bpp.PixelFormat);
// Calculate the number of bytes required and allocate them.
var numberOfBytes = bitmapData.Stride * IMAGE_HEIGHT;
var bitmapBytes = new short[IMAGE_WIDTH * IMAGE_HEIGHT];
// Fill the bitmap bytes with random data.
var random = new Random();
for (int x = 0; x < IMAGE_WIDTH; x++)
{
for (int y = 0; y < IMAGE_HEIGHT; y++)
{
var i = ((y * IMAGE_WIDTH) + x); // 16bpp
// Generate the next random pixel color value.
var value = (short)random.Next(5);
bitmapBytes[i] = value; // GRAY
}
}
// Copy the randomized bits to the bitmap pointer.
var ptr = bitmapData.Scan0;
Marshal.Copy(bitmapBytes, 0, ptr, bitmapBytes.Length);
// Unlock the bitmap, we're all done.
b16bpp.UnlockBits(bitmapData);
b16bpp.Save("random.bmp", ImageFormat.Bmp);
Debug.WriteLine("saved");
}
Explanation of my changes: 我的更改说明:
bitmapData.Stride
is already IMAGE_WIDTH * BytesPerPixel
so you don't need to multiply by 2 bitmapData.Stride
已经是IMAGE_WIDTH * BytesPerPixel
因此您不需要乘以2 bitmapBytes
as short[]
it has to have the size of the image in pixels not in bytes 正如您将bitmapBytes
声明为short[]
一样,图像的大小必须以像素为单位,而不是以字节为单位 i
by 2 这意味着您也不需要将i
乘以2 All in all you tried to copy an array 8 times to large into the bitmap. 总而言之,您试图将一个数组复制8次,使其大到位图中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.