"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libvips/foreign/tiff2vips.c" between
vips-8.10.6.tar.gz and vips-8.11.0.tar.gz

About: VIPS is a free image processing system (see also the GUI nip2).

tiff2vips.c  (vips-8.10.6):tiff2vips.c  (vips-8.11.0)
skipping to change at line 204 skipping to change at line 204
* 18/11/19 * 18/11/19
* - support ASSOCALPHA in any alpha band * - support ASSOCALPHA in any alpha band
* 27/1/20 * 27/1/20
* - read logluv images as XYZ * - read logluv images as XYZ
* 11/4/20 petoor * 11/4/20 petoor
* - better handling of aligned reads in multipage tiffs * - better handling of aligned reads in multipage tiffs
* 28/5/20 * 28/5/20
* - add subifd * - add subifd
* 6/6/20 MathemanFlo * 6/6/20 MathemanFlo
* - support 2 and 4 bit greyscale load * - support 2 and 4 bit greyscale load
* 27/3/21
* - add jp2k decompresion
*/ */
/* /*
This file is part of VIPS. This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
skipping to change at line 256 skipping to change at line 258
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h> #include <vips/internal.h>
#include <vips/thread.h> #include <vips/thread.h>
#include "pforeign.h" #include "pforeign.h"
#include "tiff.h" #include "tiff.h"
/* Aperio TIFFs (svs) use these compression types for jp2k-compressed tiles.
*/
#define JP2K_YCC 33003
#define JP2K_RGB 33005
/* Bioformats uses this tag for jp2k compressed tiles.
*/
#define JP2K_LOSSY 33004
/* Compression types we handle ourselves.
*/
static int rtiff_we_decompress[] = {
JP2K_YCC,
JP2K_RGB,
JP2K_LOSSY
};
/* What we read from the tiff dir to set our read strategy. For multipage /* What we read from the tiff dir to set our read strategy. For multipage
* read, we need to read and compare lots of these, so it needs to be broken * read, we need to read and compare lots of these, so it needs to be broken
* out as a separate thing. * out as a separate thing.
*/ */
typedef struct _RtiffHeader { typedef struct _RtiffHeader {
uint32 width; uint32 width;
uint32 height; uint32 height;
int samples_per_pixel; int samples_per_pixel;
int bits_per_sample; int bits_per_sample;
int photometric_interpretation; int photometric_interpretation;
skipping to change at line 319 skipping to change at line 338
double stonits; double stonits;
/* Number of subifds, if any. /* Number of subifds, if any.
*/ */
int subifd_count; int subifd_count;
/* Optional IMAGEDESCRIPTION. /* Optional IMAGEDESCRIPTION.
*/ */
char *image_description; char *image_description;
/* TRUE if the compression type is not supported by libtiff directly
* and we must read the raw data and decompress ourselves.
*/
gboolean we_decompress;
} RtiffHeader; } RtiffHeader;
/* Scanline-type process function. /* Scanline-type process function.
*/ */
struct _Rtiff; struct _Rtiff;
typedef void (*scanline_process_fn)( struct _Rtiff *, typedef void (*scanline_process_fn)( struct _Rtiff *,
VipsPel *q, VipsPel *p, int n, void *client ); VipsPel *q, VipsPel *p, int n, void *client );
/* Stuff we track during a read. /* Stuff we track during a read.
*/ */
skipping to change at line 374 skipping to change at line 398
/* Hold a single strip or tile, possibly just an image plane. /* Hold a single strip or tile, possibly just an image plane.
*/ */
tdata_t plane_buf; tdata_t plane_buf;
/* Hold a plane-assembled strip or tile ... a set of samples_per_pixel /* Hold a plane-assembled strip or tile ... a set of samples_per_pixel
* strips or tiles interleaved. * strips or tiles interleaved.
*/ */
tdata_t contig_buf; tdata_t contig_buf;
/* If we are decompressing, we need a buffer to read the raw tile to
* before running the decompressor.
*/
tdata_t compressed_buf;
tsize_t compressed_buf_length;
/* The Y we are reading at. Used to verify strip read is sequential. /* The Y we are reading at. Used to verify strip read is sequential.
*/ */
int y_pos; int y_pos;
} Rtiff; } Rtiff;
/* Test for field exists. /* Test for field exists.
*/ */
static int static int
tfexists( TIFF *tif, ttag_t tag ) tfexists( TIFF *tif, ttag_t tag )
{ {
skipping to change at line 1722 skipping to change at line 1752
if( !(buf = vips_malloc( NULL, rtiff->header.tile_size )) ) if( !(buf = vips_malloc( NULL, rtiff->header.tile_size )) )
return( NULL ); return( NULL );
return( (void *) buf ); return( (void *) buf );
} }
static int static int
rtiff_read_tile( Rtiff *rtiff, tdata_t *buf, int x, int y ) rtiff_read_tile( Rtiff *rtiff, tdata_t *buf, int x, int y )
{ {
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "rtiff_read_tile: x = %d, y = %d\n", x, y ); printf( "rtiff_read_tile: x = %d, y = %d, we_decompress = %d\n",
x, y, rtiff->header.we_decompress );
#endif /*DEBUG_VERBOSE*/ #endif /*DEBUG_VERBOSE*/
if( TIFFReadTile( rtiff->tiff, buf, x, y, 0, 0 ) < 0 ) { if( rtiff->header.we_decompress ) {
vips_foreign_load_invalidate( rtiff->out ); ttile_t tile_no = TIFFComputeTile( rtiff->tiff, x, y, 0, 0 );
return( -1 );
tsize_t size;
size = TIFFReadRawTile( rtiff->tiff, tile_no,
rtiff->compressed_buf, rtiff->compressed_buf_length );
if( size <= 0 ) {
vips_foreign_load_invalidate( rtiff->out );
return( -1 );
}
switch( rtiff->header.compression ) {
case JP2K_YCC:
case JP2K_RGB:
case JP2K_LOSSY:
if( vips__foreign_load_jp2k_decompress(
rtiff->out,
rtiff->header.tile_width,
rtiff->header.tile_height,
TRUE,
rtiff->compressed_buf, size,
buf, rtiff->header.tile_size ) )
return( -1 );
break;
default:
g_assert_not_reached();
break;
}
}
else {
if( TIFFReadTile( rtiff->tiff, buf, x, y, 0, 0 ) < 0 ) {
vips_foreign_load_invalidate( rtiff->out );
return( -1 );
}
} }
return( 0 ); return( 0 );
} }
/* Paint a tile from the file. This is a /* Paint a tile from the file. This is a
* special-case for when a region is exactly a tiff tile, and pixels need no * special-case for when a region is exactly a tiff tile, and pixels need no
* conversion. In this case, libtiff can read tiles directly to our output * conversion. In this case, libtiff can read tiles directly to our output
* region. * region.
*/ */
skipping to change at line 1984 skipping to change at line 2049
#endif /*DEBUG*/ #endif /*DEBUG*/
/* I don't have a sample images for tiled + separate, ban it for now. /* I don't have a sample images for tiled + separate, ban it for now.
*/ */
if( rtiff->header.separate ) { if( rtiff->header.separate ) {
vips_error( "tiff2vips", vips_error( "tiff2vips",
"%s", _( "tiled separate planes not supported" ) ); "%s", _( "tiled separate planes not supported" ) );
return( -1 ); return( -1 );
} }
/* If we will be decompressing, we need a buffer large enough to hold
* the largest compressed tile in any page.
*
* Allocate a buffer 2x the uncompressed tile size ... much simpler
* than searching every page for the largest tile with
* TIFFTAG_TILEBYTECOUNTS.
*/
if( rtiff->header.we_decompress ) {
rtiff->compressed_buf_length = 2 * rtiff->header.tile_size;
if( !(rtiff->compressed_buf = vips_malloc( VIPS_OBJECT( out ),
rtiff->compressed_buf_length )) )
return( -1 );
}
/* Read to this image, then cache to out, see below. /* Read to this image, then cache to out, see below.
*/ */
t[0] = vips_image_new(); t[0] = vips_image_new();
if( rtiff_set_header( rtiff, t[0] ) ) if( rtiff_set_header( rtiff, t[0] ) )
return( -1 ); return( -1 );
/* Double check: in memcpy mode, the vips tilesize should exactly /* Double check: in memcpy mode, the vips tilesize should exactly
* match the tifftile size. * match the tifftile size.
*/ */
skipping to change at line 2357 skipping to change at line 2436
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
/* Load from a tiff dir into one of our tiff header structs. /* Load from a tiff dir into one of our tiff header structs.
*/ */
static int static int
rtiff_header_read( Rtiff *rtiff, RtiffHeader *header ) rtiff_header_read( Rtiff *rtiff, RtiffHeader *header )
{ {
int i;
uint16 extra_samples_count; uint16 extra_samples_count;
uint16 *extra_samples_types; uint16 *extra_samples_types;
toff_t *subifd_offsets; toff_t *subifd_offsets;
char *image_description; char *image_description;
if( !tfget32( rtiff->tiff, TIFFTAG_IMAGEWIDTH, if( !tfget32( rtiff->tiff, TIFFTAG_IMAGEWIDTH,
&header->width ) || &header->width ) ||
!tfget32( rtiff->tiff, TIFFTAG_IMAGELENGTH, !tfget32( rtiff->tiff, TIFFTAG_IMAGELENGTH,
&header->height ) || &header->height ) ||
!tfget16( rtiff->tiff, TIFFTAG_SAMPLESPERPIXEL, !tfget16( rtiff->tiff, TIFFTAG_SAMPLESPERPIXEL,
skipping to change at line 2379 skipping to change at line 2459
&header->bits_per_sample ) || &header->bits_per_sample ) ||
!tfget16( rtiff->tiff, TIFFTAG_PHOTOMETRIC, !tfget16( rtiff->tiff, TIFFTAG_PHOTOMETRIC,
&header->photometric_interpretation ) || &header->photometric_interpretation ) ||
!tfget16( rtiff->tiff, TIFFTAG_INKSET, !tfget16( rtiff->tiff, TIFFTAG_INKSET,
&header->inkset ) ) &header->inkset ) )
return( -1 ); return( -1 );
TIFFGetFieldDefaulted( rtiff->tiff, TIFFGetFieldDefaulted( rtiff->tiff,
TIFFTAG_COMPRESSION, &header->compression ); TIFFTAG_COMPRESSION, &header->compression );
/* One of the types we decompress?
*/
for( i = 0; i < VIPS_NUMBER( rtiff_we_decompress ); i++ )
if( header->compression == rtiff_we_decompress[i] ) {
#ifdef DEBUG
printf( "rtiff_header_read: "
"compression %d handled by us\n",
header->compression );
#endif /*DEBUG*/
header->we_decompress = TRUE;
break;
}
/* We must set this here since it'll change the value of scanline_size. /* We must set this here since it'll change the value of scanline_size.
*/ */
rtiff_set_decode_format( rtiff ); rtiff_set_decode_format( rtiff );
/* Request YCbCr expansion. libtiff complains if you do this for /* Request YCbCr expansion. libtiff complains if you do this for
* non-jpg images. We must set this here since it changes the result * non-jpg images. We must set this here since it changes the result
* of scanline_size. * of scanline_size.
*/ */
if( header->compression != COMPRESSION_JPEG && if( header->compression != COMPRESSION_JPEG &&
header->photometric_interpretation == PHOTOMETRIC_YCBCR ) { header->photometric_interpretation == PHOTOMETRIC_YCBCR ) {
skipping to change at line 2424 skipping to change at line 2517
} }
/* For logluv, the calibration factor to get to absolute luminance. /* For logluv, the calibration factor to get to absolute luminance.
*/ */
if( !TIFFGetField( rtiff->tiff, TIFFTAG_STONITS, &header->stonits ) ) if( !TIFFGetField( rtiff->tiff, TIFFTAG_STONITS, &header->stonits ) )
header->stonits = 1.0; header->stonits = 1.0;
/* Arbitrary sanity-checking limits. /* Arbitrary sanity-checking limits.
*/ */
if( header->width <= 0 || if( header->width <= 0 ||
header->width > VIPS_MAX_COORD || header->width >= VIPS_MAX_COORD ||
header->height <= 0 || header->height <= 0 ||
header->height > VIPS_MAX_COORD ) { header->height >= VIPS_MAX_COORD ) {
vips_error( "tiff2vips", vips_error( "tiff2vips",
"%s", _( "width/height out of range" ) ); "%s", _( "width/height out of range" ) );
return( -1 ); return( -1 );
} }
if( header->samples_per_pixel <= 0 || if( header->samples_per_pixel <= 0 ||
header->samples_per_pixel > 10000 || header->samples_per_pixel > 10000 ||
header->bits_per_sample <= 0 || header->bits_per_sample <= 0 ||
header->bits_per_sample > 32 ) { header->bits_per_sample > 32 ) {
vips_error( "tiff2vips", vips_error( "tiff2vips",
skipping to change at line 2654 skipping to change at line 2747
static int static int
rtiff_header_equal( RtiffHeader *h1, RtiffHeader *h2 ) rtiff_header_equal( RtiffHeader *h1, RtiffHeader *h2 )
{ {
if( h1->width != h2->width || if( h1->width != h2->width ||
h1->height != h2->height || h1->height != h2->height ||
h1->samples_per_pixel != h2->samples_per_pixel || h1->samples_per_pixel != h2->samples_per_pixel ||
h1->bits_per_sample != h2->bits_per_sample || h1->bits_per_sample != h2->bits_per_sample ||
h1->photometric_interpretation != h1->photometric_interpretation !=
h2->photometric_interpretation || h2->photometric_interpretation ||
h1->sample_format != h2->sample_format || h1->sample_format != h2->sample_format ||
h1->compression != h2->compression ||
h1->separate != h2->separate || h1->separate != h2->separate ||
h1->tiled != h2->tiled || h1->tiled != h2->tiled ||
h1->orientation != h2->orientation ) h1->orientation != h2->orientation )
return( 0 ); return( 0 );
if( h1->tiled ) { if( h1->tiled ) {
if( h1->tile_width != h2->tile_width || if( h1->tile_width != h2->tile_width ||
h1->tile_height != h2->tile_height ) h1->tile_height != h2->tile_height )
return( 0 ); return( 0 );
} }
 End of changes. 12 change blocks. 
6 lines changed or deleted 100 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)