I have absolutely no time to develop this line of thought further but the image entropy is probably a good discriminant for selecting JPEG or PNG - see my earlier comment on your question.
If you use ImageMagick, you can calculate the Entropy easily like this:
identify -verbose -features 1 image.jpg | grep -i -A1 entropy
Your top image gives output like this:
identify -verbose -features 1 t.jpg | grep -i -A1 entropy
Sum Entropy:
0.703064, 0.723437, 0.733147, 0.733015, 0.723166
Entropy:
1.01034, 1.12974, 1.14983, 1.15122, 1.11028
Difference Entropy:
0.433414, 0.647495, 0.665738, 0.671079, 0.604431
and your bottom image gives output like this:
identify -verbose -features 1 b.jpg | grep -i -A1 entropy
Sum Entropy:
1.60934, 1.62512, 1.65567, 1.65315, 1.63582
Entropy:
2.19687, 2.33206, 2.44111, 2.43816, 2.35205
Difference Entropy:
0.737134, 0.879926, 0.980157, 0.979763, 0.894245
I suspect images with a higher entropy will compress better as JPEGs and those with a lower entropy will fare better as PNGs - but I have to dash now :-)
There are 5 values for each type of entropy - horizontal, vertical, left diag, right diag and overall. I think the last value is the only one you need consider.
Updated
Ok, I have had a little more time to spend on this now. I do not have a pile of sample images to test my theory on, so I did it a different way. I made a little script to calculate the following for a given input file:
- ratio of JPEG size to PNG size
- entropy
Here it is:
#!/bin/bash
f="$1"
jsize=$(convert "$f" -strip JPG:- | wc -c)
psize=$(convert "$f" PNG:- | wc -c)
jpratio=$(echo $jsize*100/$psize | bc)
# Make greyscale version for entropy calculation
rm temp*.jpg 2> /dev/null
convert "$f" -colorspace gray temp.jpg
entropy=$(identify -verbose -features 1 temp.jpg | grep -A1 " Entropy:" | tail -n 1 | awk -F, '{print $5}')
echo $jpratio:$entropy
So, for a given image, you would do this:
./go image.jpg
8:3.3 # JPEG is 8x bigger than PNG and entropy is 3.3
Then I took your image and added different amounts of noise to it to increase its entropy, like this
for i in {1..99}; do convert bottom.jpg +noise Gaussian -evaluate add ${i}% xx${i}.jpg;done
that gives me files called xx1.jpg
with 1% noise, xx2.jpg
with 2% noise and so on, up to xx99.jpg with 99% noise.
Then I ran each of the files through the first script, like this:
for f in xx*.jpg; do ./go $f;done > data.txt
to give me data.txt
.
Then I created the following gnuplot command file plot.cmd
:
set title 'Plotted with Gnuplot'
set ylabel 'Entropy'
set xlabel 'JPEG size/PNG Size'
set grid
set terminal postscript color landscape dashed enhanced 'Times-Roman'
set output 'file.eps'
plot 'data.txt'
and ran it with
gnuplot plot.cmd
And I got the following plot which shows that as ImageMagick's entropy number increases, the ratio of JPEG size to PNG size improves in favour of JPEG... not very scientific, but something at least. Maybe you could run the script against the type of images you normally use and see what you get.
