【问题标题】:convert 8 bit color bmp image to 8 bit grayscale bmp将 8 位彩色 bmp 图像转换为 8 位灰度 bmp
【发布时间】:2011-12-18 20:09:22
【问题描述】:

这是我的位图对象

Bitmap b = new Bitmap(columns, rows, PixelFormat.Format8bppIndexed);
BitmapData bmd = b.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadWrite, b.PixelFormat);

如何将其转换为 8 位灰度位图?

【问题讨论】:

  • 你为什么使用LockBits
  • 不要忘记将其中一个答案标记为已接受,然后查看适合您的答案。虽然所有答案都基本相同

标签: c# bitmap


【解决方案1】:

是的,无需更改像素,只需调色板即可。 ColorPalette 是一种片状类型,此示例代码运行良好:

        var bmp = Image.FromFile("c:/temp/8bpp.bmp");
        if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed) throw new InvalidOperationException();
        var newPalette = bmp.Palette;
        for (int index = 0; index < bmp.Palette.Entries.Length; ++index) {
            var entry = bmp.Palette.Entries[index];
            var gray = (int)(0.30 * entry.R + 0.59 * entry.G + 0.11 * entry.B);
            newPalette.Entries[index] = Color.FromArgb(gray, gray, gray);
        }
        bmp.Palette = newPalette;    // Yes, assignment to self is intended
        if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
        pictureBox1.Image = bmp;

我实际上不建议您使用此代码,索引像素格式是一个需要处理的 pita。您会在this answer 中找到快速且更通用的彩色到灰度转换。

【讨论】:

  • 8 位调色板条目是否始终相同?我认为您可以使用优化的图像来优化图像。如果它相同,只有我可以使用 var gray = (int)(0.30 * entry.R + 0.59 * entry.G + 0.11 * entry.B);对吗?
  • 仅当您需要将 24bpp 图像转换为 8bpp 图像时,才需要优化调色板。这需要将 1600 万种可能的颜色映射到仅 256 种可用颜色。这不是你要求的。
  • 这意味着 C# 在创建 8 位图像时总是使用默认调色板?
  • 是的,当您从头开始创建一个新的 8bpp 位图时,GDI+ 会创建一个默认调色板。实际上很少这样做,对于具有索引像素格式之一的位图,您无能为力。你无法融入其中。绘画程序是 8bpp 位图的典型来源。
  • 正如代码注释所说,这实际上不是“对自我的分配”。调色板的getter创建了一个新对象,这就是为什么最后这个赋值是必要的,为什么调色板不能直接用bmp.Palette.Entries[index] = value;编辑。
【解决方案2】:

类似:

Bitmap b = new Bitmap(columns, rows, PixelFormat.Format8bppIndexed);
for (int i = 0; i < columns; i++)
{
   for (int x = 0; x < rows; x++)
    {
       Color oc = b.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);
       b.SetPixel(i, x, nc);
  }
}
BitmapData bmd = b.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadWrite, b.PixelFormat);

【讨论】:

  • 这样就够了吗?您不需要更改颜色表吗?因为修改后的位图数据仍将使用相同的颜色表?
  • SetPixel 甚至可以处理索引图像吗?它们的索引是像素值,而不是颜色。
【解决方案3】:

您好,您可以将调色板更改为灰度调色板

虽然下面的代码在 Vb.net 中。您可以轻松地将其转换为 C#

Private Function GetGrayScalePalette() As ColorPalette  
    Dim bmp As Bitmap = New Bitmap(1, 1, Imaging.PixelFormat.Format8bppIndexed)  

    Dim monoPalette As ColorPalette = bmp.Palette  

    Dim entries() As Color = monoPalette.Entries  

    Dim i As Integer 
    For i = 0 To 256 - 1 Step i + 1  
        entries(i) = Color.FromArgb(i, i, i)  
    Next 

    Return monoPalette  
End Function 

原文出处 -> http://social.msdn.microsoft.com/Forums/en-us/vblanguage/thread/500f7827-06cf-4646-a4a1-e075c16bbb38

【讨论】:

  • 除非原始图像的调色板奇迹般地已经按亮度排序,否则将这个调色板分配给图像会完全搞砸。
【解决方案4】:

请注意,如果您想进行与现代 HDTV 相同的转换,则需要使用 Rec. 709 个系数进行转换。上面提供的(.3、.59、.11)是(几乎)Rec。 601(标准定义)系数。推荐。 709 个系数是灰色 = 0.2126 R' + 0.7152 G' + 0.0722 B',其中 R'、G' 和 B' 是经过伽马调整的红色、绿色和蓝色分量。

【讨论】:

    【解决方案5】:

    检查此link。我们在大学里做过这个,而且效果很好。

    这就是你所需要的输入和输出。

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 2017-01-17
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-07
      • 2016-06-18
      • 2020-03-21
      相关资源
      最近更新 更多