AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

2012.01.07 02:39 "[Tiff] resubmit tiff_ojpeg patch (2011/6/8)", by Ryan Wong

This is a repost of the patch, originally sent on 2011/6/8, for reading certain tif_ojpeg files from a certain software vendor.

I repost this because the earlier patch was not in unified diff format, making it difficult to apply. In order to address the issue of TIFFTAG_JPEGIFOFFSET not pointing to the start of any JPEG marker (that is, the first byte being not 0xFF), the tif_ojpeg.c was extensively modified to test both TIFFTAG_STRIPOFFSETS and TIFFTAG_JPEGIFOFFSET, in addition to a limited range of marker searching. It is also modified to deal with incorrect metadata in the file. The patch is applicable to 3.9.5 only. Regards,rwong_002@hotmail.com

--- libtiff-3_9_5_r227596\source\libtiff\tif_dirread.c 2012-01-06 17:40:59.693689100 -0800
+++ libtiff-3_9_5\source\libtiff\tif_dirread.c 2012-01-06 17:50:58.475760000 -0800
@@ -77,12 +77,13 @@

        int n;
        TIFFDirectory* td;
        TIFFDirEntry *dp, *dir = NULL;
        uint16 iv;
        uint32 v;
+       uint16 iv2[2];
        const TIFFFieldInfo* fip;
        size_t fix;
        uint16 dircount;
        uint16 previous_tag = 0;
        int diroutoforderwarning = 0, compressionknown = 0;
        int haveunknowntags = 0;

@@ -641,12 +642,22 @@

                                 * by spec.  Assume correct SamplesPerPixel value of 1.
                                 */

                                if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1))
                                        goto bad;
                        }
                }

+               /*
+                * If there is any disagreement between the TIFF header and JPEG datastream,
+                * the values from the JPEG datastream should be used. Calling TIFFGetField
+                * will trigger the OJPEG handler to perform a cross-check, which will fix 
+                * the TIFF directory fields.
+                */
+               TIFFGetField(tif,TIFFTAG_BITSPERSAMPLE, &iv);
+               TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL, &iv);
+               TIFFGetField(tif,TIFFTAG_PHOTOMETRIC, &iv);
+               TIFFGetField(tif,TIFFTAG_YCBCRSUBSAMPLING, iv2 + 0, iv2 + 1);

        }
        /*
         * Verify Palette image has a Colormap.
         */
        if (td->td_photometric == PHOTOMETRIC_PALETTE &&
            !TIFFFieldSet(tif, FIELD_COLORMAP)) {

--- libtiff-3_9_5_r227596\source\libtiff\tif_ojpeg.c    2012-01-06 17:40:59.772697000 -0800

+++ libtiff-3_9_5\source\libtiff\tif_ojpeg.c    2012-01-06 17:50:58.428760000 -0800

@@ -332,12 +332,13 @@
 static int OJPEGReadHeaderInfo(TIFF* tif);
 static int OJPEGReadSecondarySos(TIFF* tif, tsample_t s);
 static int OJPEGWriteHeaderInfo(TIFF* tif);
 static void OJPEGLibjpegSessionAbort(TIFF* tif);

 static int OJPEGReadHeaderInfoSec(TIFF* tif);
+static int OJPEGReadHeaderInfoSecStream(TIFF* tif);

 static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif);
 static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif);
 static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif);
 static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id);
 static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif);

 static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif);
@@ -458,12 +459,27 @@
                case TIFFTAG_JPEGIFOFFSET:

                        *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format;
                        break;
                case TIFFTAG_JPEGIFBYTECOUNT:
                        *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format_length;
                        break;
+               case TIFFTAG_BITSPERSAMPLE:
+                       if (sp->subsamplingcorrect_done==0)
+                               OJPEGSubsamplingCorrect(tif);
+                       return (*sp->vgetparent)(tif,tag,ap);
+                       break;
+               case TIFFTAG_SAMPLESPERPIXEL:
+                       if (sp->subsamplingcorrect_done==0)
+                               OJPEGSubsamplingCorrect(tif);
+                       return (*sp->vgetparent)(tif,tag,ap);
+                       break;
+               case TIFFTAG_PHOTOMETRIC:
+                       if (sp->subsamplingcorrect_done==0)
+                               OJPEGSubsamplingCorrect(tif);
+                       return (*sp->vgetparent)(tif,tag,ap);
+                       break;
                case TIFFTAG_YCBCRSUBSAMPLING:
                        if (sp->subsamplingcorrect_done==0)
                                OJPEGSubsamplingCorrect(tif);
                        *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor;
                        *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver;
                        break;
@@ -562,12 +578,17 @@
                case TIFFTAG_JPEGPROC:
                        sp->jpeg_proc=(uint8)va_arg(ap,uint32);
                        break;
                case TIFFTAG_JPEGRESTARTINTERVAL:
                        sp->restart_interval=(uint16)va_arg(ap,uint32);
                        break;
+               case TIFFTAG_BITSPERSAMPLE:
+                       // TIFF IFD contains a BitsPerSample value 
+                       // inconsistent with the OJPEG stream.
+                       tif->tif_dir.td_bitspersample = (uint16)8;
+                       break;

                default:
                        return (*sp->vsetparent)(tif,tag,ap);
        }
        TIFFSetFieldBit(tif,_TIFFFieldWithTag(tif,tag)->field_bit);
        tif->tif_flags|=TIFF_DIRTYDIRECT;
        return(1);
@@ -839,19 +860,22 @@

 static void

 OJPEGPostDecode(TIFF* tif, tidata_t buf, tsize_t cc)
 {
        OJPEGState* sp=(OJPEGState*)tif->tif_data;
        (void)buf;
        (void)cc;
+ if (tif->tif_row % sp->lines_per_strile == 0)
+ {
        sp->write_curstrile++;
        if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0)
        {
                assert(sp->libjpeg_session_active!=0);
                OJPEGLibjpegSessionAbort(tif);
                sp->writeheader_done=0;
        }
+ }
 }

 static int
 OJPEGSetupEncode(TIFF* tif)
 {
        static const char module[]="OJPEGSetupEncode";
@@ -937,41 +961,114 @@
 OJPEGSubsamplingCorrect(TIFF* tid��