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

本文关键字:指针 绘制 图像 不安全 | 更新日期: 2023-09-27 17:59:14

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

 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。在外循环的每次交互中,我都会将指针前进到所需的地址,但我只得到一条由红色像素组成的"细"水平线。。。这表明CCD_ 1地址有问题。。我不明白为什么。 p += y * stride + x * 4;-这就是我每次推进指针的方式。。。我错过什么了吗?

我希望我的问题很清楚。提前谢谢。

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

  • 循环中的快捷方式不能很好地结合在一起。至少内部循环需要一个合适的起始值。最好同时设置起始值和结束值;很可能你以后会想要一个矩形。。

  • 此外,正如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相比,这并不是真正的性能提升。但是,如果你不想设置一个像素块和/或不想将所有像素都设置为一种固定的颜色,你的代码将是有意义的。。