2011-10-14 25 views
3

我试图用Lockbits写出来的灰度图像,我当前的代码看起来是使用LockBits产生怪异的图像

/// <summary> 
/// Save the content of the FrameProc out to a bitmap 
/// </summary> 
public void Save(string path) 
{ 
    Bitmap bmp = new Bitmap(this.size.Width, this.size.Height 
          ,PixelFormat.Format32bppRgb); 
    var data = bmp.LockBits(this.size, ImageLockMode.WriteOnly, bmp.PixelFormat); 

    unsafe 
    { 
     for (int y = 0; y < this.size.Height; y++) 
     { 
      byte* row = (byte*)data.Scan0 + (y * data.Stride); 
      for (int x = 0; x < this.size.Width; x++) 
      { 
       byte value = (byte)this.buffer[y, x]; 
       row[x*Bits+r] = value; 
       row[x*Bits+g] = value; 
       row[x*Bits+b] = value; 
      } 
     } 
    } 

    bmp.UnlockBits(data); 
    bmp.Save(path, ImageFormat.Bmp); 
} 

其中

/// <summary> 
/// The amount of Bytes per pixel in the image 
/// </summary> 
private const int Bits = 4; 

/// <summary> 
/// Image components 
/// </summary> 
private const int a=3, r = 2, g = 1, b = 0; 

但是我收到的图像是不正确的:

Broken image http://i52.tinypic.com/2e4vsxz.jpg

也许这是关系到如何我读把他们介入?因此,这里的代码

public FrameProc(Bitmap bmp) 
    { 
     this.size=new Rectangle(new Point(0,0), bmp.Size); 
     var data = bmp.LockBits(this.size 
           ,ImageLockMode.ReadOnly 
           ,bmp.PixelFormat); 
     this.buffer = new Matrix(this.size.Height, this.size.Width); 

     unsafe 
     { 
      for (int y = 0; y < this.size.Height; y++) 
      { 
       byte* row = (byte*)data.Scan0 + (y * data.Stride); 
       for (int x = 0; x < this.size.Width; x++) 
       { 
        this.buffer[y,x] = 0.299*row[x*Bytes+r] 
            + 0.587*row[x*Bytes+g] 
            + 0.114*row[x*Bytes+b]; 
       } 
      } 
     } 

     bmp.UnlockBits(data); 
    } 
+1

我不确定你选择的图片是否适合每个人的口味。 – spender

回答

4

从你得到的结果采取 - 它看起来正好好像每个像素是三个字节大,而不是四个,因为你已经宣布它 - 并如人们所期望的。 (注意:你称之为位 - 但这是错误的 - 它应该是名字,而不是位)。

我实验的这任一个:

  • 变化从4到3个字节从Format32bppRgb
  • 变化Format32bppArgb并填写阿尔法4到3字节255
  • 变化从Format32bppRgb从Format24bppRgb

我还要重写循环略有性能(对不起,我不能帮助自己):

for (int x = 0; x < this.size.Width; x++, row += Bits) 
       { 
        byte value = (byte)this.buffer[y, x]; 
        row[r] = value; 
        row[g] = value; 
        row[b] = value; 
       } 

但是你真的会得到更多的速度,如果你得到一个指向this.buffer使用fixed关键字。是的,你没有任何性能问题,但我不能提起它!

+0

该循环会一次跳过3个字节,图像最终会出现漏洞。行比this.buffer大3倍,因为缓存只保存Y并且排列RGBx值。 – Phyx

+0

是的 - 你增加行INSTEAD在每一轮执行不必要的x *位乘法。相信我,我做图像处理和.LockBita *很多*。但我从来没有使用Format32bppRgb格式。 –

+0

哦对,我看到了行+ =位为x + =位, – Phyx

1

使用此功能确实:

public Bitmap MakeGrayscale(Bitmap original) 
{ 
    unsafe 
    { 
     //create an empty bitmap the same size as original 
     Bitmap newBitmap = new Bitmap(original.Width, original.Height); 

     //lock the original bitmap in memory 
     BitmapData originalData = original.LockBits(
     new Rectangle(0, 0, original.Width, original.Height), 
     ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 

     //lock the new bitmap in memory 
     BitmapData newData = newBitmap.LockBits(
     new Rectangle(0, 0, original.Width, original.Height), 
     ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 

     //set the number of bytes per pixel 
     // here is set to 3 because I use an Image with 24bpp 
     int pixelSize = 3; 

     for (int y = 0; y < original.Height; y++) 
     { 
     //get the data from the original image 
     byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride); 

     //get the data from the new image 
     byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride); 

     for (int x = 0; x < original.Width; x++) 
     { 
      //create the grayscale version 
      byte grayScale = 
       (byte)((oRow[x * pixelSize] * .11) + //B 
       (oRow[x * pixelSize + 1] * .59) + //G 
       (oRow[x * pixelSize + 2] * .3)); //R 

      //set the new image's pixel to the grayscale version 
      nRow[x * pixelSize] = grayScale; //B 
      nRow[x * pixelSize + 1] = grayScale; //G 
      nRow[x * pixelSize + 2] = grayScale; //R 
     } 
     } 

     //unlock the bitmaps 
     newBitmap.UnlockBits(newData); 
     original.UnlockBits(originalData); 

     return newBitmap; 
    } 
} 

来源和其他有趣的例子(与理论背后)可以从here

+0

我试图做的实际操作不仅仅是将图像转换为灰度。我正在对图像的字节进行图像处理,其中转换为灰度仅仅是第一步。所以我确实需要做ColorMatrix无法覆盖的操作。 – Phyx

+0

@Phyx:在链接上,我在回答中发布了一个函数_MakeGrayScale_,使用'LockBits':看看这个。 – Marco

+0

@Phyx:我刚刚编辑我的答案写在该链接中找到的功能 – Marco