You need to log in before you can comment on or make changes to this bug.
Created an attachment (id=363) [details] two small but important bug fixes I have been doing some work with an application that will be using libtiff's JPEG-in-TIFF support. The application is HylaFAX. Color fax image data is compressed as JPEG. In order to put a multi-page fax into one file (as well as to make use of valuable data-space in TIFF headers), HylaFAX is wrapping the JPEG images with TIFF. Unfortunately, there are some obstacles (libtiff bugs) in this purpose which has required me to seek out and fix the problems - at least for my purpose. The primary bugs are these: 1) When generating a JPEG-compressed TIFF file and writing the JPEG data into the TIFF with TIFFWriteRawStrip libtiff automatically generates a JPEGTables TIFF tag without being requested by the application and said JPEGTables TIFF tag contains no valid data, just 2000 null bytes. 2) It does not seem possible for the application to produce the JPEGTables tag independent from libtiff. In other words, libtiff must use libjpeg to compress the bitmap data into JPEG in order for a valid JPEGTables tag to be produced. The application cannot suggest a JPEGTables tag to libtiff. Consequently the invalid JPEGTables tag makes it impossible for the viewer applications to render the image properly... and there does not seem to be a workaround other than to decompress the JPEG first and then to recompress it into the TIFF via libtiff (which would introduce some unnecessary loss). 3) When running a JPEG-compressed TIFF file through the tiff2pdf tool (which basically just changes the TIFF wrapper for a PDF wrapper since PDF can have JPEG-compressed image data in it), the resulting PDF file is not viewable in Acrobat Reader, evince, or Ghostscript, although xpdf does handle it fine. I've attached a patch file against libtiff 4.0.0beta5. At the end of tif_jpeg.c is the change that I made in order to resolve my point #1 above (which made my point #2 unimportant). I'm not sure if TIFFSetFieldBit(tif, FIELD_JPEGTABLES) actually needs to be called at this point. I suspect that this field bit will get set later if it is used by the application or by the library, and so I think that during this memory-allocation process at the outset of the TIFF creation it is not important to set the field bit. In any case, removing this one line solves the majority of my grief. The solution to my point #3 above is to write the JPEG SOI headers into the TIFF strip data rather than to skip them. Those two lines of code solve problem #3. Then the PDF can be viewed in all PDF readers I have tested.
The patch has been committed.
I am seeing a regression in the GDAL test suite when this with your change. I have disabled it like this to get back to my original results. Index: tif_jpeg.c =================================================================== --- tif_jpeg.c (revision 19257) +++ tif_jpeg.c (working copy) @@ -2289,8 +2289,8 @@ when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be set, anyway, later when actual JPEGTABLES header is generated, so removing it here hopefully is harmless. +*/ TIFFSetFieldBit(tif, FIELD_JPEGTABLES); -*/ sp->jpegtables_length = SIZE_OF_JPEGTABLES; sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length); _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES); I will investigate further to see if I can determine what the best way forward is.
I have come to the conclusion that deferring the allocation of the jpegtables field is causing the size of the directory to change at a dangerous point for my code. This means it is hard to use the "update directory" functionality if the jpegtables are added late. I'm going to dig and see if there is a clean fix for this.
I have modified TIFFFlush() to call TIFFRewriteDirectory() instead of TIFFWriteDirectory() which seems to take care of forcing the directory to the end of the file if it has changed materially.
Locally I have also enabled the line with TIFFSetFieldBit again. I'm seeing problems (with 3.9.5 and 4.0.0b7) when using TIFFCheckpointDirectory (I would like IFD0 near the beginning of a file because, IIRC, at least Adobe Photoshop CS2 couldn't read a directory if it starts on or after a 2 GB offset). I boiled my problem down to the following sample: #include <tiffio.h> int main(int argc, char *argv[]) { char buf[3] = {127, 127, 127}; TIFF *tiff = TIFFOpen("test.tif", "w"); TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, 1); TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, 1); TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_JPEG); TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFCheckpointDirectory(tiff); TIFFWriteScanline(tiff, buf, 0, 0); TIFFClose(tiff); return 0; } Opening the file results in the error "Not a JPEG file: starts with 0x02 0x00". Without the TIFFCheckpointDirectory it works fine. I can also choose not to make the early TIFFCheckpointDirectory call in case of using JPEG compression because with such compression it's unlikely to reach the 2 GB boundary, but re-enabling the TIFFSetFieldBit line seems easier (and doesn't appear to result in problems for me, probably because I don't make use of TIFFWriteRawStrip).
Bugzilla is no longer used for tracking libtiff issues. Remaining open tickets, such as this one, have been migrated to the libtiff GitLab instance at https://gitlab.com/libtiff/libtiff/issues . The migrated tickets have their summary prefixed with [BZ#XXXX] where XXXX is the initial Bugzilla issue number.