Progressive JPEG File Truncation

A progressive JPEG image contains several interlaced scans: A partially decoded or truncated JPEG file results in the display of a degraded copy of the entire image.

Each scan begins with an SOS marker (octets FF DA). An SOS marker can not occur in entropy-coded JPEG data. Therefore, truncating a JPEG file before the second SOS marker yields a file containing only one scan. Such a file can be displayed by web browsers.

The following Bourne Shell script truncates a progressive JPEG image file given as first argument so that it only contains the number of scans given as the second argument. It writes the result and an EOI marker (octets FF D9) to standard output.

#!/bin/sh

SCANS=$2; SIZE_TARGET=$( ( hexdump -v -e '"" 1/1 "%02X" ""' <$1 | grep -ob FFDA | head -n$(echo $SCANS 1 + p | dc) | tail -n1 | cut -d: -f1; echo 2 / p ) | dc ); head -c"$SIZE_TARGET" <"$1"; env printf '\xff\xd9';
Kodak Image 23 encoded using GIMP at 45% JPEG quality using 4:2:0 chroma subsampling and floating point DCT.
close-up of two brightly colored birds, with out of focus greenery in background
An image containing two scans has a size of around ¼ compared to the original file.
close-up of two brightly colored birds, with out of focus greenery in background
An image containing one scan has a size of around ⅙ compared to the original file.
close-up of two brightly colored birds, with out of focus greenery in background