8 and 12 bit JPEG in TIFF

The JPEG compression scheme can be used in either 8 or 12 bit precision. There is substantial interest in use of 12bit JPEG compressed TIFF files as a way of distributing high (color) precision color geospatial imagery. Traditionally Intergraph scanners have produced such products. Supporting these products is complicated because the IJG libjpeg must be statically built to either support 8bit or 12bit images. It cannot currently support both in one build. This makes it difficult to build general software on libjpeg that supports both.

A few years ago, LizardTech supported an effort to modify libjpeg to support reading 8 or 12 bit jpeg imagery in the same build. David Gilbert implemented this and the effort was reasonably successful. The code is available as the "mk1-branch" in the libjpeg CVS repository at Also libtiff was modified somewhat to take advantage of this modified libjpeg. However, this work did not address writing 8/12 bit jpeg imagery. The changes were never merged back into the official libjpeg which has experiences weak maintenance this decade.

In 2009 ESRI and Surdex agreed to support work to support reading and writing 8/12 bit jpeg compressed tiff files. Further work on the mk1-branch was considered as well as other fairly radical options. In the end it was decide to go with a more straight forward approach which is to link two copies of libjpeg into libtiff - one built for 8bit and one for 12bit. Renaming of the entire public API of the 12bit libjpeg is used to facilitate coexistance. This work was done by Frank Warmerdam. This page attempts to document the changes made, and explain how to build a dual model libtiff and GDAL.


The essential changes to libjpeg are:

  • Provide an option to rename all public entry points to include _12 if NEED_12_BIT_NAMES is defined. This is accomplished by #defines in various include files, and matches the defines used when NEED_SHORT_EXTERNAL_NAMES is defined.
  • Provide alternative tables suitable for 12bit mode for std_huff_tables() in jcparam.c.
  • Attempt to hide non-public API entry points through the use of -fvisibility=hidden and attribute((visibility("default))) on the gcc toolchain.

The following tickets have been opened against libtiff with regard to 12bit support, and patches applied.

To build in 12bit mode it should only be necessary to define BITS_IN_JSAMPLE to 12, and NEED_12_BIT_NAMES in jmorecfg.h.

#define BITS_IN_JSAMPLE 12
#define NEED_12_BIT_NAMES


The essential changes to libtiff are (mostly applied in tif_jpeg.c 1.82):

  • Add handling of BITS_IN_JSAMPLE==12 to activate some of the JPEG_LIB_MK1 handling.
  • Several fixes in JPEGDecode, JPEGDecodeRaw, and JPEGEncode for 12bit mode.
  • Introduction of an alternate build of tif_jpeg.c (via tif_jpeg_12.c) for 12bit mode.
  • Support for switching modes to _12 stuff in JPEGSetupDecode and JPEGSetupEncode in tif_jpeg.c.
  • changes for --with-jpeg12, --with-jpeg12-include-dir, and --with-jpeg12-lib options.

The changes are all in libtiff4 (HEAD) CVS now. No effort has been made to back port this to libtiff3.9. To build add the following definitions in tif_config.h:

/* 8/12 bit libjpeg dual mode enabled */
#define JPEG_DUAL_MODE_8_12 1
/* 12bit libjpeg primary include file with path */
#define LIBJPEG_12_PATH "/home/warmerda/wrk/jpeg_12/bld/include/jpeglib.h"

and link against the appropriate 12bit library or on linux/unix configure like:

    --enable-jpeg12 \
    --with-jpeg12-include-dir=/home/warmerda/wrk/jpeg_12/bld/include \


The internal versions of libtiff, and libjpeg in GDAL have been updated to include the above changes, and in GDAL trunk a default build with internal libtiff and libjpeg should result in 8/12bit dual mode being enabled. On unix dual mode can be disabled via the --without-jpeg12 switch. On windows this is controlled by the JPEG12_SETTING value in nmake.opt. If the setting is commented out dual mode is disabled.

Reading 12bit files is straightforward. Generating them requires particular creation options for the GTiff driver, for example:

gdal_translate mandril_rgb.tif -co COMPRESS=JPEG -co PHOTOMETRIC=YCBCR -co NBITS=12 out.tif

Band type is UInt16.

Prebuilt Binaries

Dual mode support has been incorporated into OSGeo4W's libtiff package and thus by GDAL. Note that only gdal16 and gdal-dev packages support the NBITS creation option, so it is not currently possible to create 12bit jpeg tiff files with the default gdal 1.5 environment. The 12bit jpeg is provided by the libjpeg12 package.

It is also built into the FWTools 2.4.2 release for windows and later.

Compiling GDAL

To build recent versions of gdal from Source with jpeg12 support, add the following to your ./configure line:

--with-libtiff=internal --with-geotiff=internal --with-jpeg=internal --with-jpeg12

Sample Data

An example 12bit jpeg encoded tiff is available at:

Additional sample data pointers welcome!

Last modified 23 months ago Last modified on Jan 23, 2022, 7:07:27 PM
Note: See TracWiki for help on using the wiki.