Merge branch '8.10'
This commit is contained in:
commit
2e56828053
@ -30,6 +30,9 @@
|
|||||||
- fix includes of glib headers in C++ [lovell]
|
- fix includes of glib headers in C++ [lovell]
|
||||||
- fix build with more modern librsvg [lovell]
|
- fix build with more modern librsvg [lovell]
|
||||||
- fix a possible segv with very wide images [f1ac]
|
- fix a possible segv with very wide images [f1ac]
|
||||||
|
- revise premultiply, again [jjonesrs]
|
||||||
|
- revise profile handling in vipsthumbnail
|
||||||
|
- fix tiff deflate predictor setting [Adios]
|
||||||
|
|
||||||
18/12/20 started 8.10.5
|
18/12/20 started 8.10.5
|
||||||
- fix potential /0 in animated webp load [lovell]
|
- fix potential /0 in animated webp load [lovell]
|
||||||
|
@ -1060,7 +1060,7 @@ if test x"$with_tiff" != x"no"; then
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# WEBP in TIFF added in libtiff 4.0.10
|
# ZSTD and WEBP in TIFF added in libtiff 4.0.10
|
||||||
if test x"$with_tiff" != x"no"; then
|
if test x"$with_tiff" != x"no"; then
|
||||||
save_INCLUDES="$INCLUDES"
|
save_INCLUDES="$INCLUDES"
|
||||||
INCLUDES="$INCLUDES $TIFF_INCLUDES"
|
INCLUDES="$INCLUDES $TIFF_INCLUDES"
|
||||||
|
@ -67,7 +67,7 @@ typedef struct _VipsFlatten {
|
|||||||
*/
|
*/
|
||||||
VipsArrayDouble *background;
|
VipsArrayDouble *background;
|
||||||
|
|
||||||
/* The [double] converted to the input image format.
|
/* The [double] background converted to the input image format.
|
||||||
*/
|
*/
|
||||||
VipsPel *ink;
|
VipsPel *ink;
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
* - max_alpha defaults to 65535 for RGB16/GREY16
|
* - max_alpha defaults to 65535 for RGB16/GREY16
|
||||||
* 24/11/17 lovell
|
* 24/11/17 lovell
|
||||||
* - match normalised alpha to output type
|
* - match normalised alpha to output type
|
||||||
|
* 27/2/21 jjonesrs
|
||||||
|
* - revise range clipping and 1/x, again
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -70,7 +72,8 @@ typedef VipsConversionClass VipsUnpremultiplyClass;
|
|||||||
|
|
||||||
G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
||||||
|
|
||||||
/* Unpremultiply an N-band image.
|
/* Unpremultiply an N-band image. Don't use clip_alpha to calculate factor: we
|
||||||
|
* want over and undershoots on alpha and RGB to cancel.
|
||||||
*/
|
*/
|
||||||
#define UNPRE_MANY( IN, OUT ) { \
|
#define UNPRE_MANY( IN, OUT ) { \
|
||||||
IN * restrict p = (IN *) in; \
|
IN * restrict p = (IN *) in; \
|
||||||
@ -78,18 +81,11 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
|||||||
\
|
\
|
||||||
for( x = 0; x < width; x++ ) { \
|
for( x = 0; x < width; x++ ) { \
|
||||||
IN alpha = p[alpha_band]; \
|
IN alpha = p[alpha_band]; \
|
||||||
|
OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \
|
||||||
\
|
\
|
||||||
if( alpha != 0 ) { \
|
for( i = 0; i < alpha_band; i++ ) \
|
||||||
OUT factor = max_alpha / alpha; \
|
q[i] = factor * p[i]; \
|
||||||
\
|
q[alpha_band] = VIPS_CLIP( 0, alpha, max_alpha ); \
|
||||||
for( i = 0; i < alpha_band; i++ ) \
|
|
||||||
q[i] = factor * p[i]; \
|
|
||||||
q[alpha_band] = alpha; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
for( i = 0; i < alpha_band + 1; i++ ) \
|
|
||||||
q[i] = 0; \
|
|
||||||
\
|
|
||||||
for( i = alpha_band + 1; i < bands; i++ ) \
|
for( i = alpha_band + 1; i < bands; i++ ) \
|
||||||
q[i] = p[i]; \
|
q[i] = p[i]; \
|
||||||
\
|
\
|
||||||
@ -106,21 +102,12 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
|||||||
\
|
\
|
||||||
for( x = 0; x < width; x++ ) { \
|
for( x = 0; x < width; x++ ) { \
|
||||||
IN alpha = p[3]; \
|
IN alpha = p[3]; \
|
||||||
|
OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \
|
||||||
\
|
\
|
||||||
if( alpha != 0 ) { \
|
q[0] = factor * p[0]; \
|
||||||
OUT factor = max_alpha / alpha; \
|
q[1] = factor * p[1]; \
|
||||||
\
|
q[2] = factor * p[2]; \
|
||||||
q[0] = factor * p[0]; \
|
q[3] = VIPS_CLIP( 0, alpha, max_alpha ); \
|
||||||
q[1] = factor * p[1]; \
|
|
||||||
q[2] = factor * p[2]; \
|
|
||||||
q[3] = alpha; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
q[0] = 0; \
|
|
||||||
q[1] = 0; \
|
|
||||||
q[2] = 0; \
|
|
||||||
q[3] = 0; \
|
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
p += 4; \
|
p += 4; \
|
||||||
q += 4; \
|
q += 4; \
|
||||||
|
@ -590,8 +590,8 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
|
|||||||
* User @level to set the ZSTD compression level. Use @lossless to
|
* User @level to set the ZSTD compression level. Use @lossless to
|
||||||
* set WEBP lossless mode on. Use @Q to set the WEBP compression level.
|
* set WEBP lossless mode on. Use @Q to set the WEBP compression level.
|
||||||
*
|
*
|
||||||
* Use @predictor to set the predictor for lzw and deflate compression. It
|
* Use @predictor to set the predictor for lzw, deflate and zstd compression.
|
||||||
* defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal
|
* It defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal
|
||||||
* differencing. Please refer to the libtiff
|
* differencing. Please refer to the libtiff
|
||||||
* specifications for further discussion of various predictors.
|
* specifications for further discussion of various predictors.
|
||||||
*
|
*
|
||||||
|
@ -333,9 +333,9 @@ struct _Wtiff {
|
|||||||
VipsPel *tbuf; /* TIFF output buffer */
|
VipsPel *tbuf; /* TIFF output buffer */
|
||||||
int tls; /* Tile line size */
|
int tls; /* Tile line size */
|
||||||
|
|
||||||
int compression; /* Compression type */
|
int compression; /* libtiff compression type */
|
||||||
int Q; /* JPEG q-factor, webp level */
|
int Q; /* JPEG q-factor, webp level */
|
||||||
int predictor; /* Predictor value */
|
int predictor; /* libtiff predictor type */
|
||||||
int tile; /* Tile or not */
|
int tile; /* Tile or not */
|
||||||
int tilew, tileh; /* Tile size */
|
int tilew, tileh; /* Tile size */
|
||||||
int pyramid; /* Wtiff pyramid */
|
int pyramid; /* Wtiff pyramid */
|
||||||
@ -659,12 +659,16 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer )
|
|||||||
TIFFSetField( tif, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
TIFFSetField( tif, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
||||||
TIFFSetField( tif, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
TIFFSetField( tif, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
||||||
}
|
}
|
||||||
if( wtiff->compression == COMPRESSION_ZSTD )
|
if( wtiff->compression == COMPRESSION_ZSTD ) {
|
||||||
TIFFSetField( tif, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
TIFFSetField( tif, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
||||||
|
if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||||
|
TIFFSetField( tif,
|
||||||
|
TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||||
|
}
|
||||||
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
||||||
|
|
||||||
if( (wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE ||
|
if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE ||
|
||||||
wtiff->compression == VIPS_FOREIGN_TIFF_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 );
|
||||||
|
|
||||||
@ -1862,10 +1866,19 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
|
|||||||
TIFFSetField( out, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
TIFFSetField( out, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
||||||
TIFFSetField( out, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
TIFFSetField( out, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
||||||
}
|
}
|
||||||
if( wtiff->compression == COMPRESSION_ZSTD )
|
if( wtiff->compression == COMPRESSION_ZSTD ) {
|
||||||
TIFFSetField( out, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
TIFFSetField( out, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
||||||
|
if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||||
|
TIFFSetField( out,
|
||||||
|
TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||||
|
}
|
||||||
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
||||||
|
|
||||||
|
if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE ||
|
||||||
|
wtiff->compression == COMPRESSION_LZW) &&
|
||||||
|
wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||||
|
TIFFSetField( out, TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||||
|
|
||||||
/* We can't copy profiles or xmp :( Set again from wtiff.
|
/* We can't copy profiles or xmp :( Set again from wtiff.
|
||||||
*/
|
*/
|
||||||
if( !wtiff->strip )
|
if( !wtiff->strip )
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
* - add thumbnail_source
|
* - add thumbnail_source
|
||||||
* 2/6/20
|
* 2/6/20
|
||||||
* - add subifd pyr support
|
* - add subifd pyr support
|
||||||
|
* 27/2/21
|
||||||
|
* - simplify rules re. processing space, colour management and linear
|
||||||
|
* mode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -624,16 +627,19 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
int preshrunk_page_height;
|
int preshrunk_page_height;
|
||||||
double hshrink;
|
double hshrink;
|
||||||
double vshrink;
|
double vshrink;
|
||||||
VipsInterpretation interpretation;
|
|
||||||
|
|
||||||
/* TRUE if we've done the import of an ICC transform and still need to
|
/* TRUE if we've done the import of an ICC transform and still need to
|
||||||
* export.
|
* export.
|
||||||
*/
|
*/
|
||||||
gboolean have_imported;
|
gboolean have_imported;
|
||||||
|
|
||||||
/* TRUE if we've premultiplied and need to unpremultiply.
|
/* If we shrink in linear space, we need to return to the input
|
||||||
|
* colourspace after the shrink.
|
||||||
|
*/
|
||||||
|
VipsInterpretation input_interpretation;
|
||||||
|
|
||||||
|
/* The format we need to revert to after unpremultiply.
|
||||||
*/
|
*/
|
||||||
gboolean have_premultiplied;
|
|
||||||
VipsBandFormat unpremultiplied_format;
|
VipsBandFormat unpremultiplied_format;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -679,60 +685,78 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
in = t[12];
|
in = t[12];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In linear mode, we import right at the start.
|
/* In linear mode, we need to transform to a linear space before
|
||||||
*
|
* vips_resize().
|
||||||
* We also have to import the whole image if it's CMYK, since
|
|
||||||
* vips_colourspace() (see below) doesn't let you specify the fallback
|
|
||||||
* profile.
|
|
||||||
*
|
|
||||||
* This is only going to work for images in device space. If you have
|
|
||||||
* an image in PCS which also has an attached profile, strange things
|
|
||||||
* will happen.
|
|
||||||
*/
|
*/
|
||||||
have_imported = FALSE;
|
have_imported = FALSE;
|
||||||
if( thumbnail->linear &&
|
if( thumbnail->linear ) {
|
||||||
in->Coding == VIPS_CODING_NONE &&
|
/* If we are doing colour management (there's an import
|
||||||
(in->BandFmt == VIPS_FORMAT_UCHAR ||
|
* profile), then we can use XYZ PCS as the resize space.
|
||||||
in->BandFmt == VIPS_FORMAT_USHORT) &&
|
*/
|
||||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
if( in->Coding == VIPS_CODING_NONE &&
|
||||||
thumbnail->import_profile) ) {
|
(in->BandFmt == VIPS_FORMAT_UCHAR ||
|
||||||
g_info( "importing to XYZ PCS" );
|
in->BandFmt == VIPS_FORMAT_USHORT) &&
|
||||||
if( thumbnail->import_profile )
|
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||||
g_info( "fallback input profile %s",
|
thumbnail->import_profile) ) {
|
||||||
thumbnail->import_profile );
|
g_info( "importing to XYZ PCS" );
|
||||||
|
if( thumbnail->import_profile )
|
||||||
|
g_info( "fallback input profile %s",
|
||||||
|
thumbnail->import_profile );
|
||||||
|
|
||||||
if( vips_icc_import( in, &t[1],
|
if( vips_icc_import( in, &t[1],
|
||||||
"input_profile", thumbnail->import_profile,
|
"input_profile", thumbnail->import_profile,
|
||||||
"embedded", TRUE,
|
"embedded", TRUE,
|
||||||
"intent", thumbnail->intent,
|
"intent", thumbnail->intent,
|
||||||
"pcs", VIPS_PCS_XYZ,
|
"pcs", VIPS_PCS_XYZ,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
in = t[1];
|
||||||
|
|
||||||
in = t[1];
|
have_imported = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Otherwise, use scRGB or GREY16 for linear shrink.
|
||||||
|
*/
|
||||||
|
VipsInterpretation interpretation;
|
||||||
|
|
||||||
have_imported = TRUE;
|
/* Note the interpretation we will revert to after
|
||||||
|
* linear.
|
||||||
|
*/
|
||||||
|
input_interpretation = in->Type;
|
||||||
|
|
||||||
|
if( in->Bands < 3 )
|
||||||
|
interpretation = VIPS_INTERPRETATION_GREY16;
|
||||||
|
else
|
||||||
|
interpretation = VIPS_INTERPRETATION_scRGB;
|
||||||
|
|
||||||
|
g_info( "converting to processing space %s",
|
||||||
|
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||||
|
interpretation ) );
|
||||||
|
if( vips_colourspace( in, &t[2], interpretation,
|
||||||
|
NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* In non-linear mode, use sRGB or B_W as the processing
|
||||||
|
* space.
|
||||||
|
*/
|
||||||
|
VipsInterpretation interpretation;
|
||||||
|
|
||||||
/* To the processing colourspace. This will unpack LABQ, import CMYK,
|
if( in->Bands < 3 )
|
||||||
* etc.
|
interpretation = VIPS_INTERPRETATION_B_W;
|
||||||
*
|
else
|
||||||
* If this is a CMYK image, we need to set have_imported since we only
|
interpretation = VIPS_INTERPRETATION_sRGB;
|
||||||
* want to export at the end.
|
|
||||||
*/
|
g_info( "converting to processing space %s",
|
||||||
if( in->Type == VIPS_INTERPRETATION_CMYK )
|
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||||
have_imported = TRUE;
|
interpretation ) );
|
||||||
if( thumbnail->linear )
|
if( vips_colourspace( in, &t[2], interpretation,
|
||||||
interpretation = VIPS_INTERPRETATION_scRGB;
|
NULL ) )
|
||||||
else if( in->Bands < 3 )
|
return( -1 );
|
||||||
interpretation = VIPS_INTERPRETATION_B_W;
|
in = t[2];
|
||||||
else
|
}
|
||||||
interpretation = VIPS_INTERPRETATION_sRGB;
|
|
||||||
g_info( "converting to processing space %s",
|
|
||||||
vips_enum_nick( VIPS_TYPE_INTERPRETATION, interpretation ) );
|
|
||||||
if( vips_colourspace( in, &t[2], interpretation, NULL ) )
|
|
||||||
return( -1 );
|
|
||||||
in = t[2];
|
|
||||||
|
|
||||||
/* Shrink to preshrunk_page_height, so we work for multi-page images.
|
/* Shrink to preshrunk_page_height, so we work for multi-page images.
|
||||||
*/
|
*/
|
||||||
@ -751,23 +775,23 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
vshrink = (double) in->Ysize / target_image_height;
|
vshrink = (double) in->Ysize / target_image_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vips_premultiply() makes a float image, so when we unpremultiply
|
||||||
|
* below we must cast back to the original format. Use NOTSET to
|
||||||
|
* meran no pre/unmultiply.
|
||||||
|
*/
|
||||||
|
unpremultiplied_format = VIPS_FORMAT_NOTSET;
|
||||||
|
|
||||||
/* If there's an alpha, we have to premultiply before shrinking. See
|
/* If there's an alpha, we have to premultiply before shrinking. See
|
||||||
* https://github.com/libvips/libvips/issues/291
|
* https://github.com/libvips/libvips/issues/291
|
||||||
*/
|
*/
|
||||||
have_premultiplied = FALSE;
|
|
||||||
if( vips_image_hasalpha( in ) &&
|
if( vips_image_hasalpha( in ) &&
|
||||||
hshrink != 1.0 &&
|
hshrink != 1.0 &&
|
||||||
vshrink != 1.0 ) {
|
vshrink != 1.0 ) {
|
||||||
g_info( "premultiplying alpha" );
|
g_info( "premultiplying alpha" );
|
||||||
|
unpremultiplied_format = in->BandFmt;
|
||||||
|
|
||||||
if( vips_premultiply( in, &t[3], NULL ) )
|
if( vips_premultiply( in, &t[3], NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
have_premultiplied = TRUE;
|
|
||||||
|
|
||||||
/* vips_premultiply() makes a float image. When we
|
|
||||||
* vips_unpremultiply() below, we need to cast back to the
|
|
||||||
* pre-premultiply format.
|
|
||||||
*/
|
|
||||||
unpremultiplied_format = in->BandFmt;
|
|
||||||
in = t[3];
|
in = t[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,6 +801,14 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[4];
|
in = t[4];
|
||||||
|
|
||||||
|
if( unpremultiplied_format != VIPS_FORMAT_NOTSET ) {
|
||||||
|
g_info( "unpremultiplying alpha" );
|
||||||
|
if( vips_unpremultiply( in, &t[5], NULL ) ||
|
||||||
|
vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[6];
|
||||||
|
}
|
||||||
|
|
||||||
/* Only set page-height if we have more than one page, or this could
|
/* Only set page-height if we have more than one page, or this could
|
||||||
* accidentally turn into an animated image later.
|
* accidentally turn into an animated image later.
|
||||||
*/
|
*/
|
||||||
@ -792,21 +824,12 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
VIPS_META_PAGE_HEIGHT, output_page_height );
|
VIPS_META_PAGE_HEIGHT, output_page_height );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( have_premultiplied ) {
|
|
||||||
g_info( "unpremultiplying alpha" );
|
|
||||||
if( vips_unpremultiply( in, &t[5], NULL ) ||
|
|
||||||
vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) )
|
|
||||||
return( -1 );
|
|
||||||
in = t[6];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Colour management.
|
/* Colour management.
|
||||||
*
|
|
||||||
* If we've already imported, just export. Otherwise, we're in
|
|
||||||
* device space and we need a combined import/export to transform to
|
|
||||||
* the target space.
|
|
||||||
*/
|
*/
|
||||||
if( have_imported ) {
|
if( have_imported ) {
|
||||||
|
/* We've already imported, just export. Go to sRGB if there's
|
||||||
|
* no export profile.
|
||||||
|
*/
|
||||||
if( thumbnail->export_profile ||
|
if( thumbnail->export_profile ||
|
||||||
vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
|
vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
|
||||||
g_info( "exporting to device space with a profile" );
|
g_info( "exporting to device space with a profile" );
|
||||||
@ -825,21 +848,54 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
in = t[7];
|
in = t[7];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( thumbnail->export_profile &&
|
else if( thumbnail->export_profile ) {
|
||||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
/* Not imported, but we are doing colour management. Transform
|
||||||
thumbnail->import_profile) ) {
|
* to the output space.
|
||||||
|
*/
|
||||||
g_info( "transforming to %s", thumbnail->export_profile );
|
g_info( "transforming to %s", thumbnail->export_profile );
|
||||||
if( thumbnail->import_profile )
|
|
||||||
g_info( "fallback input profile %s",
|
|
||||||
thumbnail->import_profile );
|
|
||||||
|
|
||||||
if( vips_icc_transform( in, &t[7],
|
/* If there's some kind of import profile, we can transform to
|
||||||
thumbnail->export_profile,
|
* the output. Otherwise we have to convert to PCS and then
|
||||||
"input_profile", thumbnail->import_profile,
|
* export.
|
||||||
"intent", thumbnail->intent,
|
*/
|
||||||
"embedded", TRUE,
|
if( thumbnail->import_profile ||
|
||||||
NULL ) )
|
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||||
return( -1 );
|
thumbnail->import_profile) ) {
|
||||||
|
g_info( "transforming with supplied profiles" );
|
||||||
|
if( vips_icc_transform( in, &t[7],
|
||||||
|
thumbnail->export_profile,
|
||||||
|
"input_profile", thumbnail->import_profile,
|
||||||
|
"intent", thumbnail->intent,
|
||||||
|
"embedded", TRUE,
|
||||||
|
NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
in = t[7];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_info( "exporting with %s",
|
||||||
|
thumbnail->export_profile );
|
||||||
|
if( vips_colourspace( in, &t[7],
|
||||||
|
VIPS_INTERPRETATION_XYZ, NULL ) ||
|
||||||
|
vips_icc_export( t[7], &t[8],
|
||||||
|
"output_profile",
|
||||||
|
thumbnail->export_profile,
|
||||||
|
"intent", thumbnail->intent,
|
||||||
|
NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( thumbnail->linear ) {
|
||||||
|
/* Linear mode, no colour management. We went to scRGB for
|
||||||
|
* processing, so we now revert to the input colourspace.
|
||||||
|
*/
|
||||||
|
g_info( "reverting to input space %s",
|
||||||
|
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||||
|
input_interpretation ) );
|
||||||
|
if( vips_colourspace( in, &t[7],
|
||||||
|
input_interpretation, NULL ) )
|
||||||
|
return( -1 );
|
||||||
in = t[7];
|
in = t[7];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1368,7 +1424,7 @@ vips_thumbnail_buffer_init( VipsThumbnailBuffer *buffer )
|
|||||||
* * @intent: #VipsIntent, rendering intent
|
* * @intent: #VipsIntent, rendering intent
|
||||||
* * @option_string: %gchararray, extra loader options
|
* * @option_string: %gchararray, extra loader options
|
||||||
*
|
*
|
||||||
* Exacty as vips_thumbnail(), but read from a memory buffer. One extra
|
* Exactly as vips_thumbnail(), but read from a memory buffer. One extra
|
||||||
* optional argument, @option_string, lets you pass options to the underlying
|
* optional argument, @option_string, lets you pass options to the underlying
|
||||||
* loader.
|
* loader.
|
||||||
*
|
*
|
||||||
@ -1564,7 +1620,7 @@ vips_thumbnail_source_init( VipsThumbnailSource *source )
|
|||||||
* * @intent: #VipsIntent, rendering intent
|
* * @intent: #VipsIntent, rendering intent
|
||||||
* * @option_string: %gchararray, extra loader options
|
* * @option_string: %gchararray, extra loader options
|
||||||
*
|
*
|
||||||
* Exacty as vips_thumbnail(), but read from a source. One extra
|
* Exactly as vips_thumbnail(), but read from a source. One extra
|
||||||
* optional argument, @option_string, lets you pass options to the underlying
|
* optional argument, @option_string, lets you pass options to the underlying
|
||||||
* loader.
|
* loader.
|
||||||
*
|
*
|
||||||
@ -1671,7 +1727,7 @@ vips_thumbnail_image_init( VipsThumbnailImage *image )
|
|||||||
* * @export_profile: %gchararray, export ICC profile
|
* * @export_profile: %gchararray, export ICC profile
|
||||||
* * @intent: #VipsIntent, rendering intent
|
* * @intent: #VipsIntent, rendering intent
|
||||||
*
|
*
|
||||||
* Exacty as vips_thumbnail(), but read from an existing image.
|
* Exactly as vips_thumbnail(), but read from an existing image.
|
||||||
*
|
*
|
||||||
* This operation
|
* This operation
|
||||||
* is not able to exploit shrink-on-load features of image load libraries, so
|
* is not able to exploit shrink-on-load features of image load libraries, so
|
||||||
|
@ -42,6 +42,9 @@ BMP_FILE = os.path.join(IMAGES, "MARBLES.BMP")
|
|||||||
NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz")
|
NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz")
|
||||||
ICO_FILE = os.path.join(IMAGES, "favicon.ico")
|
ICO_FILE = os.path.join(IMAGES, "favicon.ico")
|
||||||
AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif")
|
AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif")
|
||||||
|
HEIC_FILE = os.path.join(IMAGES, "heic-orientation-6.heic")
|
||||||
|
RGBA_FILE = os.path.join(IMAGES, "rgba.png")
|
||||||
|
RGBA_CORRECT_FILE = os.path.join(IMAGES, "rgba-correct.ppm")
|
||||||
MOSAIC_FILES = [os.path.join(IMAGES, "cd1.1.jpg"), os.path.join(IMAGES, "cd1.2.jpg"),
|
MOSAIC_FILES = [os.path.join(IMAGES, "cd1.1.jpg"), os.path.join(IMAGES, "cd1.2.jpg"),
|
||||||
os.path.join(IMAGES, "cd2.1.jpg"), os.path.join(IMAGES, "cd2.2.jpg"),
|
os.path.join(IMAGES, "cd2.1.jpg"), os.path.join(IMAGES, "cd2.2.jpg"),
|
||||||
os.path.join(IMAGES, "cd3.1.jpg"), os.path.join(IMAGES, "cd3.2.jpg"),
|
os.path.join(IMAGES, "cd3.1.jpg"), os.path.join(IMAGES, "cd3.2.jpg"),
|
||||||
|
5
test/test-suite/images/rgba-correct.ppm
Normal file
5
test/test-suite/images/rgba-correct.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
test/test-suite/images/rgba.png
Normal file
BIN
test/test-suite/images/rgba.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
@ -2,7 +2,8 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import pyvips
|
import pyvips
|
||||||
from helpers import JPEG_FILE, OME_FILE, AVIF_FILE, TIF_FILE, all_formats, have
|
from helpers import JPEG_FILE, OME_FILE, HEIC_FILE, TIF_FILE, all_formats, \
|
||||||
|
have, RGBA_FILE, RGBA_CORRECT_FILE, AVIF_FILE
|
||||||
|
|
||||||
|
|
||||||
# Run a function expecting a complex image on a two-band image
|
# Run a function expecting a complex image on a two-band image
|
||||||
@ -193,6 +194,11 @@ class TestResample:
|
|||||||
im2 = pyvips.Image.thumbnail_buffer(buf, 100)
|
im2 = pyvips.Image.thumbnail_buffer(buf, 100)
|
||||||
assert abs(im1.avg() - im2.avg()) < 1
|
assert abs(im1.avg() - im2.avg()) < 1
|
||||||
|
|
||||||
|
# linear shrink should work on rgba images
|
||||||
|
im1 = pyvips.Image.thumbnail(RGBA_FILE, 64, linear=True)
|
||||||
|
im2 = pyvips.Image.new_from_file(RGBA_CORRECT_FILE)
|
||||||
|
assert abs(im1.flatten(background=255).avg() - im2.avg()) < 1
|
||||||
|
|
||||||
if have("heifload"):
|
if have("heifload"):
|
||||||
# this image is orientation 6 ... thumbnail should flip it
|
# this image is orientation 6 ... thumbnail should flip it
|
||||||
im = pyvips.Image.new_from_file(AVIF_FILE)
|
im = pyvips.Image.new_from_file(AVIF_FILE)
|
||||||
|
Loading…
Reference in New Issue
Block a user