JPEG compression

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
khavish
Posts: 12
Joined: 2017-10-27T07:37:54-07:00
Authentication code: 1151

JPEG compression

Post by khavish » 2017-12-31T08:07:36-07:00

The JPEG compression algorithm split the image into 8x8 blocks

Image

My thinking is that if we split an image into 8x8 blocks, feed each block to libjpeg and then merge the JPEG blocks into a lossless format(say PNG) , we should theoretically obtain the same JPEG if we had converted the original image directly into JPEG.However this isn't the case in practice.

Image used : https://drive.google.com/file/d/1ncp_gZ ... sp=sharing

Here is my code:

Code: Select all

#!/bin/bash
# crop the image in 8x8 blocks(a.k.a tiles) and save offsets in filename
convert bench.png -crop 8x8 bench_%d.png
num=`convert bench_*.png -format "%n\n" info: | tail -n 1`

#Convert the tiles to JPEG
for ((i=0; i< $num; i++)); do
offset=`convert bench_$i.png -format "%X%Y" info:`
convert bench_$i.png -quality 80 bench_${i}_${offset}.jpg
done

#Merge the JPEG tiles into a single PNG image

list=""
for ((i=0; i < $num; i++)); do
offset=`echo bench_${i}_*.jpg | sed -n 's/^bench.*[+]\(.*\)[+]\(.*\).jpg$/+\1+\2/p'`
echo "$i $offset"
list="$list ( bench_${i}_${offset}.jpg -set page $offset )"
done
convert $list -layers merge bench_merge_tiles_q80.png
convert bench.png -quality 80 bench_q80_direct.jpg
#Compared the generated merged JPEG in PNG with the directly converted whole image 
compare -metric SSIM  bench_q80_direct.jpg bench_merge_tiles_q80.png /dev/null 
What am i missing here ?

snibgo
Posts: 10554
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: JPEG compression

Post by snibgo » 2017-12-31T11:54:38-07:00

With a sampling factor 4:4:4 (ie no downsamping), there is no difference.

With downsampling, you need larger blocks, eg 16x16. Even then, there is a difference, but only up to about 1% RMSE even with low "-quality" numbers. I guess the difference is because the downsampling is done before splitting into blocks.

Aside: I would put "+repage" after "-layers merge", though it doesn't matter here.

A revised script (for my old version of IM which doesn't have "-metric SSIM") is:

Code: Select all

#!/bin/bash

# Set qual <= 100:
qual=2

# Choose a combination of sampl and blksz:
sampl=4:2:2
blksz=16x16

sampl=4:4:4
blksz=8x8

sampl=4:2:0
blksz=16x16


rm bench_*.png
rm bench_*.jpg

# crop the image in ${blksz} eg 8x8 blocks(a.k.a tiles) and save offsets in filename
convert bench.png -crop ${blksz} bench_%d.png
num=`convert bench_*.png -format "%n\n" info: | tail -n 1`

#Convert the tiles to JPEG
for ((i=0; i< $num; i++)); do
offset=`convert bench_$i.png -format "%X%Y" info:`
convert bench_$i.png -quality ${qual} -define jpeg:sampling-factor=${sampl} bench_${i}_${offset}.jpg
done

#Merge the JPEG tiles into a single PNG image

list=""
for ((i=0; i < $num; i++)); do
offset=`echo bench_${i}_*.jpg | sed -n 's/^bench.*[+]\(.*\)[+]\(.*\).jpg$/+\1+\2/p'`
echo "$i $offset"
list="$list ( bench_${i}_${offset}.jpg -set page $offset )"
done
convert $list -layers merge +repage bench_merge_tiles_q${qual}.png
convert bench.png -quality ${qual} -define jpeg:sampling-factor=${sampl} bench_q${qual}_direct.jpg
#Compared the generated merged JPEG in PNG with the directly converted whole image 
compare -metric RMSE bench_q${qual}_direct.jpg bench_merge_tiles_q${qual}.png NULL:
snibgo's IM pages: im.snibgo.com

khavish
Posts: 12
Joined: 2017-10-27T07:37:54-07:00
Authentication code: 1151

Re: JPEG compression

Post by khavish » 2017-12-31T12:28:14-07:00

Ahh...i forgot about automatic chroma subsampling in IM.Thanks for the reminder and the help.


Happy new Year

Post Reply