.NET Forum / Windows Forms / Drawing / January 2008
Any way to set PNG compression level?
|
|
Thread rating:  |
Dave Huang - 05 Jan 2008 03:42 GMT Hi, using Image.Save(filename, ImageFormat.Png) gives me a working PNG file, but it seems bigger than it needs to be. Is there a way to configure the compression level? I looked into EncoderParameters, but didn't spot anything that sounded like compression level. Encoder.Compression seems to be for selecting a compression algorithm for TIFFs. Encoder.Quality seems to be for adjusting the "lossiness" of JPEGs.
So, is there no way to control the compression level for PNGs using something that comes with the .NET class library?
Industrial One - 05 Jan 2008 06:22 GMT > Hi, using Image.Save(filename, ImageFormat.Png) gives me a working PNG > file, but it seems bigger than it needs to be. Is there a way to [quoted text clipped - 6 lines] > So, is there no way to control thecompressionlevel for PNGs using > something that comes with the .NET class library? PNG is lossless so there really is no "level." But it depends on what you're trying to compress. If it's linear content like a Windows screenshot, save it as 256 color or 16 color BMP (if some loss in color is tolerable) and save THAT as PNG. E.g. if you got a monochrome, black-n-white image stored as 24-bit BMP but compressed with PNG -- it will compress way better if you save it as what it's meant to be saved as, a 1-bit monochrome BMP.
Dave Huang - 05 Jan 2008 23:18 GMT > PNG is lossless so there really is no "level." But it depends on what > you're trying to compress. If it's linear content like a Windows [quoted text clipped - 3 lines] > with PNG -- it will compress way better if you save it as what it's > meant to be saved as, a 1-bit monochrome BMP. No, there certainly are levels. Lossless just means that if you compress a picture, then uncompress it, the result is byte-for-byte (or pixel-for-pixel) identical to the input. It says nothing about how much smaller the compressed is compared to the original. Of course, with lossless compression, information theory says there's going to be a limit to the minimum size of the compressed file. However, at least by default, System.Drawing.Imaging comes nowhere close to the theoretical minimum size.
I did some more searching, and came across a few other posts from people asking the same thing, and for some reason, it seems like the response is always something along the lines of your initial statement: PNG is lossless, so there's nothing you can do. I'm not sure where this widespread misunderstanding comes from though. As an example, let's take two trivial run-length encoding style lossless compression algorithm. Say your input is a string of 32 "A"s, followed by 10 "B"s:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
In algorithm 1, the maximum run length is 8, so that string would compress down to: 8A 8A 8A 8A 8B 2B
In algorithm 2, the maximum run length is 256, so that same string would compress to: 32A 10B
Obviously, algorithm 2 has a higher compression level than algorithm 1, yet both are lossless.
Now that's a contrived example, but it's very similar to what real-world lossless compression algorithms do, including the one that PNG uses. Higher compression levels translate into using larger buffers to look ahead further and find repeated strings, along with more memory usage and CPU usage. If you've used archiver programs like WinZip or 7-Zip, you'll see they let you control the compression level... there's often a "fast" setting that doesn't compress as well, but is really fast, "normal", and a "best" setting that is slow, but gives smaller file sizes.
And to get back to PNG, see the description of libpng's png_set_compression_level() at http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-5.8
That is exactly what I'm looking for... sure, I could just _use_ libpng, but it'd be a shame to have to go to an unmanaged DLL when MS supplies as part of .NET something that almost does what I need.
Also see http://en.wikipedia.org/wiki/Pngcrush and http://en.wikipedia.org/wiki/OptiPNG , two utilities which take a PNG file and losslessly recompress it to a smaller size, if possible.
Anyways, hope this explains a bit more about PNG compression, and how those of us who are looking for a way to adjust the compression level aren't asking for something that doesn't make sense.
However, I do get the impression that it doesn't exist in System.Drawing.Imaging :( At least http://msdn2.microsoft.com/en-us/library/ms533846(VS.85).aspx seems to say that the PNG encoder has no configurable parameters. So perhaps I'll have to use libpng after all.
Industrial One - 06 Jan 2008 01:49 GMT > > PNG is lossless so there really is no "level." But it depends on what > > you're trying to compress. If it's linear content like a Windows [quoted text clipped - 61 lines] > say that the PNG encoder has no configurable parameters. So perhaps I'll > have to use libpng after all. True, there can always be an option for an Arithmetic algorithm that dedicates more CPU power to compress the target more efficiently. But since PNG has been around for a long time (1995) (despite not being as recognized as JPEG or GIF) and 'cuz compressing an IMAGE nowadays is a matter of microseconds, I simply ASSUMED PNG was set at its maximum level by default (ignoring what the color depth of the original image was) so didn't think there would be any need for "levels." But it could have, I dunno.
What exactly is your purpose? What are you trying to compress?
Dave Huang - 06 Jan 2008 03:51 GMT > True, there can always be an option for an Arithmetic algorithm that > dedicates more CPU power to compress the target more efficiently. But [quoted text clipped - 4 lines] > was) so didn't think there would be any need for "levels." But it > could have, I dunno. If you're referring to arithmetic coding, PNG doesn't support that (JPEG does though, but due to patent concerns, everyone uses Huffman coding instead).
I suspect if you try compressing a high-resolution, 100+-megabyte image, you'll find that it takes longer than a few microseconds :) And if .NET used the maximum level by default, I wouldn't be here asking how to make it compress better. I don't think it makes sense to use the max compression level by default either--it does take significantly more CPU time, for only minor benefits. It's good to have the option if you need it, but most people don't need max compression.
> What exactly is your purpose? What are you trying to compress? Does it matter? The point is that for whatever reason, .NET's PNGs are lightly compressed, and apparently there's no way to adjust that. But if you must know, I'm compressing screenshots. As an example, I have a 1280x1024, 24-bit BMP that's 3840Kbytes. Image.Save() turns that into a 143K PNG. libpng with the default compression level of 6 turns it into a 112K PNG. OptiPNG gets it down to 106K. Not a huge difference, but enough that I noticed it and thought it was unusual.
Industrial One - 06 Jan 2008 16:17 GMT > If you're referring to arithmetic coding, PNG doesn't support that (JPEG > does though, but due to patent concerns, everyone uses Huffman coding > instead). Arithmetic coding was an example, 'cuz it's usually known for providing the best compression and taking a shitload of time/CPU.
> I suspect if you try compressing a high-resolution, 100+-megabyte image, > you'll find that it takes longer than a few microseconds :) And if .NET [quoted text clipped - 3 lines] > time, for only minor benefits. It's good to have the option if you > need it, but most people don't need max compression. Yeah and it makes sense to believe the average person actually engineers some high-res gigapixel images. Nigga PLEEZ! But meh, I agree, there should be a feature to choose the cpx sensitivity.
> Does it matter? The point is that for whatever reason, .NET's PNGs are Nope, but it helps me give you the best advice. If you were trying to compress natural graphics with PNG then I'd tell you to just use JPEG and quit being so goddamn jewish about lossiness as perfection isn't necessary in a natural scene image, ESPECIALLY if it's some 50-100 pics of the same goddamn tree. But since you are trying to compress desktop screenshots, I'd recommend what I said earlier: down the color depth if such loss can be tolerated and you'll see it compressed down to 30 KB. I dunno what is on your screenshot but if it must retain it's 24-bit color depth, then I dunno.
> lightly compressed, and apparently there's no way to adjust that. But if > you must know, I'm compressing screenshots. As an example, I have a > 1280x1024, 24-bit BMP that's 3840Kbytes. Image.Save() turns that into a > 143K PNG. libpng with the default compression level of 6 turns it into a > 112K PNG. OptiPNG gets it down to 106K. Not a huge difference, but > enough that I noticed it and thought it was unusual. Hmm, I just use Paint, and my average screenshot I took was usually around 100-150 KB. 'Never heard of OptiPNG. If you do find one that features compression sensitivity level adjustment, be sure to inform me. I'd like one.
Michael C - 07 Jan 2008 04:18 GMT > Does it matter? The point is that for whatever reason, .NET's PNGs are > lightly compressed, and apparently there's no way to adjust that. But if [quoted text clipped - 3 lines] > 112K PNG. OptiPNG gets it down to 106K. Not a huge difference, but enough > that I noticed it and thought it was unusual. I can't help but can say thanks for the useful info :-)
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|