2

I have an image that I have created in memory as Format24bppRgb.

I save this as a PNG and it is 24kb.

If I save the same image with photoshop as a 24bit PNG it comes to about the same size, but if i save it as an 8bit PNG with only 32 colors it goes down to 5kb.

How can I create an indexed version of a PNG file using C# / GDI+ / System.Drawing ?

I'm having a hard time finding any answers to this question that don't just apply to grayscale images or require an external library. is it not possible within GDI+ as is?

4

3 回答 3

2

我最终使用了带有 C# 包装器的FreeImageAPI DLL 。我尽量避免使用 3rd 方库,但我认为没有其他选择。它似乎是一个非常标准且使用良好的库。

在我的例子中,我有一个动态创建的System.Drawing.Image对象'image'——我想将它作为压缩图像保存到 HttpContext 输出流中。注意Image没有需要的GetHbitmap()方法,但是Bitmap有。

// convert image to a 'FreeImageAPI' image
var fiBitmap = FreeImageAPI.FreeImageBitmap.FromHbitmap((image as Bitmap).GetHbitmap());
fiBitmap.ConvertColorDepth(FreeImageAPI.FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP);

// see http://stackoverflow.com/questions/582766
MemoryStream ms = new MemoryStream();
fiBitmap.Save(ms, FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_COMPRESSION);
context.HttpContext.Response.OutputStream.Write(ms.ToArray(), 0, (int)ms.Length);

我的 24kb 位图现在只有 9kb :-)

提示:当您运行它时,请确保在您的 bin 中同时提供 'FreeImageNET' 和 'FreeImage' dll。目前,C# 示例项目包含对“Library.DLL”的引用,该引用似乎不存在于其 zip 文件中。使用FreeImageNET.dllFreeImage.dll工作。如果你没有意识到,你会得到一个恼人的文件未找到错误FreeImageNet!= FreeImage

于 2009-04-08T23:46:26.470 回答
1

您可以使用nQuant执行此操作(您可以使用 nuget 安装它,或参见下面的参考资料)。以下示例转换磁盘上的图像,并且很容易适应您的需要。

    public static bool TryNQuantify(string inputFilename, string outputFilename)
    {
        var quantizer = new nQuant.WuQuantizer();
        var bitmap = new Bitmap(inputFilename);
        if (bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        {
            ConvertTo32bppAndDisposeOriginal(ref bitmap);
        }

        try
        {
            using (var quantized = quantizer.QuantizeImage(bitmap))
            {
                quantized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Png);
            }
        }
        catch
        {
            return false;
        }
        finally
        {
            bitmap.Dispose();
        }
        return true;
    }

    private static void ConvertTo32bppAndDisposeOriginal(ref Bitmap img)
    {
        var bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        using (var gr = Graphics.FromImage(bmp))
            gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
        img.Dispose();
        img = bmp;
    }

有关更多信息,请参阅:

于 2015-03-20T02:49:06.647 回答
0

您正在尝试将 16777216 种颜色转换为 32 种颜色。这是一个非常重要的问题,并且有很多方法可以做到这一点,所有这些方法都有其优点和缺点。这不是您经常需要做的事情,尤其是在全彩色显示器变得无处不在之后。

这篇 Microsoft 文章有一些关于 GIF 文件的信息,这些信息也应该与 PNG 相关。

http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q319061

于 2009-04-08T21:45:49.427 回答