C#使用不安全的指针绘制图像

时间:2016-07-29 08:41:25

标签: c# pointers bitmap

我尝试使用不安全的指针访问来设置位图中的几个像素(用于提升性能) - 这是我的代码:

 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; - 这就是我每次推进指针的方式......我错过了什么?

我希望我的问题很明确。 提前谢谢。

1 个答案:

答案 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的性能提升。但是,如果您不想设置像素块和/或不将所有像素设置为仅一种固定颜色,那么您的代码将是有意义的。