繁体   English   中英

C#将32bpp图像转换为8bpp

[英]C# Converting 32bpp image to 8bpp

我正在尝试使用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向后兼容

通常,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像素格式,其中调色板项由编码器计算。 您可以根据需要将其强制转换为Bitmap。 到目前为止,最好的办法就是根本不用去理会索引格式。 它们可以追溯到计算的石器时代,当时内存受到严重限制。 或使用专业的图形编辑器。

AForge库使用Grayscale完美地做到了。

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

此类是图像灰度缩放的基础类。过滤器接受24、32、48和64 bpp彩色图像,并产生8(如果源是24或32 bpp图像)或16(如果源是48或64 bpp)图片)bpp灰度图片。

负的步幅表示图像自下而上(反转)。 如果您不在乎,请使用步幅的绝对值。 我知道这适用于24bpp图像,不知道它是否适用于其他人。

您可以使用System.Windows.Media.Imaging在PresentationCore大会看一看这里了解更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM