fix composite for some combinations of blend modes

composite could get mixed up blend modes if:

- many images being composited
- some small and positioned with x/y
- at least one unskippable blend mode

phew!
This commit is contained in:
John Cupitt 2019-06-04 15:24:54 +01:00
parent 81861baee9
commit 5657099223
2 changed files with 22 additions and 12 deletions

View File

@ -2,6 +2,7 @@
- improve realpath() use on older libc - improve realpath() use on older libc
- better magickload error messages - better magickload error messages
- more consistent behaviour for page-height metadata - more consistent behaviour for page-height metadata
- fix for composite with many small images and some combinations of blend modes
21/9/18 started 8.8.0 21/9/18 started 8.8.0
- much faster smartcrop [lovell] - much faster smartcrop [lovell]

View File

@ -907,7 +907,8 @@ vips_combine_pixels( VipsCompositeSequence *seq, VipsPel *q )
B[b] *= aB; B[b] *= aB;
for( int i = 1; i < n; i++ ) { for( int i = 1; i < n; i++ ) {
VipsBlendMode m = n_mode == 1 ? mode[0] : mode[i - 1]; int j = seq->enabled[i];
VipsBlendMode m = n_mode == 1 ? mode[0] : mode[j - 1];
vips_composite_base_blend<T>( composite, m, B, tp[i] ); vips_composite_base_blend<T>( composite, m, B, tp[i] );
} }
@ -941,7 +942,7 @@ vips_combine_pixels( VipsCompositeSequence *seq, VipsPel *q )
} }
#ifdef HAVE_VECTOR_ARITH #ifdef HAVE_VECTOR_ARITH
/* Three band (four with alpha) vecvtior case. Non-double output. min_T and /* Three band (four with alpha) vector case. Non-double output. min_T and
* max_T are the numeric range for this type. 0, 0 means no limit, * max_T are the numeric range for this type. 0, 0 means no limit,
* for example float. * for example float.
*/ */
@ -975,7 +976,8 @@ vips_combine_pixels3( VipsCompositeSequence *seq, VipsPel *q )
} }
for( int i = 1; i < n; i++ ) { for( int i = 1; i < n; i++ ) {
VipsBlendMode m = n_mode == 1 ? mode[0] : mode[i - 1]; int j = seq->enabled[i];
VipsBlendMode m = n_mode == 1 ? mode[0] : mode[j - 1];
vips_composite_base_blend3<T>( composite, m, B, tp[i] ); vips_composite_base_blend3<T>( composite, m, B, tp[i] );
} }
@ -1021,10 +1023,15 @@ vips_composite_base_gen( VipsRegion *output_region,
VipsRect *r = &output_region->valid; VipsRect *r = &output_region->valid;
int ps = VIPS_IMAGE_SIZEOF_PEL( output_region->im ); int ps = VIPS_IMAGE_SIZEOF_PEL( output_region->im );
VIPS_DEBUG_MSG( "vips_composite_base_gen: at %d x %d, size %d x %d\n",
r->left, r->top, r->width, r->height );
/* Find the subset of our input images which intersect this region. /* Find the subset of our input images which intersect this region.
*/ */
vips_composite_base_select( seq, r ); vips_composite_base_select( seq, r );
VIPS_DEBUG_MSG( " selected %d images\n", seq->n );
/* Is there just one? We can prepare directly to output and return. /* Is there just one? We can prepare directly to output and return.
*/ */
if( seq->n == 1 ) { if( seq->n == 1 ) {
@ -1051,6 +1058,12 @@ vips_composite_base_gen( VipsRegion *output_region,
VipsRect hit; VipsRect hit;
VipsRect request; VipsRect request;
/* Set the composite region up to be a bit of memory at the
* right position.
*/
if( vips_region_buffer( seq->composite_regions[j], r ) )
return( -1 );
/* Clip against this subimage position and size. /* Clip against this subimage position and size.
*/ */
hit = *r; hit = *r;
@ -1062,12 +1075,6 @@ vips_composite_base_gen( VipsRegion *output_region,
request.left -= composite->subimages[j].left; request.left -= composite->subimages[j].left;
request.top -= composite->subimages[j].top; request.top -= composite->subimages[j].top;
/* Set the composite region up to be a bit of memory at the
* right position.
*/
if( vips_region_buffer( seq->composite_regions[j], r ) )
return( -1 );
/* If the request is smaller than the target region, there /* If the request is smaller than the target region, there
* will be some gaps. We must make sure these are zero. * will be some gaps. We must make sure these are zero.
*/ */
@ -1081,12 +1088,14 @@ vips_composite_base_gen( VipsRegion *output_region,
* If we are not in skippable mode, we can be completely * If we are not in skippable mode, we can be completely
* outside the subimage area. * outside the subimage area.
*/ */
if( !vips_rect_isempty( &request ) && if( !vips_rect_isempty( &request ) ) {
vips_region_prepare_to( seq->input_regions[j], VIPS_DEBUG_MSG( " fetching pixels for input %d\n", j );
if( vips_region_prepare_to( seq->input_regions[j],
seq->composite_regions[j], &request, seq->composite_regions[j], &request,
hit.left, hit.top ) ) hit.left, hit.top ) )
return( -1 ); return( -1 );
} }
}
VIPS_GATE_START( "vips_composite_base_gen: work" ); VIPS_GATE_START( "vips_composite_base_gen: work" );