Image file formats and compression

Intermediate format
An intermediate file is one you use just to pass the image data around between programs while working on it, e.g. from RawTherapee to GIMP or Photoshop.

The ideal intermediate format is one which loses no image data or metadata and is quick to read and write. This pretty much means you should always use uncompressed 16-bit TIFF as your intermediate format. Period.

Final format
Some things to consider when deciding which format to use for storing non-intermediate files, e.g. final processed images, scanned film, high dynamic range images, and so forth:
 * JPEG is the most widely supported but is lossy and in most implementations limited to 8 bits per channel, 24 bits per pixel.
 * TIFF and JPEG support metadata, PNG generally does not.
 * TIFF can use various compression methods (including the one PNG uses: DEFLATE, also known as Zip). Zip is the most efficient compression method for real-world photos supported by TIFF.
 * PNG is slow and inefficient.
 * The images can be converted externally to other more efficient formats, such as 16-bit JPEG-2000 or OpenEXR.

Lossless compression comparison
The input file is a 16-bit 10000x5000 pixel real-world panorama.

To convert the formats I used ImageMagick-6.8.8.10 on an x86_64 Intel(R) Core(TM) i7 CPU Q 820 @ 1.73GHz, and I scripted the steps in Bash.

TIFF 16-bit
for c in RLE None LZW Zip; do time convert foo.tif[0] -monitor -depth 16 -compress "$c" "${c}_16.tif"; ls -lh "${c}_16.tif"; done

Yes, the result using RLE was bigger than the uncompressed image.

TIFF 12-bit
for c in None LZW Zip; do time convert foo.tif[0] -monitor -depth 12 -compress "$c" "${c}_12.tif"; ls -lh "${c}_12.tif"; done

TIFF 8-bit
for c in None LZW Zip; do time convert foo.tif[0] -monitor -depth 8 -compress "$c" "${c}_8.tif"; ls -lh "${c}_8.tif"; done

TIFF 16-bit floating-point
for c in None LZW Zip; do time convert foo.tif[0] -monitor -define quantum:format=floating-point -compress "$c" "${c}_fp.tif"; ls -lh "${c}_fp.tif"; done

TIFF 64-bit double-precision floating-point
for c in None LZW Zip; do time convert foo.tif[0] -monitor -depth 64 -define quantum:format=floating-point -compress "$c" "${c}_64fp.tif"; ls -lh "${c}_64fp.tif"; done

OpenEXR 16-bit floating-point
OpenEXR is a good option; it's modern, efficient and widely supported. for c in None Zip PIZ; do time convert foo.tif[0] -monitor -depth 16 -compress "$c" "${c}_16.exr"; ls -lh "${c}_16.exr"; done

To convert the EXR to a 16-bit TIFF you need to set the colorspace to sRGB (set it, not transform it): convert Zip_16.exr -depth 16 -set colorspace sRGB suchwow.tif

PNG 16-bit
Finally, PNG. ImageMagick lets you set the zlib compression level 1-9, or uses Huffman compression if you set the first value to 0. The second value sets date encoding filtering, where 5=Adaptive, best for real-world photos. for l in 0 6 9; do time foo.tif[0] -monitor -depth 16 -quality "${l}5" "${l}5_16.png"; ls -lh "${l}5_16.png"; done

PNG 8-bit
for l in 0 6 9; do time foo.tif[0] -monitor -depth 8 -quality "${l}5" "${l}5_8.png"; ls -lh "${l}5_8.png"; done