.net - 在 .NET 中优化 System.Drawing 的 PNG 输出

标签 .net png system.drawing

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。




8年前关闭。




我有一个例程读取图像,调整它的大小并将其定位在新的背景上(全新的位图,只是设置了大小)。

这一切都非常完美,但现在我想减小 PNG 的大小它输出的文件 - 如果我输出 JPEG文件,我得到了大约 4K 左右的文件大小,但我的 PNG 文件大小超过 30K。

我知道我永远无法使用 PNG 达到 JPEG 级别,但我认为我可以做得更好。

当我将输出的 PNG 加载到 Fireworks 中时,我注意到背景和调整大小的图像仍然是单独的图层。在 Fireworks 中展平 PNG 可以将文件大小减少 5 到 10K。

那么,首先有没有办法以编程方式在输出时展平 PNG?

其次,有没有其他人可以推荐减少 PNG 大小?

我正在使用 PNG 文件,因为我希望将背景保留为透明。

代码:

private static void ResizeImage(String ImageInPath, int MaxWidth, int MaxHeight, String ImageOutPath, Boolean PadImage, Color MyColour)
{
    Bitmap MyImage = new Bitmap(ImageInPath);
    Bitmap MyResizedImage = null;

    int XPosition = 0;
    int YPosition = 0;
    float Ratio = MyImage.Width / (float)MyImage.Height;

    int MyImageHeight = MyImage.Height;
    int MyImageWidth = MyImage.Width;

    if (MyImage.Width > MyImage.Height)
    {
        if (MyImage.Width > MaxWidth)
            MyResizedImage = new Bitmap(MyImage, new Size(MaxWidth, (int)Math.Round(MaxWidth /
            Ratio, 0)));
        YPosition = (MaxHeight / 2) - (MyResizedImage.Height / 2);
    }
    else if (MyImage.Height > MyImage.Width)
    {
        if (MyImage.Height > MaxHeight)
            MyResizedImage = new Bitmap(MyImage, new Size((int)Math.Round(MaxWidth * Ratio,
            0), MaxHeight));
        XPosition = (MaxWidth / 2) - (MyResizedImage.Width / 2);
    }


    if (PadImage)
    {
        Bitmap MyUnderlay = new Bitmap(MaxWidth, MaxHeight);
        var Canvas = Graphics.FromImage(MyUnderlay);
        Canvas.Clear(MyColour);
        Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
        Canvas.DrawImage(MyResizedImage, XPosition, YPosition);
        Canvas.Save();
        if (MyColour == Color.Transparent)
        {
            MyUnderlay.Save(ImageOutPath + ".png", ImageFormat.Png);
        }
        else
        {
            MyUnderlay.Save(ImageOutPath, ImageFormat.Jpeg);
        }

        Canvas.Dispose();
        MyUnderlay.Dispose();
    }
    else
    {
        MyResizedImage.Save(ImageOutPath, ImageFormat.Jpeg);
    }

    MyResizedImage.Dispose();
    MyImage.Dispose();
}

最佳答案

super 用户回答,How to read Fireworks PNG multilayer files without Fireworks ,说明 Fireworks 具有 PNG 扩展名,可以在 PNG 文件中存储多个图层。展平会移除多余的图层。鉴于这些文件最初不是在 Fireworks 中创建的,理论上“扁平化”应该对它们没有影响。我怀疑尺寸的减小是由于 Firework 对 PNG 文件进行了保存优化。

我用于 PNG 优化的工具是:

  • 转换为 PNG8 :如果颜色很少(比如截图),那么我使用 pngnqGIMP's索引颜色模式可量化为 256 色。 PNG8 可以小于 PNG24 或 PNG32。详情见PNG8 – The Clear Winner .
  • Optipng ,一个快速的通用 PNG 优化器。 C# PNG Optimization Tutorial有关于如何运行的详细信息 optipng 来自 C#。
  • 最后,pngout很慢,但通常(80-90% 的时间)设法将 PNG 压缩得比 optipng 更进一步。不过首先运行 optipng,因为 optipng 会自动执行 pngout 没有尝试的其他优化。

  • 如果您对优化 PNG 文件感兴趣,请查看 PNG specification出奇的简单,值得一看Smallest possible transparent PNG .和规范一样,实现也出奇的简单,比如单个文件,纯Python实现 png.py (pypng) .

    关于.net - 在 .NET 中优化 System.Drawing 的 PNG 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2075084/

    相关文章:

    c# - Visual Studio 中的安装项目创建的 setup.exe 文件有什么意义吗?

    c - <png.h> 在 mac os X mavericks 中找不到

    Java将GIF图片转PNG格式

    c# - 为字母绘制矩形框

    javascript - .net mvc 5 不引人注目的禁用字段验证

    c# - 在模块 CommonLanguageRuntimeLibrary 中找不到类型 System.ApplicationException

    具有透明背景的PHP图像复制

    c# - 在 C# 中调整大小和水印图像

    c# - 无法使用 GetManifestResourceStream 找到嵌入式资源

    c# - 使用 .NET + Linq 创建项目列表时是否可以使用匿名方法?