在Java中我会做这样的事情
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
其中 image 是一个 BufferedImage ,然后改变那里的像素并制作我自己的 blitting 方法但是我应该如何在 C# 中做这样的事情?我知道我可以使用位图来替换 C# 中的 BufferedImage,但我不确定是否要引用上面显示的数据。
您将使用Lockbits
and Marshal.Copy
:
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// do something with the array
// Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
注意:代码基本上是来自LockBits
文档页面的示例代码,但代码有一个限制。它假定该Stride
值为正,即图像没有倒置存储在内存中,尽管使用Math.Abs
onStride
值表明编写代码的人知道该Stride
值可能为负。
对于负值Stride
,Scan0
不能用作连续内存块的起始地址,因为它是第一条扫描线的地址。内存块的起始地址将是图像中最后一行的起始地址,而不是第一行。
该地址将是bmpData.Scan0 + bmpData.Stride * (bmp.Height - 1)