"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libvips/foreign/vips2tiff.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).

vips2tiff.c  (vips-8.10.6):vips2tiff.c  (vips-8.11.0)
skipping to change at line 273 skipping to change at line 273
* *
* A write-plane-separate flag to the TIFF writer could let us set the * A write-plane-separate flag to the TIFF writer could let us set the
* photometric interpretation correctly, and save all planes in a single * photometric interpretation correctly, and save all planes in a single
* pass before doing a final gather sweep. * pass before doing a final gather sweep.
*/ */
/* Max number of alpha channels we allow. /* Max number of alpha channels we allow.
*/ */
#define MAX_ALPHA (64) #define MAX_ALPHA (64)
/* Bioformats uses this tag for lossy jp2k compressed tiles.
*/
#define JP2K_LOSSY 33004
/* Compression types we handle ourselves.
*/
static int wtiff_we_compress[] = {
JP2K_LOSSY
};
typedef struct _Layer Layer; typedef struct _Layer Layer;
typedef struct _Wtiff Wtiff; typedef struct _Wtiff Wtiff;
/* A layer in the pyramid. /* A layer in the pyramid.
*/ */
struct _Layer { struct _Layer {
Wtiff *wtiff; /* Main wtiff struct */ Wtiff *wtiff; /* Main wtiff struct */
/* The filename for this layer, for file output. /* The filename for this layer, for file output.
*/ */
skipping to change at line 354 skipping to change at line 364
int resunit; /* Resolution unit (inches or cm) */ int resunit; /* Resolution unit (inches or cm) */
double xres; /* Resolution in X */ double xres; /* Resolution in X */
double yres; /* Resolution in Y */ double yres; /* Resolution in Y */
const char *profile; /* Profile to embed */ const char *profile; /* Profile to embed */
int bigtiff; /* True for bigtiff write */ int bigtiff; /* True for bigtiff write */
int rgbjpeg; /* True for RGB not YCbCr */ int rgbjpeg; /* True for RGB not YCbCr */
int properties; /* Set to save XML props */ int properties; /* Set to save XML props */
int strip; /* Don't write metadata */ int strip; /* Don't write metadata */
VipsRegionShrink region_shrink; /* How to shrink regions */ VipsRegionShrink region_shrink; /* How to shrink regions */
int level; /* zstd compression level */ int level; /* zstd compression level */
gboolean lossless; /* webp lossless mode */ gboolean lossless; /* lossless mode */
VipsForeignDzDepth depth; /* Pyr depth */ VipsForeignDzDepth depth; /* Pyr depth */
gboolean subifd; /* Write pyr layers into subifds */ gboolean subifd; /* Write pyr layers into subifds */
gboolean premultiply; /* Premultiply alpha */
/* True if we've detected a toilet-roll image, plus the page height, /* True if we've detected a toilet-roll image, plus the page height,
* which has been checked to be a factor of im->Ysize. page_number * which has been checked to be a factor of im->Ysize. page_number
* starts at zero and ticks up as we write each page. * starts at zero and ticks up as we write each page.
*/ */
gboolean toilet_roll; gboolean toilet_roll;
int page_height; int page_height;
int page_number; int page_number;
int n_pages; int n_pages;
/* The height of the TIFF we write. Equal to page_height in toilet /* The height of the TIFF we write. Equal to page_height in toilet
* roll mode. * roll mode.
*/ */
int image_height; int image_height;
/* TRUE if the compression type is not supported by libtiff directly
* and we must compress ourselves.
*/
gboolean we_compress;
/* If we are copying, we need a buffer to read the compressed tile to.
*/
tdata_t compressed_buf;
tsize_t compressed_buf_length;
}; };
/* Write an ICC Profile from a file into the JPEG stream. /* Write an ICC Profile from a file into the JPEG stream.
*/ */
static int static int
embed_profile_file( TIFF *tif, const char *profile ) embed_profile_file( TIFF *tif, const char *profile )
{ {
VipsBlob *blob; VipsBlob *blob;
if( vips_profile_load( profile, &blob, NULL ) ) if( vips_profile_load( profile, &blob, NULL ) )
skipping to change at line 639 skipping to change at line 660
return( 0 ); return( 0 );
} }
/* Write a TIFF header for this layer. /* Write a TIFF header for this layer.
*/ */
static int static int
wtiff_write_header( Wtiff *wtiff, Layer *layer ) wtiff_write_header( Wtiff *wtiff, Layer *layer )
{ {
TIFF *tif = layer->tif; TIFF *tif = layer->tif;
int i;
int orientation; int orientation;
#ifdef DEBUG #ifdef DEBUG
printf( "wtiff_write_header: sub %d, width %d, height %d\n", printf( "wtiff_write_header: sub %d, width %d, height %d\n",
layer->sub, layer->width, layer->height ); layer->sub, layer->width, layer->height );
#endif /*DEBUG*/ #endif /*DEBUG*/
/* Output base header fields. /* Output base header fields.
*/ */
TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, layer->width ); TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, layer->width );
skipping to change at line 675 skipping to change at line 697
TIFFSetField( tif, TIFFSetField( tif,
TIFFTAG_PREDICTOR, wtiff->predictor ); TIFFTAG_PREDICTOR, wtiff->predictor );
} }
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/ #endif /*HAVE_TIFF_COMPRESSION_WEBP*/
if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE || if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE ||
wtiff->compression == COMPRESSION_LZW) && wtiff->compression == COMPRESSION_LZW) &&
wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
TIFFSetField( tif, TIFFTAG_PREDICTOR, wtiff->predictor ); TIFFSetField( tif, TIFFTAG_PREDICTOR, wtiff->predictor );
for( i = 0; i < VIPS_NUMBER( wtiff_we_compress ); i++ )
if( wtiff->compression == wtiff_we_compress[i] ) {
wtiff->we_compress = TRUE;
break;
}
/* Don't write mad resolutions (eg. zero), it confuses some programs. /* Don't write mad resolutions (eg. zero), it confuses some programs.
*/ */
TIFFSetField( tif, TIFFTAG_RESOLUTIONUNIT, wtiff->resunit ); TIFFSetField( tif, TIFFTAG_RESOLUTIONUNIT, wtiff->resunit );
TIFFSetField( tif, TIFFTAG_XRESOLUTION, TIFFSetField( tif, TIFFTAG_XRESOLUTION,
VIPS_FCLIP( 0.01, wtiff->xres, 1000000 ) ); VIPS_FCLIP( 0.01, wtiff->xres, 1000000 ) );
TIFFSetField( tif, TIFFTAG_YRESOLUTION, TIFFSetField( tif, TIFFTAG_YRESOLUTION,
VIPS_FCLIP( 0.01, wtiff->yres, 1000000 ) ); VIPS_FCLIP( 0.01, wtiff->yres, 1000000 ) );
if( !wtiff->strip ) if( !wtiff->strip )
if( wtiff_embed_profile( wtiff, tif ) || if( wtiff_embed_profile( wtiff, tif ) ||
skipping to change at line 794 skipping to change at line 822
alpha_bands = VIPS_CLIP( 0, alpha_bands = VIPS_CLIP( 0,
wtiff->ready->Bands - colour_bands, MAX_ALPHA ); wtiff->ready->Bands - colour_bands, MAX_ALPHA );
if( alpha_bands > 0 ) { if( alpha_bands > 0 ) {
uint16 v[MAX_ALPHA]; uint16 v[MAX_ALPHA];
int i; int i;
/* EXTRASAMPLE_UNASSALPHA means generic extra /* EXTRASAMPLE_UNASSALPHA means generic extra
* alpha-like channels. ASSOCALPHA means pre-multipled * alpha-like channels. ASSOCALPHA means pre-multipled
* alpha only. * alpha only.
*
* Make the first channel the premultiplied alpha, if
* we are premultiplying.
*/ */
for( i = 0; i < alpha_bands; i++ ) for( i = 0; i < alpha_bands; i++ )
v[i] = EXTRASAMPLE_UNASSALPHA; v[i] = i == 0 && wtiff->premultiply ?
EXTRASAMPLE_ASSOCALPHA :
EXTRASAMPLE_UNASSALPHA;
TIFFSetField( tif, TIFFSetField( tif,
TIFFTAG_EXTRASAMPLES, alpha_bands, v ); TIFFTAG_EXTRASAMPLES, alpha_bands, v );
} }
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric ); TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
} }
/* Layout. /* Layout.
*/ */
if( wtiff->tile ) { if( wtiff->tile ) {
skipping to change at line 929 skipping to change at line 962
if( wtiff->tile ) if( wtiff->tile )
wtiff->tbuf = vips_malloc( NULL, wtiff->tbuf = vips_malloc( NULL,
TIFFTileSize( wtiff->layer->tif ) ); TIFFTileSize( wtiff->layer->tif ) );
else else
wtiff->tbuf = vips_malloc( NULL, wtiff->tbuf = vips_malloc( NULL,
TIFFScanlineSize( wtiff->layer->tif ) ); TIFFScanlineSize( wtiff->layer->tif ) );
if( !wtiff->tbuf ) if( !wtiff->tbuf )
return( -1 ); return( -1 );
} }
/* If we will be copying layers 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( wtiff->pyramid ) {
wtiff->compressed_buf_length = 2 * wtiff->tls * wtiff->tileh;
if( !(wtiff->compressed_buf = vips_malloc( NULL,
wtiff->compressed_buf_length )) )
return( -1 );
}
return( 0 ); return( 0 );
} }
/* Delete any temp files we wrote. /* Delete any temp files we wrote.
*/ */
static void static void
wtiff_delete_temps( Wtiff *wtiff ) wtiff_delete_temps( Wtiff *wtiff )
{ {
Layer *layer; Layer *layer;
skipping to change at line 984 skipping to change at line 1031
if( layer->below ) if( layer->below )
layer_free_all( layer->below ); layer_free_all( layer->below );
layer_free( layer ); layer_free( layer );
} }
static void static void
wtiff_free( Wtiff *wtiff ) wtiff_free( Wtiff *wtiff )
{ {
wtiff_delete_temps( wtiff ); wtiff_delete_temps( wtiff );
VIPS_UNREF( wtiff->ready ); VIPS_UNREF( wtiff->ready );
VIPS_FREE( wtiff->tbuf ); VIPS_FREE( wtiff->tbuf );
VIPS_FREEF( layer_free_all, wtiff->layer ); VIPS_FREEF( layer_free_all, wtiff->layer );
VIPS_FREE( wtiff->filename ); VIPS_FREE( wtiff->filename );
VIPS_FREE( wtiff->compressed_buf );
VIPS_FREE( wtiff ); VIPS_FREE( wtiff );
} }
static int static int
get_compression( VipsForeignTiffCompression compression ) get_compression( VipsForeignTiffCompression compression )
{ {
switch( compression ) { switch( compression ) {
case VIPS_FOREIGN_TIFF_COMPRESSION_NONE: case VIPS_FOREIGN_TIFF_COMPRESSION_NONE:
return( COMPRESSION_NONE ); return( COMPRESSION_NONE );
case VIPS_FOREIGN_TIFF_COMPRESSION_JPEG: case VIPS_FOREIGN_TIFF_COMPRESSION_JPEG:
skipping to change at line 1014 skipping to change at line 1061
case VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4: case VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4:
return( COMPRESSION_CCITTFAX4 ); return( COMPRESSION_CCITTFAX4 );
case VIPS_FOREIGN_TIFF_COMPRESSION_LZW: case VIPS_FOREIGN_TIFF_COMPRESSION_LZW:
return( COMPRESSION_LZW ); return( COMPRESSION_LZW );
#ifdef HAVE_TIFF_COMPRESSION_WEBP #ifdef HAVE_TIFF_COMPRESSION_WEBP
case VIPS_FOREIGN_TIFF_COMPRESSION_WEBP: case VIPS_FOREIGN_TIFF_COMPRESSION_WEBP:
return( COMPRESSION_WEBP ); return( COMPRESSION_WEBP );
case VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD: case VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD:
return( COMPRESSION_ZSTD ); return( COMPRESSION_ZSTD );
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/ #endif /*HAVE_TIFF_COMPRESSION_WEBP*/
case VIPS_FOREIGN_TIFF_COMPRESSION_JP2K:
return( JP2K_LOSSY );
default: default:
return( COMPRESSION_NONE ); return( COMPRESSION_NONE );
} }
} }
static int static int
get_resunit( VipsForeignTiffResunit resunit ) get_resunit( VipsForeignTiffResunit resunit )
{ {
switch( resunit ) { switch( resunit ) {
skipping to change at line 1043 skipping to change at line 1092
/* Keep -Wall happy. /* Keep -Wall happy.
*/ */
return( -1 ); return( -1 );
} }
/* Get the image ready to be written. /* Get the image ready to be written.
*/ */
static int static int
ready_to_write( Wtiff *wtiff ) ready_to_write( Wtiff *wtiff )
{ {
if( vips_check_coding_known( "vips2tiff", wtiff->input ) ) VipsImage *input;
VipsImage *x;
input = wtiff->input;
g_object_ref( input );
if( vips_check_coding_known( "vips2tiff", input ) ) {
VIPS_UNREF( input );
return( -1 ); return( -1 );
}
/* Premultiply any alpha, if necessary.
*/
if( wtiff->premultiply &&
vips_image_hasalpha( input ) ) {
VipsBandFormat start_format = input->BandFmt;
if( vips_premultiply( input, &x, NULL ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
input = x;
/* Premultiply always makes a float -- cast back again.
*/
if( vips_cast( input, &x, start_format, NULL ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
input = x;
}
/* "squash" float LAB down to LABQ. /* "squash" float LAB down to LABQ.
*/ */
if( wtiff->bitdepth && if( wtiff->bitdepth &&
wtiff->input->Bands == 3 && input->Bands == 3 &&
wtiff->input->BandFmt == VIPS_FORMAT_FLOAT && input->BandFmt == VIPS_FORMAT_FLOAT &&
wtiff->input->Type == VIPS_INTERPRETATION_LAB ) { input->Type == VIPS_INTERPRETATION_LAB ) {
if( vips_Lab2LabQ( wtiff->input, &wtiff->ready, NULL ) ) if( vips_Lab2LabQ( input, &x, NULL ) ) {
VIPS_UNREF( input );
return( -1 ); return( -1 );
wtiff->bitdepth = 0; }
} VIPS_UNREF( input );
else { input = x;
wtiff->ready = wtiff->input;
g_object_ref( wtiff->ready );
} }
wtiff->ready = input;
return( 0 ); return( 0 );
} }
static Wtiff * static Wtiff *
wtiff_new( VipsImage *input, const char *filename, wtiff_new( VipsImage *input, const char *filename,
VipsForeignTiffCompression compression, int Q, VipsForeignTiffCompression compression, int Q,
VipsForeignTiffPredictor predictor, VipsForeignTiffPredictor predictor,
const char *profile, const char *profile,
gboolean tile, int tile_width, int tile_height, gboolean tile, int tile_width, int tile_height,
gboolean pyramid, gboolean pyramid,
skipping to change at line 1082 skipping to change at line 1163
gboolean miniswhite, gboolean miniswhite,
VipsForeignTiffResunit resunit, double xres, double yres, VipsForeignTiffResunit resunit, double xres, double yres,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean properties,
gboolean strip, gboolean strip,
VipsRegionShrink region_shrink, VipsRegionShrink region_shrink,
int level, int level,
gboolean lossless, gboolean lossless,
VipsForeignDzDepth depth, VipsForeignDzDepth depth,
gboolean subifd ) gboolean subifd,
gboolean premultiply )
{ {
Wtiff *wtiff; Wtiff *wtiff;
if( !(wtiff = VIPS_NEW( NULL, Wtiff )) ) if( !(wtiff = VIPS_NEW( NULL, Wtiff )) )
return( NULL ); return( NULL );
wtiff->input = input; wtiff->input = input;
wtiff->ready = NULL; wtiff->ready = NULL;
wtiff->filename = filename ? vips_strdup( NULL, filename ) : NULL; wtiff->filename = filename ? vips_strdup( NULL, filename ) : NULL;
wtiff->layer = NULL; wtiff->layer = NULL;
wtiff->tbuf = NULL; wtiff->tbuf = NULL;
skipping to change at line 1115 skipping to change at line 1197
wtiff->profile = profile; wtiff->profile = profile;
wtiff->bigtiff = bigtiff; wtiff->bigtiff = bigtiff;
wtiff->rgbjpeg = rgbjpeg; wtiff->rgbjpeg = rgbjpeg;
wtiff->properties = properties; wtiff->properties = properties;
wtiff->strip = strip; wtiff->strip = strip;
wtiff->region_shrink = region_shrink; wtiff->region_shrink = region_shrink;
wtiff->level = level; wtiff->level = level;
wtiff->lossless = lossless; wtiff->lossless = lossless;
wtiff->depth = depth; wtiff->depth = depth;
wtiff->subifd = subifd; wtiff->subifd = subifd;
wtiff->premultiply = premultiply;
wtiff->toilet_roll = FALSE; wtiff->toilet_roll = FALSE;
wtiff->page_height = vips_image_get_page_height( input ); wtiff->page_height = vips_image_get_page_height( input );
wtiff->page_number = 0; wtiff->page_number = 0;
wtiff->n_pages = 1; wtiff->n_pages = 1;
wtiff->image_height = input->Ysize; wtiff->image_height = input->Ysize;
/* Any pre-processing on the image. /* Any pre-processing on the image.
*/ */
if( ready_to_write( wtiff ) ) { if( ready_to_write( wtiff ) ) {
wtiff_free( wtiff ); wtiff_free( wtiff );
skipping to change at line 1240 skipping to change at line 1323
if( wtiff->miniswhite && if( wtiff->miniswhite &&
(wtiff->ready->Coding != VIPS_CODING_NONE || (wtiff->ready->Coding != VIPS_CODING_NONE ||
vips_band_format_iscomplex( wtiff->ready->BandFmt ) || vips_band_format_iscomplex( wtiff->ready->BandFmt ) ||
wtiff->ready->Bands > 2) ) { wtiff->ready->Bands > 2) ) {
g_warning( "%s", g_warning( "%s",
_( "can only save non-complex greyscale images " _( "can only save non-complex greyscale images "
"as miniswhite -- disabling miniswhite" ) ); "as miniswhite -- disabling miniswhite" ) );
wtiff->miniswhite = FALSE; wtiff->miniswhite = FALSE;
} }
/* lossless is for webp only.
*/
#ifdef HAVE_TIFF_COMPRESSION_WEBP
if( wtiff->lossless ) {
if( wtiff->compression == COMPRESSION_NONE )
wtiff->compression = COMPRESSION_WEBP;
if( wtiff->compression != COMPRESSION_WEBP ) {
g_warning( "%s",
_( "lossless is for WEBP compression only" ) );
wtiff->lossless = FALSE;
}
}
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
/* Sizeof a line of bytes in the TIFF tile. /* Sizeof a line of bytes in the TIFF tile.
*/ */
if( wtiff->ready->Coding == VIPS_CODING_LABQ ) if( wtiff->ready->Coding == VIPS_CODING_LABQ )
wtiff->tls = wtiff->tilew * 3; wtiff->tls = wtiff->tilew * 3;
else if( wtiff->bitdepth == 1 ) else if( wtiff->bitdepth == 1 )
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 8 ) / 8; wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 8 ) / 8;
else if( wtiff->bitdepth == 2 ) else if( wtiff->bitdepth == 2 )
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 4 ) / 4; wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 4 ) / 4;
else if( wtiff->bitdepth == 4 ) else if( wtiff->bitdepth == 4 )
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 2 ) / 2; wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 2 ) / 2;
skipping to change at line 1492 skipping to change at line 1560
area->width * area->width *
VIPS_IMAGE_SIZEOF_PEL( wtiff->ready ) ); VIPS_IMAGE_SIZEOF_PEL( wtiff->ready ) );
q += wtiff->tls; q += wtiff->tls;
} }
} }
/* Write a set of tiles across the strip. /* Write a set of tiles across the strip.
*/ */
static int static int
wtiff_layer_write_tile( Wtiff *wtiff, Layer *layer, VipsRegion *strip ) wtiff_layer_write_tiles( Wtiff *wtiff, Layer *layer, VipsRegion *strip )
{ {
VipsImage *im = layer->image; VipsImage *im = layer->image;
VipsRect *area = &strip->valid; VipsRect *area = &strip->valid;
VipsRect image; VipsRect image;
int x; int x;
image.left = 0; image.left = 0;
image.top = 0; image.top = 0;
image.width = im->Xsize; image.width = im->Xsize;
skipping to change at line 1514 skipping to change at line 1582
for( x = 0; x < im->Xsize; x += wtiff->tilew ) { for( x = 0; x < im->Xsize; x += wtiff->tilew ) {
VipsRect tile; VipsRect tile;
tile.left = x; tile.left = x;
tile.top = area->top; tile.top = area->top;
tile.width = wtiff->tilew; tile.width = wtiff->tilew;
tile.height = wtiff->tileh; tile.height = wtiff->tileh;
vips_rect_intersectrect( &tile, &image, &tile ); vips_rect_intersectrect( &tile, &image, &tile );
/* Have to repack pixels.
*/
wtiff_pack2tiff( wtiff, layer, strip, &tile, wtiff->tbuf );
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "Writing %dx%d tile at position %dx%d to image %s\n", printf( "Writing %dx%d tile at position %dx%d to image %s\n",
tile.width, tile.height, tile.left, tile.top, tile.width, tile.height, tile.left, tile.top,
TIFFFileName( layer->tif ) ); TIFFFileName( layer->tif ) );
#endif /*DEBUG_VERBOSE*/ #endif /*DEBUG_VERBOSE*/
if( TIFFWriteTile( layer->tif, wtiff->tbuf, if( wtiff->we_compress ) {
tile.left, tile.top, 0, 0 ) < 0 ) { ttile_t tile_no = TIFFComputeTile( layer->tif,
vips_error( "vips2tiff", tile.left, tile.top, 0, 0 );
"%s", _( "TIFF write tile failed" ) );
return( -1 ); VipsTarget *target;
int result;
unsigned char *buffer;
size_t length;
target = vips_target_new_to_memory();
switch( wtiff->compression ) {
case JP2K_LOSSY:
/* Sadly chroma subsample seems not to work
* for edge tiles in tiff with jp2k
* compression, so we always pass FALSE
* instead of:
*
* !wtiff->rgbjpeg && wtiff->Q < 90,
*
* I've verified that the libvips jp2k
* encode and decode subsample operations fill
* the comps[i].data arrays correctly, so it
* seems to be a openjpeg bug.
*
* FIXME ... try again with openjpeg 2.5,
* when that comes.
*/
result = vips__foreign_load_jp2k_compress(
strip, &tile, target,
wtiff->tilew, wtiff->tileh,
!wtiff->rgbjpeg,
// !wtiff->rgbjpeg && wtiff->Q < 90,
FALSE,
wtiff->lossless,
wtiff->Q );
break;
default:
result = -1;
g_assert_not_reached();
break;
}
if( result ) {
g_object_unref( target );
return( -1 );
}
buffer = vips_target_steal( target, &length );
g_object_unref( target );
result = TIFFWriteRawTile( layer->tif, tile_no,
buffer, length );
g_free( buffer );
if( result < 0 ) {
vips_error( "vips2tiff",
"%s", _( "TIFF write tile failed" ) );
return( -1 );
}
}
else {
/* Have to repack pixels for libtiff.
*/
wtiff_pack2tiff( wtiff,
layer, strip, &tile, wtiff->tbuf );
if( TIFFWriteTile( layer->tif, wtiff->tbuf,
tile.left, tile.top, 0, 0 ) < 0 ) {
vips_error( "vips2tiff",
"%s", _( "TIFF write tile failed" ) );
return( -1 );
}
} }
} }
return( 0 ); return( 0 );
} }
/* Write tileh scanlines, less for the last strip. /* Write tileh scanlines, less for the last strip.
*/ */
static int static int
wtiff_layer_write_strip( Wtiff *wtiff, Layer *layer, VipsRegion *strip ) wtiff_layer_write_strip( Wtiff *wtiff, Layer *layer, VipsRegion *strip )
skipping to change at line 1675 skipping to change at line 1810
layer_strip_arrived( Layer *layer ) layer_strip_arrived( Layer *layer )
{ {
Wtiff *wtiff = layer->wtiff; Wtiff *wtiff = layer->wtiff;
int result; int result;
VipsRect new_strip; VipsRect new_strip;
VipsRect overlap; VipsRect overlap;
VipsRect image_area; VipsRect image_area;
if( wtiff->tile ) if( wtiff->tile )
result = wtiff_layer_write_tile( wtiff, layer, layer->strip ); result = wtiff_layer_write_tiles( wtiff, layer, layer->strip );
else else
result = wtiff_layer_write_strip( wtiff, layer, layer->strip ); result = wtiff_layer_write_strip( wtiff, layer, layer->strip );
if( result ) if( result )
return( -1 ); return( -1 );
if( layer->below && if( layer->below &&
layer_strip_shrink( layer ) ) layer_strip_shrink( layer ) )
return( -1 ); return( -1 );
/* Position our strip down the image. /* Position our strip down the image.
skipping to change at line 1806 skipping to change at line 1941
* we might have set. * we might have set.
*/ */
static int static int
wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in ) wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
{ {
uint32 ui32; uint32 ui32;
uint16 ui16; uint16 ui16;
uint16 ui16_2; uint16 ui16_2;
float f; float f;
tdata_t buf; tdata_t buf;
ttile_t tile; ttile_t tile_no;
ttile_t n; ttile_t n;
uint16 *a; uint16 *a;
/* All the fields we might have set. /* All the fields we might have set.
*/ */
CopyField( TIFFTAG_IMAGEWIDTH, ui32 ); CopyField( TIFFTAG_IMAGEWIDTH, ui32 );
CopyField( TIFFTAG_IMAGELENGTH, ui32 ); CopyField( TIFFTAG_IMAGELENGTH, ui32 );
CopyField( TIFFTAG_PLANARCONFIG, ui16 ); CopyField( TIFFTAG_PLANARCONFIG, ui16 );
CopyField( TIFFTAG_ORIENTATION, ui16 ); CopyField( TIFFTAG_ORIENTATION, ui16 );
CopyField( TIFFTAG_XRESOLUTION, f ); CopyField( TIFFTAG_XRESOLUTION, f );
skipping to change at line 1894 skipping to change at line 2029
if( !wtiff->strip ) if( !wtiff->strip )
if( wtiff_embed_profile( wtiff, out ) || if( wtiff_embed_profile( wtiff, out ) ||
wtiff_embed_xmp( wtiff, out ) || wtiff_embed_xmp( wtiff, out ) ||
wtiff_embed_iptc( wtiff, out ) || wtiff_embed_iptc( wtiff, out ) ||
wtiff_embed_photoshop( wtiff, out ) || wtiff_embed_photoshop( wtiff, out ) ||
wtiff_embed_imagedescription( wtiff, out ) ) wtiff_embed_imagedescription( wtiff, out ) )
return( -1 ); return( -1 );
buf = vips_malloc( NULL, TIFFTileSize( in ) ); buf = vips_malloc( NULL, TIFFTileSize( in ) );
n = TIFFNumberOfTiles( in ); n = TIFFNumberOfTiles( in );
for( tile = 0; tile < n; tile++ ) { for( tile_no = 0; tile_no < n; tile_no++ ) {
tsize_t len; tsize_t len;
/* It'd be good to use TIFFReadRawTile()/TIFFWtiffRawTile() len = TIFFReadRawTile( in, tile_no,
* here to save compression/decompression, but sadly it seems wtiff->compressed_buf, wtiff->compressed_buf_length );
* not to work :-( investigate at some point. if( len <= 0 ||
*/ TIFFWriteRawTile( out, tile_no,
len = TIFFReadEncodedTile( in, tile, buf, -1 ); wtiff->compressed_buf, len ) < 0 )
if( len < 0 ||
TIFFWriteEncodedTile( out, tile, buf, len ) < 0 ) {
g_free( buf );
return( -1 ); return( -1 );
}
} }
g_free( buf ); g_free( buf );
return( 0 ); return( 0 );
} }
/* Append all of the layers we wrote to the output. /* Append all of the layers we wrote to the output.
*/ */
static int static int
wtiff_gather( Wtiff *wtiff ) wtiff_gather( Wtiff *wtiff )
skipping to change at line 2088 skipping to change at line 2219
int bitdepth, int bitdepth,
gboolean miniswhite, gboolean miniswhite,
VipsForeignTiffResunit resunit, double xres, double yres, VipsForeignTiffResunit resunit, double xres, double yres,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean strip, gboolean properties, gboolean strip,
VipsRegionShrink region_shrink, VipsRegionShrink region_shrink,
int level, int level,
gboolean lossless, gboolean lossless,
VipsForeignDzDepth depth, VipsForeignDzDepth depth,
gboolean subifd ) gboolean subifd,
gboolean premultiply )
{ {
Wtiff *wtiff; Wtiff *wtiff;
#ifdef DEBUG #ifdef DEBUG
printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() ); printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() );
#endif /*DEBUG*/ #endif /*DEBUG*/
vips__tiff_init(); vips__tiff_init();
if( !(wtiff = wtiff_new( input, filename, if( !(wtiff = wtiff_new( input, filename,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, bitdepth, tile, tile_width, tile_height, pyramid, bitdepth,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless, depth, properties, strip, region_shrink, level, lossless, depth,
subifd )) ) subifd, premultiply )) )
return( -1 ); return( -1 );
if( wtiff_write_image( wtiff ) ) { if( wtiff_write_image( wtiff ) ) {
wtiff_free( wtiff ); wtiff_free( wtiff );
return( -1 ); return( -1 );
} }
wtiff_free( wtiff ); wtiff_free( wtiff );
return( 0 ); return( 0 );
skipping to change at line 2134 skipping to change at line 2266
int bitdepth, int bitdepth,
gboolean miniswhite, gboolean miniswhite,
VipsForeignTiffResunit resunit, double xres, double yres, VipsForeignTiffResunit resunit, double xres, double yres,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean strip, gboolean properties, gboolean strip,
VipsRegionShrink region_shrink, VipsRegionShrink region_shrink,
int level, int level,
gboolean lossless, gboolean lossless,
VipsForeignDzDepth depth, VipsForeignDzDepth depth,
gboolean subifd ) gboolean subifd,
gboolean premultiply )
{ {
Wtiff *wtiff; Wtiff *wtiff;
vips__tiff_init(); vips__tiff_init();
if( !(wtiff = wtiff_new( input, NULL, if( !(wtiff = wtiff_new( input, NULL,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, bitdepth, tile, tile_width, tile_height, pyramid, bitdepth,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless, depth, properties, strip, region_shrink, level, lossless, depth,
subifd )) ) subifd, premultiply )) )
return( -1 ); return( -1 );
wtiff->obuf = obuf; wtiff->obuf = obuf;
wtiff->olen = olen; wtiff->olen = olen;
if( wtiff_write_image( wtiff ) ) { if( wtiff_write_image( wtiff ) ) {
wtiff_free( wtiff ); wtiff_free( wtiff );
return( -1 ); return( -1 );
} }
 End of changes. 32 change blocks. 
55 lines changed or deleted 188 lines changed or added

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