handle transparency in vips_region_shrink()
we weren't multiplying through alpha in vips_region_shrink(), causing fringing on pyramids with transparent elements thanks sickrandir! see https://github.com/jcupitt/libvips/issues/599
This commit is contained in:
parent
f84825a634
commit
4bbd56fb0a
@ -31,6 +31,7 @@
|
|||||||
- vips_gaussnoise() pixels are reproducible on recalc, thanks MvGulik
|
- vips_gaussnoise() pixels are reproducible on recalc, thanks MvGulik
|
||||||
- max/min sort values by y and x coordinate
|
- max/min sort values by y and x coordinate
|
||||||
- tiff read uses libtiff scanline API if rows-per-strip is large
|
- tiff read uses libtiff scanline API if rows-per-strip is large
|
||||||
|
- vips_region_shrink() knows about alpha, helps dzsave and tiffsave
|
||||||
|
|
||||||
8/12/16 started 8.4.5
|
8/12/16 started 8.4.5
|
||||||
- allow libgsf-1.14.26 to help centos, thanks tdiprima
|
- allow libgsf-1.14.26 to help centos, thanks tdiprima
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
* - move invalid stuff to region
|
* - move invalid stuff to region
|
||||||
* 3/3/11
|
* 3/3/11
|
||||||
* - move on top of VipsObject, rename as VipsRegion
|
* - move on top of VipsObject, rename as VipsRegion
|
||||||
|
* 23/2/17
|
||||||
|
* - multiply transparent images through alpha in vips_region_shrink()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1236,6 +1238,88 @@ vips_region_shrink_uncoded( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No point having an int path, this will always be horribly slow.
|
||||||
|
*/
|
||||||
|
#define SHRINK_ALPHA_TYPE( TYPE ) { \
|
||||||
|
TYPE *tp = (TYPE *) p; \
|
||||||
|
TYPE *tp1 = (TYPE *) (p + ls); \
|
||||||
|
TYPE *tq = (TYPE *) q; \
|
||||||
|
\
|
||||||
|
for( x = 0; x < target->width; x++ ) { \
|
||||||
|
/* Make the input alphas. \
|
||||||
|
*/ \
|
||||||
|
double a1 = tp[nb - 1]; \
|
||||||
|
double a2 = tp[nb + nb - 1]; \
|
||||||
|
double a3 = tp1[nb - 1]; \
|
||||||
|
double a4 = tp1[nb + nb - 1]; \
|
||||||
|
\
|
||||||
|
/* Output alpha. \
|
||||||
|
*/ \
|
||||||
|
double a = (a1 + a2 + a3 + a4) / 4.0; \
|
||||||
|
\
|
||||||
|
if( a == 0 ) { \
|
||||||
|
for( z = 0; z < nb; z++ ) \
|
||||||
|
tq[z] = 0; \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
for( z = 0; z < nb - 1; z++ ) \
|
||||||
|
tq[z] = (a1 * tp[z] + a2 * tp[z + nb] + \
|
||||||
|
a3 * tp1[z] + a4 * tp1[z + nb]) / \
|
||||||
|
(4.0 * a); \
|
||||||
|
tq[z] = a; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Move on two pels in input. \
|
||||||
|
*/ \
|
||||||
|
tp += nb << 1; \
|
||||||
|
tp1 += nb << 1; \
|
||||||
|
tq += nb; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate area @target in @to using pixels in @from. Non-complex. Use the
|
||||||
|
* last band as alpha.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_region_shrink_alpha( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||||
|
{
|
||||||
|
int ls = VIPS_REGION_LSKIP( from );
|
||||||
|
int nb = from->im->Bands;
|
||||||
|
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
|
for( y = 0; y < target->height; y++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( from,
|
||||||
|
target->left * 2, (target->top + y) * 2 );
|
||||||
|
VipsPel *q = VIPS_REGION_ADDR( to,
|
||||||
|
target->left, target->top + y );
|
||||||
|
|
||||||
|
/* Process this line of pels.
|
||||||
|
*/
|
||||||
|
switch( from->im->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
SHRINK_ALPHA_TYPE( unsigned char ); break;
|
||||||
|
case VIPS_FORMAT_CHAR:
|
||||||
|
SHRINK_ALPHA_TYPE( signed char ); break;
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
SHRINK_ALPHA_TYPE( unsigned short ); break;
|
||||||
|
case VIPS_FORMAT_SHORT:
|
||||||
|
SHRINK_ALPHA_TYPE( signed short ); break;
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
SHRINK_ALPHA_TYPE( unsigned int ); break;
|
||||||
|
case VIPS_FORMAT_INT:
|
||||||
|
SHRINK_ALPHA_TYPE( signed int ); break;
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
SHRINK_ALPHA_TYPE( float ); break;
|
||||||
|
case VIPS_FORMAT_DOUBLE:
|
||||||
|
SHRINK_ALPHA_TYPE( double ); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_region_shrink:
|
* vips_region_shrink:
|
||||||
* @from: source region
|
* @from: source region
|
||||||
@ -1243,7 +1327,8 @@ vips_region_shrink_uncoded( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
|||||||
* @target: #VipsRect of pixels you need to copy
|
* @target: #VipsRect of pixels you need to copy
|
||||||
*
|
*
|
||||||
* Write the pixels @target in @to from the x2 larger area in @from.
|
* Write the pixels @target in @to from the x2 larger area in @from.
|
||||||
* Non-complex uncoded images and LABQ only.
|
* Non-complex uncoded images and LABQ only. Images with alpha (see
|
||||||
|
* vips_image_hasalpha()) shrink with pixels scaled by alpha to avoid fringing.
|
||||||
*
|
*
|
||||||
* See also: vips_region_copy().
|
* See also: vips_region_copy().
|
||||||
*/
|
*/
|
||||||
@ -1259,7 +1344,10 @@ vips_region_shrink( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
|||||||
if( vips_check_noncomplex( "vips_region_shrink", image ) )
|
if( vips_check_noncomplex( "vips_region_shrink", image ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
vips_region_shrink_uncoded( from, to, target );
|
if( vips_image_hasalpha( image ) )
|
||||||
|
vips_region_shrink_alpha( from, to, target );
|
||||||
|
else
|
||||||
|
vips_region_shrink_uncoded( from, to, target );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vips_region_shrink_labpack( from, to, target );
|
vips_region_shrink_labpack( from, to, target );
|
||||||
|
Loading…
Reference in New Issue
Block a user