If I compress with no options, it's automatically reducing the bitdepth to 4. I thought, the /d0 switch has to be set in order to enable automatic reducing?
This is a new feature. PNGOUT makes a guess as to whether the input file was previously compressed by PNGOUT or by another program. If it thinks it was from another program, PNGOUT uses full autodetection, which works well for most images. Phoenix is one of the notable exceptions. If it thinks PNGOUT previously compressed it, then it will reuse the existing settings.
This guess is based on the Zlib compression flags (PNGOUT uses "fast", which is perhaps the least used method by other programs), and whether there are unnecessary chunks in the file (meaning it was probably not run through PNGOUT).
counting_pine at
That's an interesting concept, deciding how to handle an image based on what compressed it before.
The only really problem I can see is that there are other programs that use better heuristics than PNGOUT. Programs like OptiPNG, PNGCrush and Meesoft's Image Analyzer have a brute force filtering method to improve compression, but their choice of filter would be overridden by PNGOUT's heuristics.
Kerrypng at
PNGCrush and Meesoft Image Analyzer
I have never experimented with OptiPNG, but I have done extensive tests with PNGCrush -brute. I used quite a variety of different types of image and found that PNGCrush could only improve on PNGOUT if the original file size was less than 300 bytes. For tiny images, libpng and GIF LZW can sometimes beat Ken's algorithm.
I have a copy of Meesoft Image Analyzer on my PC, but I didn't get around to experimenting with its PNG compression options before.
Auto detect - try all (slow)
Auto detect - count runs
Auto detect - minimum sum
None
Sub
Up
Average
Paeth
So I did a test with a greyscale photo. Normally, photos compress better with JPEG format, but this one compresses better with PNGOUT (default settings - 27123 bytes). Using Meesoft Image Analyzer I couldn't get it smaller than 30796 bytes. You can see it on my personal weblog. It's the photo of an extinct zebra species, Quagga:
Extinctions in recent history
I would be interested to see an example of a typical image which Meesoft Image Analyzer could compress better than PNGOUT.
counting_pine at
automatic bitdepth reduction without /d0
LibPNG's (and PNGOUT's) heuristics default to filter type 5 for RGB images.
This is a good rule of thumb because images that compress best with filter type 0 can generally compress OK with filter type 5, but images that compress best with filter type 5 could compress really badly with filter type 0.
But some types of images do compress better with filter type 0, and often LibPNG can compress them better on type 0 than PNGOUT can on type 5.
Things like diagrams, or pictures with large areas of one uniform colour tend to compress well with type 0. Screenshots also do well, although not so much if it's something like a game that uses fancy graphics (or if much of the screen is just a photographic wallpaper.)
Doing a quick image search for "screenshot png", I find this image:
http://www.fvwm.org/screenshots/desktops/Piotr_Zielinski-1024x768/screenshot.png
Image Analyzer saves it as 121806 bytes (on filter type 0), while PNGOUT /f5 can only manage 127558 bytes. PNGOUT /f0 can beat it though.
After thinking about it more though, I think overall that what PNGOUT does now is actually an improvement. There are too many programs out there that are terrible at saving PNGs.
The old behaviour would be useful though, for use in batch files after optipng, or for images that need to retain their original type. Could PNGOUT have a few extra k switches, like /kc or /kf?
counting_pine at
Incidentally, I managed to make quagga.png smaller, with a game of "png tennis" between PNGOUT and OptiPNG (PNGOUT to serve:)
PNGOUT could have beaten OptiPNG automatically in the final stage if it had used OptiPNG's settings. On the other hand, if it had used OptiPNG's settings earlier, it wouldn't have even converted the image to palette, so it doesn't really help either case.
When PNGOUT converts from grayscale to palette, it gives a better palette than it had originally. Strangely, I couldn't get PNGOUT to get the same palette by optimising one of its own outputs.
Kerrypng at
I made a misleading statement about the Quagga image. I said it was grayscale, but actually I compressed it as a palette image, because, as you noted, doing it that way often produces a smaller file than /c0.
Usually, I don't spend a lot of time optimizing images unless I'm going to upload them to a website. When it comes to choosing a filter I do a first pass with Web Image Guru, a commercial application. I can step through all the filter options in a few seconds and see the resulting file sizes displayed in the preview panel. Then I switch to the GUI version of PNGOUT which comes with IrfanView. Finally, I step through the block-split options to home in on the smallest file size. What it boils down to, is that I choose the correct filter before launching PNGOUT.
You can see a screenshot of the Web Image Guru options panel at my Review of PNG GUI tools for Micro$oft Windows users.
Most of the time I create palette images, so the default /f0 filter is best. I did do some tests long ago, but I never found an exception that couldn't be better compressed as 24-bit RGB.
I ran the screenshot you suggested through Web Image Guru and got a file size of 113249 bytes -- compared to 121806 bytes with Image Analyzer. The output was 24-bit RGB -- no color reduction. I haven't got any idea how it managed it. Maybe it incorporates some techniques from OptiPNG. Previously, I avoided OptiPNG because I have an aversion to command line tools unless there is no suitable alternative. Today, I visited the OptiPNG site and discovered there's a new GUI wrapper. I haven't had time to become familiar with the options, but I ran the screenshot through OptiPNG and got a file size of 113201 bytes.
deus-ex at
Awesoken said
This is a new feature. PNGOUT makes a guess as to whether the input file was previously compressed by PNGOUT or by another program.
Please add an option to disable bitdepth reduction then (e.g. /d-) as i like to have a choice wether to reduce bitdepth or not.
Awesoken said
Phoenix is one of the notable exceptions. If it thinks PNGOUT previously compressed it, then it will reuse the existing settings.
So how about adding an option to force full autodetection for such cases?
Awesoken at
While looking for a workaround, I noticed some problems with PNGOUT's stdin/stdout handling. I just fixed that and updated my site. You may use this batch file to force PNGOUT to recompress a file with fully autodetected settings:
PNGAUTO.BAT:
@pngout %1 - /s5 /force /q | pngout - %* /y
For example, type "pngauto phoenix.png" or "pngauto phoenix.png /d8". Once you have run PNGAUTO.BAT on the file, PNGOUT will keep the same settings.
deus-ex at
Thank you, Awesoken. But this doesn't solve the problem imho because now you have to check every file for its bitdepth prior processing it with pngout in order to set the correct parameters. This renders batch compression of multiple (100-1000) files with the current Pngout version impracticable. Please reconsider of adding a switch as requested in my previous post, if it isn't to much i ask for.
Or, if that is not possible for reasons beyond my sight,please make a version (e.g. the previous) without the auto bitdepth reduction available as an alternate download.
counting_pine at
Well, if Ken doesn't change PNGOUT's behaviour, here's an alternative solution.
It's not pretty, but here's a hackish way to rewrite PNG files so that PNGOUT is fooled into thinking it compressed it. It rewrites the IDAT deflate header to match PNGOUT's, and removes ancillary chunks.
'' POFOOL.BAS - program to rewrite PNG files, to look like PNGOUT created them.
'' usage: pofool file.png
'cls
const buffersize = 1024
dim buffer as string
dim i as long, o as long
dim qw as string * 8, chunksize as long, chunkname as string * 4, crc as long, idat as string
idat = "IDAT"
dim file as string
'comment this out if command$ unsupported:
file = command$
if file = "" then
line input "PNG file: ", file
end if
open file for binary as #1
buffer = space$(8)
get #1, 1, buffer
if buffer <> chr$(&H89) + "PNG" + chr$(13) + chr$(10) + chr$(26) + chr$(10) then
print "Invalid PNG file"
close
end
end if
i = 9: o = 9
while chunkname <> "IEND"
get #1, i, qw: i = i + 8
chunksize = cvi(mid$(qw, 4, 1) + mid$(qw, 3, 1) + mid$(qw, 2, 1) + left$(qw, 1))
chunkname = right$(qw, 4)
'print chunkname, chunksize: sleep
select case chunkname
case "IHDR", "PLTE", "tRNS", "IDAT", "IEND"
put #1, o, qw: o = o + 8
while chunksize
if chunksize >= buffersize then buffer = space$(buffersize) else buffer = space$(chunksize)
chunksize = chunksize - len(buffer)
get #1, i, buffer: i = i + len(buffer)
if chunkname = idat then
idat = ""
mid$(buffer, 1, 2) = "x^"
end if
put #1, o, buffer: o = o + len(buffer)
wend
get #1, i, crc: i = i + 4
put #1, o, crc: o = o + 4
case else
i = i + chunksize + 4
end select
if i > lof(1) then close: end
wend
while o < lof(1)
if o + buffersize > lof(1) then buffer = string$(lof(1) - o, chr$(0)) else buffer = string$(buffersize, chr$(0))
put #1, o, buffer: o = o + len(buffer)
wend
close #1
It runs fine in QB, and can also be compiled in FreeBASIC.
Note: It doesn't update the CRC for the IDAT chunk, so the PNG may be invalid. Also, if it removes any ancillary chunks, there will be zeros after the end of the PNG. PNGOUT doesn't mind this, but other apps do. Everything will be fine though if PNGOUT overwrites the PNG, and the errors can be fixed with optipng -fix, although it will also change the deflate header back.
Awesoken at
I was being stubborn and lazy. I have updated PNGOUT with a "keep settings" option: /ks. This required me to allocate another precious line of text to the PNGOUT help. If I end up having nightmares over this bloat, it's all deus-ex's fault! : P
counting_pine at
Cool. It's a lot nicer than my solution.
If you're worried about the help text size, I'd suggest having a briefer introduction text, that basically just tells the user to run pngout /?|/h or something to get an extended help text (and also to try PNGOUTWin:)
deus-ex at
Awesoken said
I have updated PNGOUT with a "keep settings" option: /ks.
Much apreciated. Thank you.
Awesoken said
If I end up having nightmares over this bloat, it's all deus-ex's fault! : P
Muahahaha. :lol:
counting_pine at
Re: automatic bitdepth reduction without /d0
Hi. I've discovered a small issue with the "previous settings auto-detection" feature. If you try it on an image with a bit depth lower than 8, and try to convert it to a new type, e.g. with /c6, then it will try to take the previous bit depth, and causes an error because the new color type is incompatible with that bit depth. Can you change it so it doesn't cause an error in these situations, but just chooses a more appropriate bit depth?
Awesoken at
Thanks for the report. I have uploaded a fix - would you please verify that it works?
counting_pine at
Wow, that was quick :) I ran a few tests and it works fine, thanks.