我尝试使用不安全的指针访问来设置位图中的几个像素(用于提升性能) - 这是我的代码:
private unsafe void DrawImage(Bitmap bmp1)
{
BitmapData bmData = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp1.PixelFormat);
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
int x = 200;
int y = 400;
for (; y < 600; y++) {
byte * p = (byte * ) scan0.ToPointer();
p += y * stride + x * 4;
for (; x < 900; x++) {
p[0] = 0; //blue
p[1] = 0; //green
p[2] = 255; //red
p += 4;
}
}
bmp1.UnlockBits(bmData);
}
如你所见,我试图将一个块(红色)从 y = 400 设置为 y = 600 ,并且 x = 200 至 x = 900 。
在外循环的每次交互中,我将指针前进到所需的地址,但我只得到一个&#34; thin&#34;红色像素的水平线...这表明y
地址有问题。我无法理解。
p += y * stride + x * 4;
- 这就是我每次推进指针的方式......我错过了什么?
我希望我的问题很明确。 提前谢谢。
答案 0 :(得分:1)
循环中的快捷方式不能很好地结合在一起。至少内循环需要适当的起始值。最好设置起始值和结束值;很可能你以后想要去一个矩形..
此外,正如Hans所说,你应该确保查看实际PixelFormat
的像素宽度。
最后循环进展不正确。
这应该有效:
private unsafe void DrawImage(Bitmap bmp1)
{
BitmapData bmData = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp1.PixelFormat);
// this is only a rather incomplete test, of course:
int pixWidth = bmp1.PixelFormat == PixelFormat.Format24bppRgb ? 3 :
bmp1.PixelFormat == PixelFormat.Format32bppArgb ? 4 : 4;
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
int x0 = 100;
int y0 = 100;
int x1 = 200;
int y1 = 300;
byte* p = (byte*)scan0.ToPointer() + y0 * stride;
for (int y = y0; y < y1; y++)
{
p += stride;
int px = x0 * pixWidth;
for (int x = x0; x < x1; x++)
{
px += pixWidth;
p[px + 0] = 0; //blue
p[px + 1] = 0; //green
p[px + 2] = 255; //red
}
}
bmp1.UnlockBits(bmData);
}
如上所述,这并不是对GDI + FillRectangle
的性能提升。但是,如果您不想设置像素块和/或不将所有像素设置为仅一种固定颜色,那么您的代码将是有意义的。