我想将24位彩色位图数据复制到Int32阵列上,然后编写了以下代码来实现它。
Width of image = 200 pixels
Height of image = 150 pixels
public static Int32[] readBitmap()
{
int rows = 150;
int columns = 200;
Bitmap myBmp = new Bitmap("puppy.bmp");
BitmapData bmd = myBmp.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadWrite, myBmp.PixelFormat);
Console.WriteLine(myBmp.PixelFormat.ToString());
int fileSize = 30000; // 200 * 150
Int32[] fileBufferArray = new Int32[fileSize];
unsafe
{
for (int j = 0; j < rows; j++)
{
Int32* row = (Int32*)bmd.Scan0 + (j * bmd.Stride);
for (int i = 0; i < columns; i++)
{
try
{
fileBufferArray[j * columns + i] = row[i];
}
catch (Exception e)
{
Console.WriteLine(e.ToString() + " " + i.ToString() + " " + j.ToString());
break;
}
}
}
myBmp.UnlockBits(bmd);
return fileBufferArray;
} //unsafe
}
但是我遇到了访问冲突异常。
Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
有人可以帮我纠正这个错误吗?
答案 0 :(得分:2)
问题是具有30,000像素的位图需要3 * 30,000字节来表示24位颜色。每个像素由三个字节表示。你的循环是将字节复制到整数。因为你的整数数组的长度只有30,000个整数,所以它会失败。
如果你写过:
var fileBufferArray = new int[30000];
for (int i = 0; i < 90000; ++i)
{
fileBufferArray[i] = bitmapData[i];
}
显然,这会失败。
您需要将每三个字节组合成一个24位值。一种方法是将内循环中的赋值更改为:
int r = i * 3;
int pixelvalue = row[r];
pixelValue = (pixelValue << 8) | row[r+1];
pixelValue = (pixelValue << 8) | row[r+2];
fileBufferArray[j * columns + i] = pixelValue;
这不是最简洁或最有效的方法,但它说明了这个概念。我也可能没有正确的值的顺序。它们可能先存储低字节而不是高字节。无论如何,这个概念都是一样的。
答案 1 :(得分:1)
你超越了fileBufferArray。看看这种更通用的方法是否可以帮助您。 source:
private unsafe byte[] BmpToBytes_Unsafe (Bitmap bmp)
{
BitmapData bData = bmp.LockBits(new Rectangle (new Point(), bmp.Size),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
// number of bytes in the bitmap
int byteCount = bData.Stride * bmp.Height;
byte[] bmpBytes = new byte[byteCount];
// Copy the locked bytes from memory
Marshal.Copy (bData.Scan0, bmpBytes, 0, byteCount);
// don't forget to unlock the bitmap!!
bmp.UnlockBits (bData);
return bmpBytes;
}
使用流来获取字节数组还有更安全的方法:
private byte[] BmpToBytes(Bitmap bmp)
{
MemoryStream ms = new MemoryStream();
// Save to memory using the bmp format
bmp.Save (ms, ImageFormat.Bmp);
// read to end
byte[] bmpBytes = ms.GetBuffer();
bmp.Dispose();
ms.Close();
return bmpBytes;
}