61

有没有办法将图像转换为每像素 16 位的灰度格式,而不是将 r、g 和 b 分量中的每一个都设置为亮度。我目前有一个来自文件的 bmp。

Bitmap c = new Bitmap("filename");

我想要一个 Bitmap d,即 c 的灰度版本。我确实看到了一个包含 System.Drawing.Imaging.PixelFormat 的构造函数,但我不明白如何使用它。我是图像处理和相关 C# 库的新手,但对 C# 本身有一定的经验。

任何帮助、参考在线资源、提示或建议将不胜感激。

编辑:d 是 c 的灰度版本。

4

6 回答 6

81

“我想要一个 Bitmap d,即灰度。我确实看到了一个包含 System.Drawing.Imaging.PixelFormat 的构造函数,但我不明白如何使用它。”

这是如何做到这一点

Bitmap grayScaleBP = new 
         System.Drawing.Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);

编辑:转换为灰度

             Bitmap c = new Bitmap("fromFile");
             Bitmap d;
             int x, y;

             // Loop through the images pixels to reset color.
             for (x = 0; x < c.Width; x++)
             {
                 for (y = 0; y < c.Height; y++)
                 {
                     Color pixelColor = c.GetPixel(x, y);
                     Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
                     c.SetPixel(x, y, newColor); // Now greyscale
                 }
             }
            d = c;   // d is grayscale version of c  

来自switchonthecode的Faster Version跟随链接进行全面分析:

public static Bitmap MakeGrayscale3(Bitmap original)
{
   //create a blank bitmap the same size as original
   Bitmap newBitmap = new Bitmap(original.Width, original.Height);

   //get a graphics object from the new image
   using(Graphics g = Graphics.FromImage(newBitmap)){

       //create the grayscale ColorMatrix
       ColorMatrix colorMatrix = new ColorMatrix(
          new float[][] 
          {
             new float[] {.3f, .3f, .3f, 0, 0},
             new float[] {.59f, .59f, .59f, 0, 0},
             new float[] {.11f, .11f, .11f, 0, 0},
             new float[] {0, 0, 0, 1, 0},
             new float[] {0, 0, 0, 0, 1}
          });

       //create some image attributes
       using(ImageAttributes attributes = new ImageAttributes()){

           //set the color matrix attribute
           attributes.SetColorMatrix(colorMatrix);

           //draw the original image on the new image
           //using the grayscale color matrix
           g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                       0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
       }
   }
   return newBitmap;
}
于 2010-02-15T12:50:51.307 回答
37
Bitmap d = new Bitmap(c.Width, c.Height);

for (int i = 0; i < c.Width; i++)
{
    for (int x = 0; x < c.Height; x++)
    {
        Color oc = c.GetPixel(i, x);
        int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
        Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
        d.SetPixel(i, x, nc);
    }
}

这样它还保留了 Alpha 通道。
享受。

于 2010-10-23T14:44:50.953 回答
29

类中有一个静态方法ToolStripRenderer,名为CreateDisabledImage. 它的用法很简单:

Bitmap c = new Bitmap("filename");
Image d = ToolStripRenderer.CreateDisabledImage(c);

它使用的矩阵与接受的答案中的矩阵略有不同,并将其乘以透明度值 0.7,因此效果与灰度略有不同,但如果您只想让图像变灰,这是最简单的最佳解决方案。

于 2015-09-29T12:21:45.213 回答
8

下面的代码是最简单的解决方案:

Bitmap bt = new Bitmap("imageFilePath");

for (int y = 0; y < bt.Height; y++)
{
    for (int x = 0; x < bt.Width; x++)
    {
        Color c = bt.GetPixel(x, y);

        int r = c.R;
        int g = c.G;
        int b = c.B;
        int avg = (r + g + b) / 3;
        bt.SetPixel(x, y, Color.FromArgb(avg,avg,avg));
    }   
}

bt.Save("d:\\out.bmp");
于 2015-01-22T16:21:10.137 回答
7

上述示例均未创建 8 位 (8bpp) 位图图像。有些软件,比如图像处理,只支持8bpp。不幸的是,MS .NET 库没有解决方案。PixelFormat.Format8bppIndexed格式看起来很有希望,但经过多次尝试后我无法让它工作。

要创建真正的 8 位位图文件,您需要创建正确的标题。最终,我找到了用于创建 8 位位图 (BMP) 文件的灰度库解决方案。代码非常简单:

Image image = Image.FromFile("c:/path/to/image.jpg");
GrayBMP_File.CreateGrayBitmapFile(image, "c:/path/to/8bpp/image.bmp");

这个项目的代码远非漂亮,但它可以工作,有一个小问题很容易解决。作者将图像分辨率硬编码为 10x10。图像处理程序不喜欢这样。修复方法是打开 GrayBMP_File.cs(是的,我知道时髦的文件命名)并用下面的代码替换第 50 行和第 51 行。该示例将分辨率设置为 200x200,但您应该将其更改为正确的数字。

int resX = 200;
int resY = 200;
// horizontal resolution
Copy_to_Index(DIB_header, BitConverter.GetBytes(resX * 100), 24);
// vertical resolution 
Copy_to_Index(DIB_header, BitConverter.GetBytes(resY * 100), 28);
于 2011-04-23T14:53:47.100 回答
6

在这里总结一些项目:有一些逐像素的选项,虽然很简单,但速度并不快。

@Luis 的评论链接到:(存档)https://web.archive.org/web/20110827032809/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-灰度是一流的。

他遍历了三个不同的选项,并包括了每个选项的时间。

于 2011-08-16T22:22:07.917 回答