首页 文章

将图像转换为灰度

提问于
浏览
51

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

Bitmap c = new Bitmap("filename");

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

任何帮助,参考在线来源,提示或建议将不胜感激 .

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

6 回答

  • 6

    总结一下这里的几个项目:有一些逐像素的选项,虽然简单但不快 .

    @Luis'评论链接到:(已存档)https://web.archive.org/web/20110827032809/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale非常棒 .

    他经历了三种不同的选择,包括每种选择的时间 .

  • 6

    “我想要一个位图d,即灰度 . 我确实看到一个包含System.Drawing.Imaging.PixelFormat的consructor,但我不明白如何使用它 . ”

    这是怎么做的

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

    EDIT: 转换为 grayscale

    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的更快版本关注链接以进行全面分析:

    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
       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
       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);
    
       //dispose the Graphics object
       g.Dispose();
       return newBitmap;
    }
    
  • 63
    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通道 .
    请享用 .

  • 14

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

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

    它使用与接受答案中的矩阵稍微不同的矩阵,并且还将其乘以0.7的透明度,因此效果与仅灰度略有不同,但如果您想让图像变灰,那么它是最简单的最佳方案 .

  • 4

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

    要创建真正的8位位图文件,您需要创建proper headers . 最终我找到了用于创建8位位图(BMP)文件的Grayscale library解决方案 . 代码很简单:

    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);
    
  • 31

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

    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");
    

相关问题