我正试图使用C#将32 8bpp的屏幕截图图像转换为8bpp(或4bpp或1bpp)格式。我已经看过关于类似主题的几个堆栈溢出答案,并且大多数建议使用以下代码进行更改:
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 BitBlt和GetDIBits等。有谁能帮我解决这个问题呢?谢谢。
编辑:我应该指出,我需要向后兼容.NET框架2.0
发布于 2011-06-15 10:10:17
一般来说,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像素格式,由编码器计算调色板条目。如果有必要,可以将其转换为位图。到目前为止,最好的做法就是不使用索引格式。它们可以追溯到计算的石器时代,当时内存受到严重限制。或者使用专业的图形编辑器。
发布于 2016-03-11 14:13:04
AForge库正在使用灰度完美地完成它。
var bmp8bpp = Grayscale.CommonAlgorithms.BT709.Apply(bmp);这个类是图像灰度缩放的基类.该滤波器接受24、32、48和64 bpp彩色图像,并产生8 (if源为24或32 bpp图像)或16 (如果源为48或64 bpp图像) bpp灰度图像。
发布于 2011-09-01 19:37:27
负步幅表示图像是自下而上(倒置).如果你不在乎的话,就用绝对的步幅。我知道这适用于24bpp图像,不知道它是否适用于其他人。
https://stackoverflow.com/questions/6355135
复制相似问题