Bug 2135 - two fixes for JPEG support
: two fixes for JPEG support
Status: RESOLVED LATER
: libtiff
default
: 4.0.0
: All All
: P2 normal
: ---
Assigned To:
:
:
: migrated_to_gitlab
:
:
  Show dependency treegraph
 
Reported: 2009-12-24 02:09 by
Modified: 2019-10-01 14:19 (History)


Attachments
two small but important bug fixes (1.34 KB, patch)
2009-12-24 02:09, Lee Howard
Details | Diff


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2009-12-24 02:09:39
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.
------- Comment #1 From 2010-02-22 14:15:47 -------
The patch has been committed.
------- Comment #2 From 2010-03-30 12:27:37 -------
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.
------- Comment #3 From 2010-03-30 13:22:00 -------
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.
------- Comment #4 From 2010-03-31 08:52:29 -------
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.
------- Comment #5 From 2011-10-26 17:39:22 -------
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).
------- Comment #6 From 2019-10-01 14:19:21 -------
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.