【问题标题】:C# Converting 32bpp image to 8bppC# 将 32bpp 图像转换为 8bpp
【发布时间】:2011-09-15 08:33:16
【问题描述】:

我正在尝试使用 C# 将 32bpp 屏幕截图图像转换为 8bpp(或 4bpp 或 1bpp)格式。我已经看过几个关于类似主题的 stackoverflow 答案,并且大多数建议使用以下代码进行变体:

public static Bitmap Convert(Bitmap oldbmp) 
{
    Bitmap newbmp = new Bitmap(oldbmp.Width, oldbmp.Height, PixelFormat.Format8bppIndexed);

    Graphics gr = Graphics.FromImage(newbmp);

    gr.PageUnit = GraphicsUnit.Pixel;
    gr.DrawImageUnscaled(oldbmp, 0, 0);

    return newbmp;
}

但是,当它执行时,我得到一个异常:A graphics object cannot be created from an image that has an indexed pixel format。我知道 8、4 和 1bpp 图像具有颜色表映射,而不是实际颜色像素本身(如 32 或 16bpp 图像)所以我假设我在某处缺少一些转换步骤,但我对 C# 相当陌生(即将到来来自 C++ 背景)并且希望能够使用本机 C# 调用而不是诉诸 PInvoking BitBltGetDIBits 等。有人能帮我解决这个问题吗?谢谢。

编辑:我应该指出我需要它向后兼容 .NET framework 2.0

【问题讨论】:

    标签: c# .net windows image


    【解决方案1】:

    AForge 库正在使用 Grayscale 完美地完成它。

    var bmp8bpp = Grayscale.CommonAlgorithms.BT709.Apply(bmp);
    

    这个类是图像灰度的基类 [...] 该过滤器接受 24、32、48 和 64 bpp 彩色图像并产生 8 (如果源是 24 或 32 bpp 图像)或 16(如果源是 48 或 64 bpp image) bpp 灰度图。

    【讨论】:

    • 谢谢!无论如何,我需要为 AForge 的 Canny 边缘检测器执行此操作;不知道它是内置的:)
    【解决方案2】:

    GDI+ 通常对索引像素格式的支持很差。没有简单的方法可以将具有 65536 或 1600 万种颜色的图像转换为只有 2、16 或 256 种颜色的图像。必须从源图像中删除颜色,这是一种有损转换,可能会产生非常糟糕的结果。有多种算法可以实现这一点,但没有一种算法适合每一种图像。这是图形编辑器的工作。

    我发现了一个技巧。 GDI+ 有一个用于 GIF 文件的图像编码器。这是一种只有 256 种颜色的图形格式,编码器必须限制颜色的数量。它使用适用于照片的抖动算法。它确实具有生成网格图案的诀窍,当它这样做时,您不会感到兴奋。像这样使用它:

    public static Image Convert(Bitmap oldbmp) {
        using (var ms = new MemoryStream()) {
            oldbmp.Save(ms, ImageFormat.Gif);
            ms.Position = 0;
            return Image.FromStream(ms);
        }
    }
    

    返回的图像具有 8bpp 像素格式,其中调色板条目由编码器计算。如有必要,您可以将其转换为位图。到目前为止,最好的办法就是不要理会索引格式。它们可以追溯到计算的石器时代,当时内存受到严重限制。或者使用专业的图形编辑器。

    【讨论】:

    • 太好了,谢谢。顺便说一句,wischik.com/lu/programmer/1bpp.html 的代码还描述了一种实现我想要的方法,尽管有一定程度的 PInvoke。
    • 这样做你会得到一个非常低质量的结果(gif 技巧)。我认为最好的解决方案是使用 EmguCV(opencv 包装器)。
    • " 到目前为止,最好的办法就是不要理会索引格式。它们可以追溯到计算的石器时代,当时内存受到严重限制" 这一切都很好,但是当你'重新编写程序以处理视频内存仍然非常宝贵的手持控制台或智能手表等目标的图形?
    • 您不必担心,GDI+ 在此类设备上不可用。
    【解决方案3】:

    负步幅表示图像是自下而上(倒置)。如果您不在乎,只需使用绝对步幅即可。我知道它适用于 24bpp 图像,不知道它是否适用于其他图像。

    【讨论】:

      【解决方案4】:

      您可以在 PresentationCore Assembly 中使用 System.Windows.Media.Imaging,查看here 了解更多信息

      【讨论】:

      猜你喜欢
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 2010-10-09
      • 2013-02-10
      • 2019-12-03
      • 2016-05-18
      • 2012-10-19
      相关资源
      最近更新 更多