sort out premultiply rules for upsizing
vips_resize() uses vips_affine() for upsizing and vips_reduce() for downsizing. Affine automaticaly does a vips_premultiply() for images with an alpha channel, but reduce does not. This meant that we could sometimes premultiply twice. This patch adds a "premultiplied" flag for affine which turns automatic premultiuplication off, vips_resize() uses this to block affine's auto premul feature, and the resize docs are clarified to stress that the operation does not do premultiplication for you. See https://github.com/libvips/libvips/issues/1629
This commit is contained in:
parent
44db1742fd
commit
ba0dea001d
@ -20,6 +20,8 @@
|
|||||||
- better handling of unaligned reads in multipage tiffs [petoor]
|
- better handling of unaligned reads in multipage tiffs [petoor]
|
||||||
- mark old --delete option to vipsthumbnail as deprecated [UweOhse]
|
- mark old --delete option to vipsthumbnail as deprecated [UweOhse]
|
||||||
- png save with a bad ICC profile just gives a warning
|
- png save with a bad ICC profile just gives a warning
|
||||||
|
- add "premultipled" option to vips_affine(), clarified vips_resize()
|
||||||
|
behaviour with alpha channels
|
||||||
|
|
||||||
24/4/20 started 8.9.3
|
24/4/20 started 8.9.3
|
||||||
- better iiif tile naming [IllyaMoskvin]
|
- better iiif tile naming [IllyaMoskvin]
|
||||||
|
@ -88,6 +88,8 @@
|
|||||||
* - add "background" parameter
|
* - add "background" parameter
|
||||||
* - better clipping means we have no jaggies on edges
|
* - better clipping means we have no jaggies on edges
|
||||||
* - premultiply alpha
|
* - premultiply alpha
|
||||||
|
* 18/5/20
|
||||||
|
* - add "premultiplied" flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -166,6 +168,10 @@ typedef struct _VipsAffine {
|
|||||||
*/
|
*/
|
||||||
VipsPel *ink;
|
VipsPel *ink;
|
||||||
|
|
||||||
|
/* True if the input is already premultiplied (and we don't need to).
|
||||||
|
*/
|
||||||
|
gboolean premultiplied;
|
||||||
|
|
||||||
} VipsAffine;
|
} VipsAffine;
|
||||||
|
|
||||||
typedef VipsResampleClass VipsAffineClass;
|
typedef VipsResampleClass VipsAffineClass;
|
||||||
@ -524,11 +530,13 @@ vips_affine_build( VipsObject *object )
|
|||||||
affine->trn.idx -= 1;
|
affine->trn.idx -= 1;
|
||||||
affine->trn.idy -= 1;
|
affine->trn.idy -= 1;
|
||||||
|
|
||||||
/* If there's an alpha, we have to premultiply before resampling. See
|
/* If there's an alpha and we've not premultiplied, we have to
|
||||||
|
* premultiply before resampling. See
|
||||||
* https://github.com/libvips/libvips/issues/291
|
* https://github.com/libvips/libvips/issues/291
|
||||||
*/
|
*/
|
||||||
have_premultiplied = FALSE;
|
have_premultiplied = FALSE;
|
||||||
if( vips_image_hasalpha( in ) ) {
|
if( vips_image_hasalpha( in ) &&
|
||||||
|
!affine->premultiplied ) {
|
||||||
if( vips_premultiply( in, &t[3], NULL ) )
|
if( vips_premultiply( in, &t[3], NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
have_premultiplied = TRUE;
|
have_premultiplied = TRUE;
|
||||||
@ -680,6 +688,13 @@ vips_affine_class_init( VipsAffineClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsAffine, background ),
|
G_STRUCT_OFFSET( VipsAffine, background ),
|
||||||
VIPS_TYPE_ARRAY_DOUBLE );
|
VIPS_TYPE_ARRAY_DOUBLE );
|
||||||
|
|
||||||
|
VIPS_ARG_BOOL( class, "premultiplied", 117,
|
||||||
|
_( "Premultiplied" ),
|
||||||
|
_( "Images have premultiplied alpha" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsAffine, premultiplied ),
|
||||||
|
FALSE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -709,6 +724,7 @@ vips_affine_init( VipsAffine *affine )
|
|||||||
* * @ody: %gdouble, output vertical offset
|
* * @ody: %gdouble, output vertical offset
|
||||||
* * @extend: #VipsExtend how to generate new pixels
|
* * @extend: #VipsExtend how to generate new pixels
|
||||||
* * @background: #VipsArrayDouble colour for new pixels
|
* * @background: #VipsArrayDouble colour for new pixels
|
||||||
|
* * @premultiplied: %gboolean, images are already premultiplied
|
||||||
*
|
*
|
||||||
* This operator performs an affine transform on an image using @interpolate.
|
* This operator performs an affine transform on an image using @interpolate.
|
||||||
*
|
*
|
||||||
@ -737,6 +753,10 @@ vips_affine_init( VipsAffine *affine )
|
|||||||
*
|
*
|
||||||
* @idx, @idy, @odx, @ody default to zero.
|
* @idx, @idy, @odx, @ody default to zero.
|
||||||
*
|
*
|
||||||
|
* Image are normally treated as unpremultiplied, so this operation can be used
|
||||||
|
* directly on PNG images. If your images have been through vips_premultiply(),
|
||||||
|
* set @premultiplied.
|
||||||
|
*
|
||||||
* This operation does not change xres or yres. The image resolution needs to
|
* This operation does not change xres or yres. The image resolution needs to
|
||||||
* be updated by the application.
|
* be updated by the application.
|
||||||
*
|
*
|
||||||
|
@ -289,6 +289,7 @@ vips_resize_build( VipsObject *object )
|
|||||||
"idx", id,
|
"idx", id,
|
||||||
"idy", id,
|
"idy", id,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
|
"premultiplied", TRUE,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[4];
|
in = t[4];
|
||||||
@ -300,6 +301,7 @@ vips_resize_build( VipsObject *object )
|
|||||||
"idx", id,
|
"idx", id,
|
||||||
"idy", id,
|
"idy", id,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
|
"premultiplied", TRUE,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[4];
|
in = t[4];
|
||||||
@ -311,6 +313,7 @@ vips_resize_build( VipsObject *object )
|
|||||||
"idx", id,
|
"idx", id,
|
||||||
"idy", id,
|
"idy", id,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
|
"premultiplied", TRUE,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[4];
|
in = t[4];
|
||||||
@ -444,7 +447,10 @@ vips_resize_init( VipsResize *resize )
|
|||||||
* This operation does not change xres or yres. The image resolution needs to
|
* This operation does not change xres or yres. The image resolution needs to
|
||||||
* be updated by the application.
|
* be updated by the application.
|
||||||
*
|
*
|
||||||
* See also: vips_shrink(), vips_reduce().
|
* This operation does not premultiply alpha. If your image has an alpha
|
||||||
|
* channel, you should use vips_premultiply() on it first.
|
||||||
|
*
|
||||||
|
* See also: vips_premultiply(), vips_shrink(), vips_reduce().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error
|
* Returns: 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user