AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

2014.12.30 17:31 "[Tiff] [RFC PATCH] Supporting arithmetic encoding for JPEG compressed TIFF", by Even Rouault

Hi,

The proposed attached patch enables the use of arithmetic coding for JPEG

compressed TIFFs. Arithmetic coding is allowed by the TechNote ( http://www.remotesensing.org/libtiff/TIFFTechNote2.html ), although an

extension. Can lead to ~10% smaller files w.r.t optimized huffman coding (your

mileage may vary), all other things equals.

It needs runtime support of the JPEG library, which wasn't available in IJG

libjpeg because of the patents that were still inforce at the time of libjpeg development, but it is now available in libjpeg-turbo (which is now used as

the default libjpeg in some recent Linux distributions) and its derivatives.

Regarding the approach, I've opted for a new pseudo-tag, TIFFTAG_JPEGCODING:

#define TIFFTAG_JPEGCODING              65564   /* Coding algorithm for JPEG 

compression */

#define     JPEGCODING_HUFFMAN          0       /* Huffman coding (default) */
#define     JPEGCODING_ARITHMETIC               1       /* Arithmetic coding */

Opinions?

(My inital approach was to add a new flag value JPEGTABLESMODE_ARITHMETIC = 4

to TIFFTAG_JPEGTABLESMODE but this was a bit awkward as there are no

arithmetic tables to be emitted in JpegTables tag.)

Even

--
Spatialys - Geospatial professional services
http://www.spatialys.com

Index: tif_jpeg.c
===================================================================
--- tif_jpeg.c (révision 28266)
+++ tif_jpeg.c (copie de travail)
@@ -173,6 +173,7 @@

        int             jpegquality;    /* Compression quality level */
        int             jpegcolormode;  /* Auto RGB<=>YCbCr convert? */
        int             jpegtablesmode; /* What to put in JPEGTables */
+       int             jpegcoding;     /* Huffman or arithmetic coding ? */

         int ycbcrsampling_fetched;
 } JPEGState;
@@ -192,7 +193,8 @@
     { TIFFTAG_JPEGTABLES, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_C32_UINT8, FIELD_JPEGTABLES, FALSE, TRUE, "JPEGTables", NULL },
     { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL },
     { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL },

- { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL } + { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL }, + { TIFFTAG_JPEGCODING, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL }

 };

 /*
@@ -1774,8 +1776,12 @@
                unsuppress_quant_table(sp, 0);
                unsuppress_quant_table(sp, 1);
        }

-       if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
+       if (sp->jpegcoding == JPEGCODING_ARITHMETIC )
        {
+           sp->cinfo.c.arith_code = TRUE;
+       }
+       else if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
+       {

                /* Explicit suppression is only needed if we did not go through the */
                /* prepare_JPEGTables() code path, which may be the case if updating */
                /* an existing file */
@@ -2106,6 +2112,12 @@
                sp->ycbcrsampling_fetched = 1;
                /* should we be recomputing upsampling info here? */
                return (*sp->vsetparent)(tif, tag, ap);
+ case TIFFTAG_JPEGCODING:

+               sp->jpegcoding = (int) va_arg(ap, int);
+               /* Disable huffman tables for arithmetic coding */
+               if( sp->jpegcoding == JPEGCODING_ARITHMETIC )
+                   sp->jpegtablesmode &= ~JPEGTABLESMODE_HUFF;
+               return (1);                     /* pseudo tag */

        default:
                return (*sp->vsetparent)(tif, tag, ap);
        }
@@ -2141,6 +2153,9 @@
                case TIFFTAG_JPEGTABLESMODE:

                        *va_arg(ap, int*) = sp->jpegtablesmode;
                        break;
+               case TIFFTAG_JPEGCODING:
+                       *va_arg(ap, int*) = sp->jpegcoding;
+                       break;

                default:
                        return (*sp->vgetparent)(tif, tag, ap);
        }
@@ -2289,6 +2304,7 @@

        sp->jpegquality = 75;                   /* Default IJG quality */

        sp->jpegcolormode = JPEGCOLORMODE_RAW;
        sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF;
+ sp->jpegcoding = JPEGCODING_HUFFMAN;
         sp->ycbcrsampling_fetched = 0;

        /*
Index: tiff.h
===================================================================
--- tiff.h (révision 28243)
+++ tiff.h (copie de travail)
@@ -603,6 +603,9 @@

 #define TIFFTAG_PERSAMPLE       65563  /* interface for per sample tags */
 #define     PERSAMPLE_MERGED        0  /* present as a single value */
 #define     PERSAMPLE_MULTI         1  /* present as multiple values */
+#define TIFFTAG_JPEGCODING             65564   /* Coding algorithm for JPEG compression */
+#define     JPEGCODING_HUFFMAN         0       /* Huffman coding (default) */
+#define     JPEGCODING_ARITHMETIC      1       /* Arithmetic coding */

 /*
  * EXIF tags