4

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

这一切都非常完美,但现在我想减小它输出的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();
}
4

1 回答 1

8

超级用户的回答,如何在没有 Fireworks 的情况下读取 Fireworks PNG 多层文件,解释说 Fireworks 具有 PNG 扩展名,可以在 PNG 文件中存储多个层。展平会移除多余的图层。鉴于文件最初不是在 Fireworks 中创建的,理论上“展平”应该对它们没有影响。我怀疑大小的减小是由于 Firework 的保存优化 PNG 文件。

我用于 PNG 优化的工具是:

  1. 转换为PNG8:如果颜色很少(比如屏幕截图),那么我使用pngnqGIMP 的索引颜色模式来量化到 256 种颜色。PNG8 可以小于 PNG24 或 PNG32。有关详细信息,请参阅PNG8 - 明显的赢家
  2. Optipng,一个快速的通用 PNG 优化器。C# PNG 优化教程详细介绍了如何从 C#运行optipng 。
  3. 最后,pngout很慢,但通常(80-90% 的时间)会比 optipng 进一步压缩 PNG。不过首先运行 optipng,因为 optipng 会自动执行 pngout 不会尝试的其他优化。

如果您对优化 PNG 文件感兴趣,那么PNG 规范非常简单,值得一看Smallest possible transparent PNG。与规范一样,实现也非常简单,例如,单个文件,纯Python实现png.py (pypng)

于 2010-01-15T22:24:16.520 回答