首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用LockBits生成奇怪的图像

使用LockBits生成奇怪的图像
EN

Stack Overflow用户
提问于 2011-10-14 17:00:22
回答 2查看 2.8K关注 0票数 3

我正在尝试写出一个灰度图像使用Lockbits,我目前的代码看起来是

代码语言:javascript
复制
/// <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);
}

哪里

代码语言:javascript
复制
/// <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;

然而,我收到的图像不正确:

也许这与我是如何解读它们有关的?下面是代码

代码语言:javascript
复制
    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);
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-14 17:24:51

从你得到的结果来看,每个像素看起来就像是三个字节,而不是你所说的四个字节--正如人们所预期的那样。(注意:您称它为Bits -但这是错误的-它应该被命名为Bytes,而不是Bits)。

我会用其中的任何一个做实验:

  • 从4个字节更改为3个字节
  • 从Format32bppRgb更改为Format32bppArgb并用255填充字母
  • 从4个字节更改为3个字节,从Format32bppRgb更改为from alpha

为了提高性能,我还会稍微重写一下循环(对不起,我控制不住自己):

代码语言:javascript
复制
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关键字获得一个指向固定的指针,你会得到更快的速度。是的,您没有任何性能问题,但我忍不住要提一下!

票数 4
EN

Stack Overflow用户

发布于 2011-10-14 17:02:56

确实要使用这个函数:

代码语言:javascript
复制
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获取

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7765294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档