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��