1998.07.30 08:35 "libtiff fixes", by Tim Shaporev

Hi!

I have two patches for LIBTIFF.

In fact they are about bugs in my sample files, not in the library but these twicked data files exist already so I have to manage them and I see no harm in the changes, so it would be nice to see the changes in the library in some future.

Basically the changes do the following

The patches itself are appended to the end of message.

Finally, I have a problem and a question.

I have couple of samples with stripbytecount too small, i.e. data are really present in the file and if you try to read after the end of strip the file is decoded Ok. I'm not sure if it is worth implementing in the library, (at the moment I did it in home-made CCITT decoder).

By the way, the code to read CCITT images in libtiff looks really unpleasant for me, and, from my own point of view of course, the above home-made decoder is somewhat better (as far as I could see it might also solve the problem with "lazy decoding" although I'm not sure). Is anybody interested in such a beast? Let's discuss if so.

Regards,

                                Tim

*** tif_dirread.old     Tue Sep  2 21:54:24 1997
--- tif_dirread.c       Mon Jul 27 12:50:19 1998
***************
*** 252,257 ****
--- 252,265 ----
                 * Check data type.
                 */
                fip = tif->tif_fieldinfo[fix];
+               if (fip->field_type == TIFF_SHORT &&
+                   dp->tdir_type == TIFF_LONG) {
+                       /* Allow longs to be read instead of shorts */
+                       TIFFWarning(tif->tif_name,
+                               "wrong data type %d for \"%s\"",
+                               dp->tdir_type, fip[-1].field_name);
+                       /*fip->field_tag = TIFF_LONG;*/ /* Hm-m */
+               } else
                while (dp->tdir_type != (u_short) fip->field_type) {
                        if (fip->field_type == TIFF_ANY)        /* wildcard */
                                break;
***************
*** 489,494 ****
--- 497,504 ----
                 * is one uncompressed strip of data.
                 */
                if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
+                   (td->td_compression != COMPRESSION_NONE ||
+                    !TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) &&
                    td->td_nstrips > 1) ||
                    (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
                     td->td_nstrips != td->td_samplesperpixel)) {
***************
*** 566,583 ****
            CheckMalloc(tif, td->td_nstrips * sizeof (uint32),
                "for \"StripByteCounts\" array");
        if (td->td_compression != COMPRESSION_NONE) {
!               uint32 space = (uint32)(sizeof (TIFFHeader)
!                   + sizeof (uint16)
!                   + (dircount * sizeof (TIFFDirEntry))
!                   + sizeof (uint32));
                toff_t filesize = TIFFGetFileSize(tif);
-               uint16 n;

                /* calculate amount of space used by indirect values */
!               for (dp = dir, n = dircount; n > 0; n--, dp++) {
                        uint32 cc = dp->tdir_count*tiffDataWidth[dp->tdir_type];
!                       if (cc > sizeof (uint32))
                                space += cc;
                }
                space = filesize - space;
                if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
--- 576,604 ----
            CheckMalloc(tif, td->td_nstrips * sizeof (uint32),
                "for \"StripByteCounts\" array");
        if (td->td_compression != COMPRESSION_NONE) {

! /* sizeof() sometimes gives strange results, so specify 'em directly */
! #define HEADER_SIZE   4
! #define COUNTER_SIZE  2
! #define DIR_ENTRY_SIZE        12
! #define OFFSET_SIZE   4
!               uint32 space = HEADER_SIZE + COUNTER_SIZE +
!                       (dircount * DIR_ENTRY_SIZE) + OFFSET_SIZE;
                toff_t filesize = TIFFGetFileSize(tif);

                /* calculate amount of space used by indirect values */
!               for (dp = dir; dp-dir < dircount; dp++) {
                        uint32 cc = dp->tdir_count*tiffDataWidth[dp->tdir_type];
!                       if (cc > sizeof (uint32)) {
!                               /* did we see this data chunk? */
!                               register TIFFDirEntry *d;
!                               for (d=dir; d<dp; d++)
!                                       if (d->tdir_offset == dp->tdir_offset &&
!                                           d->tdir_type == dp->tdir_type)
!                                               goto next;
                                space += cc;
+                       next:   ;
+                       }
                }
                space = filesize - space;
                if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
***************
*** 596,605 ****
                        td->td_stripbytecount[i] =
                            filesize - td->td_stripoffset[i];
        } else {
!               uint32 rowbytes = TIFFScanlineSize(tif);
!               uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage;
!               for (i = 0; i < td->td_nstrips; i++)
!                       td->td_stripbytecount[i] = rowbytes*rowsperstrip;
        }
        TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
        if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
--- 617,640 ----
                        td->td_stripbytecount[i] =
                            filesize - td->td_stripoffset[i];
        } else {
!               uint32 bytecount, rows;
!               uint32 rowsperstrip =
!                       TIFFFieldSet(tif, FIELD_ROWSPERSTRIP) &&
!                       td->td_rowsperstrip != (uint32)-1 ?
!                       td->td_rowsperstrip :
!                       (td->td_imagelength+td->td_stripsperimage-1) /
!                               td->td_stripsperimage;

!               bytecount = rowsperstrip * TIFFScanlineSize(tif);
!               for (i=0; ++i < td->td_nstrips;)
!                       td->td_stripbytecount[i-1] = bytecount;

!               if (td->td_nstrips > 0) { /* the last strip */
!                       i = td->td_nstrips - 1;
!                       rows = td->td_imagelength - i*rowsperstrip;
!                       td->td_stripbytecount[i] = rows < rowsperstrip ?
!                               rows * TIFFScanlineSize(tif) : bytecount;
!               }
        }
        TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
        if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
*** tif_read.old        Tue Sep  2 21:54:29 1997
--- tif_read.c  Thu Jul 16 11:49:59 1998
***************
*** 257,262 ****
--- 257,272 ----
                        _TIFFfree(tif->tif_rawdata);
                tif->tif_flags &= ~TIFF_MYBUFFER;
                if (td->td_stripoffset[strip] + bytecount > tif->tif_size) {
+                   if (strip == td->td_nstrips-1 &&
+                       td->td_stripoffset[strip] < tif->tif_size) {
+                       bytecount = tif->tif_size - td->td_stripoffset[strip];
+                       TIFFWarning(tif->tif_name,
+                   "bogus byte count %lu on strip %lu adjusted to %lu",
+                               (u_long) td->td_stripbytecount[strip],
+                               (u_long) strip,
+                               (u_long) bytecount);
+                       td->td_stripbytecount[strip] = bytecount;
+                   } else {
                        /*
                         * This error message might seem strange, but it's
                         * what would happen if a read were done instead.
***************
*** 269,274 ****
--- 279,285 ----
                            (u_long) bytecount);
                        tif->tif_curstrip = NOSTRIP;
                        return (0);
+                   }
                }
                tif->tif_rawdatasize = bytecount;
                tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip];
---------- the end ----------