From e129dfc27a92939c63086abe2184707f87e0399b Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 21 Jun 2020 12:17:05 +0100 Subject: [PATCH] fix TIFFReadScanline() call We were passing in 0 instead of -1, which could trigger an assert in libtiff with some logluv images. Also, fix logluv decode. We were not always resetting the decode format. --- libvips/foreign/tiff2vips.c | 60 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index fc524483..6bde6f31 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -605,7 +605,7 @@ rtiff_strip_read( Rtiff *rtiff, int strip, tdata_t buf ) if( rtiff->header.read_scanlinewise ) length = TIFFReadScanline( rtiff->tiff, - buf, strip, (tsize_t) -1 ); + buf, strip, (tsample_t) 0 ); else length = TIFFReadEncodedStrip( rtiff->tiff, strip, buf, (tsize_t) -1 ); @@ -619,6 +619,25 @@ rtiff_strip_read( Rtiff *rtiff, int strip, tdata_t buf ) return( 0 ); } +/* We need to hint to libtiff what format we'd like pixels in. + */ +static void +rtiff_set_decode_format( Rtiff *rtiff ) +{ + /* Ask for YCbCr->RGB for jpg data. + */ + if( rtiff->header.compression == COMPRESSION_JPEG ) + TIFFSetField( rtiff->tiff, + TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); + + /* Ask for SGI LOGLUV as 3xfloat. + */ + if( rtiff->header.photometric_interpretation == + PHOTOMETRIC_LOGLUV ) + TIFFSetField( rtiff->tiff, + TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT ); +} + static int rtiff_set_page( Rtiff *rtiff, int page ) { @@ -665,12 +684,10 @@ rtiff_set_page( Rtiff *rtiff, int page ) rtiff->current_page = page; - /* This can get unset when we change directories. Make sure - * it's set again. + /* These can get unset when we change directories. Make sure + * they are set again. */ - if( rtiff->header.compression == COMPRESSION_JPEG ) - TIFFSetField( rtiff->tiff, - TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); + rtiff_set_decode_format( rtiff ); } return( 0 ); @@ -1601,21 +1618,10 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out ) uint32 data_length; void *data; - /* Request YCbCr expansion. libtiff complains if you do this for - * non-jpg images. - */ - if( rtiff->header.compression == COMPRESSION_JPEG ) - TIFFSetField( rtiff->tiff, - TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); - - /* Ask for LOGLUV as 3 x float XYZ. - */ - if( rtiff->header.photometric_interpretation == PHOTOMETRIC_LOGLUV ) { - TIFFSetField( rtiff->tiff, - TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT ); + rtiff_set_decode_format( rtiff ); + if( rtiff->header.photometric_interpretation == PHOTOMETRIC_LOGLUV ) vips_image_set_double( out, "stonits", rtiff->header.stonits ); - } out->Xsize = rtiff->header.width; out->Ysize = rtiff->header.height * rtiff->n; @@ -2371,14 +2377,16 @@ rtiff_header_read( Rtiff *rtiff, RtiffHeader *header ) TIFFGetFieldDefaulted( rtiff->tiff, TIFFTAG_COMPRESSION, &header->compression ); + /* We must set this here since it'll change the value of scanline_size. + */ + rtiff_set_decode_format( rtiff ); + /* Request YCbCr expansion. libtiff complains if you do this for * non-jpg images. We must set this here since it changes the result * of scanline_size. */ - if( header->compression == COMPRESSION_JPEG ) - TIFFSetField( rtiff->tiff, - TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); - else if( header->photometric_interpretation == PHOTOMETRIC_YCBCR ) { + if( header->compression != COMPRESSION_JPEG && + header->photometric_interpretation == PHOTOMETRIC_YCBCR ) { /* We rely on the jpg decompressor to upsample chroma * subsampled images. If there is chroma subsampling but * no jpg compression, we have to give up. @@ -2404,12 +2412,6 @@ rtiff_header_read( Rtiff *rtiff, RtiffHeader *header ) "%s", _( "not SGI-compressed LOGLUV" ) ); return( -1 ); } - - /* Always get LOGLUV as 3 x float XYZ. We must set this here - * since it'll change the value of scanline_size. - */ - TIFFSetField( rtiff->tiff, - TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT ); } /* For logluv, the calibration factor to get to absolute luminance.