开发者

Optimising PNG output from System.Drawing in .NET [closed]

开发者 https://www.devze.com 2022-12-17 16:36 出处:网络
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references,or expertise, but this question will likely solicit debate, a
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. Closed 9 years ago.

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();
    }
    els开发者_如何学Pythone
    {
        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).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号