在.NET优化PNG输出System.Drawing中 [英] Optimising PNG output from System.Drawing in .NET

查看:179
本文介绍了在.NET优化PNG输出System.Drawing中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有个常规读取图像中的,调整其大小和上一个新的背景定位它(品牌新的位图,只是大小设置)。

这一切工作万无一失了,但我现在想减少的 PNG 大小文件它输出 - 如果我的输出 JPEG 文件,我得到我期望〜4K左右的文件大小,但我的PNG文件超过30K的大小。

我知道,我将永远不会为JPEG的水平与PNG,但我想我可以做的更好一点。

当我加载PNG图像输出到烟花,我注意到背景和调整后的图像还是单独层。一个良好的5〜10K压扁在Fireworks中PNG减少文件大小。

所以,第一是有没有办法以编程方式扁平化PNG输出?

其次,还有什么人可以推荐,以减少PNG大小?

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

code:

 私有静态无效ResizeImage(字符串ImageInPath,诠释了maxWidth,诠释了maxHeight,字符串ImageOutPath,布尔PadImage,颜色MyColour)
{
    位图MYIMAGE =新位图(ImageInPath);
    位图MyResizedImage = NULL;

    INT xPosition位置= 0;
    INT YPosition = 0;
    浮动比率= MyImage.Width /(浮点)MyImage.Height;

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

    如果(MyImage.Width> MyImage.Height)
    {
        如果(MyImage.Width>了maxWidth)
            MyResizedImage =新位图(MYIMAGE,新的大小(了maxWidth,(INT)Math.Round(了maxWidth /
            比,0)));
        YPosition =(了maxHeight / 2) - (MyResizedImage.Height / 2);
    }
    否则,如果(MyImage.Height> MyImage.Width)
    {
        如果(MyImage.Height>了maxHeight)
            MyResizedImage =新位图(MYIMAGE,新的大小((INT)Math.Round(*了maxWidth比例,
            0),了maxHeight));
        xPosition位置=(了maxWidth / 2) - (MyResizedImage.Width / 2);
    }


    如果(PadImage)
    {
        位图MyUnderlay =新位图(了maxWidth,了maxHeight);
        VAR帆布= Graphics.FromImage(MyUnderlay);
        Canvas.Clear(MyColour);
        Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
        Canvas.DrawImage(MyResizedImage xPosition位置,YPosition);
        Canvas.Save();
        如果(MyColour == Color.Transparent)
        {
            MyUnderlay.Save(ImageOutPath +巴纽,ImageFormat.Png);
        }
        其他
        {
            MyUnderlay.Save(ImageOutPath,ImageFormat.Jpeg);
        }

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

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

解决方案

超级用户答案的​​ <一个href="http://superuser.com/questions/50044/how-to-read-fireworks-png-multilayer-files-without-fireworks/50068#50068">How看烟花PNG多层文件,而烟花 的解释说,烟花爆竹具有PNG扩展存储多个图层的PNG文件。拼合删除多余的层。由于这些文件未在Fireworks中首先创建的,在理论上扁平化应该对他们没有影响。我怀疑在尺寸的减小是由于烟花的保存 - 优化PNG文件。

我使用PNG优化的工具有:

  1. 转换为 PNG8 :如果有几个颜色(例如,截屏),那么我使用 pngnq 或的 GIMP的索引色模式,以量化到256色。 PNG8可以比PNG24或PNG32小。有关详细信息,请参阅 PNG8 - 明显的赢家
  2. Optipng ,快速一般PNG优化。 C#PNG优化教程对如何运行的详细信息 optipng 从C#。
  3. 最后, PNGOUT 是缓慢的,但往往(时间80-90%)设法下跌进一步挤压PNG比optipng。 optipng首先运行虽然,因为optipng会自动做PNGOUT不会尝试其他的优化​​。

如果您有兴趣在优化PNG文件时, PNG规范是出奇的简单,这是值得考虑看看尽可能小的透明PNG 。像规范,实现方式也非常简单,举个例子,单个文件,纯 Python的实施 png.py (pypng)

I have a routine which reads in an image, resizes it and positions it on a new background (brand new bitmap, just the size is set).

This all works absolutely perfectly, but now I would like to reduce the size of the PNG files it outputs - if I output JPEG files, I get the ~4K or so file size I expect, but my PNG files are more than 30K in size.

I know that I will never get to JPEG levels with PNG, but I think I can do a bit better.

When I load the outputted PNGs into Fireworks, I note that the background and the resized image are still seperate layers. Flattening the PNG in Fireworks reduces the filesize by a good 5 to 10K.

So, firstly is there a way to programmatically flatten the PNG on output?

Secondly, is there anything else anyone can recommend to reduce the PNG size?

I am using PNG files, because I wish to retain the background as transparent.

Code:

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();
}

解决方案

The Super User answer, How to read Fireworks PNG multilayer files without Fireworks, explains that Fireworks has PNG extensions to store multiple layers in a PNG file. Flattening removes the extra layers. Given that the files were not created in Fireworks in the first place, in theory "flattening" should have no effect on them. I suspect the reduction in size is due to Firework's save-optimize the PNG file.

The tools I use for PNG optimization are:

  1. Convert to PNG8: If there are few colors (say, screenshots) then I use pngnq or GIMP's Indexed color mode to quantize down to 256 colors. PNG8 can be smaller than PNG24 or PNG32. For details see PNG8 – The Clear Winner.
  2. Optipng, a fast general PNG optimizer. C# PNG Optimization Tutorial has details on how to run optipng from C#.
  3. Finally, pngout is slow but often (80-90% of the time) manages to squeeze the PNG down further than optipng. Run optipng first though, as optipng will automatically do other optimizations that pngout does not attempt.

If you are interested in optimizing PNG files, the PNG specification is surprisingly straightforward, and it is worth taking a look at Smallest possible transparent PNG. Like the specification, implementations are also surprisingly simple, take for example, the single file, pure Python implementation png.py (pypng).

这篇关于在.NET优化PNG输出System.Drawing中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆