将图像转换为灰度

发布于 2024-08-21 18:35:28 字数 309 浏览 11 评论 0原文

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

Bitmap c = new Bitmap("filename");

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

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

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

Is there a way to convert an image to grayscale 16 bits per pixel format, rather than setting each of the r,g and b components to luminance. I currently have a bmp from file.

Bitmap c = new Bitmap("filename");

I want a Bitmap d, that is grayscale version of c. I do see a constructor that includes System.Drawing.Imaging.PixelFormat, but I don't understand how to use that. I'm new to Image Processing and the relevant C# libraries, but have a moderate experience with C# itself.

Any help, reference to an online source, hint or suggestion will be appreciated.

EDIT: d is the grayscale version of c.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

执手闯天涯 2024-08-28 18:35:28

“我想要一个位图d,即灰度图。
我确实看到了一个构造函数,其中包括
系统.绘图.成像.像素格式,
但我不明白如何使用
那个。”

这是如何做到这一点

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 请点击链接进行完整分析:

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;
}

"I want a Bitmap d, that is grayscale.
I do see a consructor that includes
System.Drawing.Imaging.PixelFormat,
but I don't understand how to use
that."

Here is how to do this

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

EDIT: To convert to 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  

Faster Version from switchonthecode follow link for full analysis:

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;
}
貪欢 2024-08-28 18:35:28
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 通道。

享受。

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

This way it also keeps the alpha channel.

Enjoy.

落在眉间の轻吻 2024-08-28 18:35:28

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

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

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

There's a static method in ToolStripRenderer class, named CreateDisabledImage.
Its usage is as simple as:

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

It uses a little bit different matrix than the one in the accepted answer and additionally multiplies it by a transparency of value 0.7, so the effect is slightly different than just grayscale, but if you want to just get your image grayed, it's the simplest and best solution.

东京女 2024-08-28 18:35:28

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

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

The code below is the simplest solution:

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");
扮仙女 2024-08-28 18:35:28

上述示例均未创建 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);

None of the examples above create 8-bit (8bpp) bitmap images. Some software, such as image processing, only supports 8bpp. Unfortunately the MS .NET libraries do not have a solution. The PixelFormat.Format8bppIndexed format looks promising but after a lot of attempts I couldn't get it working.

To create a true 8-bit bitmap file you need to create the proper headers. Ultimately I found the Grayscale library solution for creating 8-bit bitmap (BMP) files. The code is very simple:

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

The code for this project is far from pretty but it works, with one little simple-to-fix problem. The author hard-coded the image resolution to 10x10. Image processing programs do not like this. The fix is open GrayBMP_File.cs (yeah, funky file naming, I know) and replace lines 50 and 51 with the code below. The example sets the resolution to 200x200 but you should change it to the proper number.

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);
独孤求败 2024-08-28 18:35:28

在此总结几项:
有一些逐像素选项虽然简单,但速度不快。

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

他介绍了三个不同的选项,并给出了每个选项的时间安排。

To summarize a few items here:
There are some pixel-by-pixel options that, while being simple just aren't fast.

@Luis' comment linking to: (archived) https://web.archive.org/web/20110827032809/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale is superb.

He runs through three different options and includes timings for each.

遗忘曾经 2024-08-28 18:35:28

我认为在这种情况下这是一个好方法:

    /// <summary>
    /// Change the RGB color to the Grayscale version
    /// </summary>
    /// <param name="color">The source color</param>
    /// <param name="volume">Gray scale volume between -255 - 255</param>
    /// <returns></returns>
    public virtual Color Grayscale(Color color, short volume = 0)
    {
        if (volume == 0) return color;
        var r = color.R;
        var g = color.G;
        var b = color.B;
        var mean = (r + g + b) / 3F;
        var n = volume / 255F;
        var o = 1 - n;
        return Color.FromArgb(color.A, Convert.ToInt32(r * o + mean * n), Convert.ToInt32(g * o + mean * n), Convert.ToInt32(b * o + mean * n));
    }

    public virtual Image Grayscale(Image source, short volume = 0)
    {
        if (volume == 0) return source;
        Bitmap bmp = new Bitmap(source);
        for (int x = 0; x < bmp.Width; x++)
            for (int y = 0; y < bmp.Height; y++)
            {
                Color c = bmp.GetPixel(x, y);
                if (c.A > 0)
                    bmp.SetPixel(x, y, Grayscale(c,volume));
            }
        return bmp;
    }

享受......

I think it's a good way in this case:

    /// <summary>
    /// Change the RGB color to the Grayscale version
    /// </summary>
    /// <param name="color">The source color</param>
    /// <param name="volume">Gray scale volume between -255 - 255</param>
    /// <returns></returns>
    public virtual Color Grayscale(Color color, short volume = 0)
    {
        if (volume == 0) return color;
        var r = color.R;
        var g = color.G;
        var b = color.B;
        var mean = (r + g + b) / 3F;
        var n = volume / 255F;
        var o = 1 - n;
        return Color.FromArgb(color.A, Convert.ToInt32(r * o + mean * n), Convert.ToInt32(g * o + mean * n), Convert.ToInt32(b * o + mean * n));
    }

    public virtual Image Grayscale(Image source, short volume = 0)
    {
        if (volume == 0) return source;
        Bitmap bmp = new Bitmap(source);
        for (int x = 0; x < bmp.Width; x++)
            for (int y = 0; y < bmp.Height; y++)
            {
                Color c = bmp.GetPixel(x, y);
                if (c.A > 0)
                    bmp.SetPixel(x, y, Grayscale(c,volume));
            }
        return bmp;
    }

Enjoy...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文