fix black background in transparent areas
This commit is contained in:
parent
25733e7bb7
commit
73c3ea38d2
|
@ -6,6 +6,8 @@
|
||||||
*
|
*
|
||||||
* 26/11/11
|
* 26/11/11
|
||||||
* - initial version
|
* - initial version
|
||||||
|
* 27/11/11
|
||||||
|
* - fix black background in transparent areas
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -36,12 +38,18 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <openslide.h>
|
#include <openslide.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/intl.h>
|
#include <vips/intl.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
openslide_t *osr;
|
||||||
|
uint32_t background;
|
||||||
|
} ReadSlide;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_slide( VipsImage *image, openslide_t *osr )
|
close_slide( VipsImage *image, openslide_t *osr )
|
||||||
{
|
{
|
||||||
|
@ -70,10 +78,10 @@ load_header( openslide_t *osr, VipsImage *out )
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fill_region( VipsRegion *out, void *seq, void *_osr, void *unused,
|
fill_region( VipsRegion *out, void *seq, void *_rslide, void *unused,
|
||||||
gboolean *stop )
|
gboolean *stop )
|
||||||
{
|
{
|
||||||
openslide_t *osr = _osr;
|
ReadSlide *rslide = _rslide;
|
||||||
uint32_t *buf;
|
uint32_t *buf;
|
||||||
const char *error;
|
const char *error;
|
||||||
PEL *pel;
|
PEL *pel;
|
||||||
|
@ -83,32 +91,34 @@ fill_region( VipsRegion *out, void *seq, void *_osr, void *unused,
|
||||||
|
|
||||||
buf = vips_malloc( NULL, out->valid.width * out->valid.height *
|
buf = vips_malloc( NULL, out->valid.width * out->valid.height *
|
||||||
sizeof( *buf ));
|
sizeof( *buf ));
|
||||||
openslide_read_region( osr, buf, out->valid.left, out->valid.top,
|
openslide_read_region( rslide->osr, buf, out->valid.left,
|
||||||
0, out->valid.width, out->valid.height );
|
out->valid.top, 0, out->valid.width, out->valid.height );
|
||||||
for( y = 0; y < out->valid.height; y++ ) {
|
for( y = 0; y < out->valid.height; y++ ) {
|
||||||
for( x = 0; x < out->valid.width; x++ ) {
|
for( x = 0; x < out->valid.width; x++ ) {
|
||||||
/* Convert from ARGB to RGBA and undo
|
/* Convert from ARGB to RGBA and undo
|
||||||
* premultiplication.
|
* premultiplication.
|
||||||
*/
|
*/
|
||||||
sample = buf[y * out->valid.height + x];
|
|
||||||
a = sample >> 24;
|
|
||||||
if( a == 0 ) {
|
|
||||||
/* R, G, B should also be zero, so we just
|
|
||||||
* need to avoid the zero divide.
|
|
||||||
*/
|
|
||||||
a = 1;
|
|
||||||
}
|
|
||||||
pel = VIPS_REGION_ADDR( out, out->valid.left + x,
|
pel = VIPS_REGION_ADDR( out, out->valid.left + x,
|
||||||
out->valid.top + y );
|
out->valid.top + y );
|
||||||
|
sample = buf[y * out->valid.height + x];
|
||||||
|
a = sample >> 24;
|
||||||
|
if( a != 0 ) {
|
||||||
pel[0] = 255 * ((sample >> 16) & 255) / a;
|
pel[0] = 255 * ((sample >> 16) & 255) / a;
|
||||||
pel[1] = 255 * ((sample >> 8) & 255) / a;
|
pel[1] = 255 * ((sample >> 8) & 255) / a;
|
||||||
pel[2] = 255 * (sample & 255) / a;
|
pel[2] = 255 * (sample & 255) / a;
|
||||||
|
} else {
|
||||||
|
/* Use background color.
|
||||||
|
*/
|
||||||
|
pel[0] = (rslide->background >> 16) & 255;
|
||||||
|
pel[1] = (rslide->background >> 8) & 255;
|
||||||
|
pel[2] = rslide->background & 255;
|
||||||
|
}
|
||||||
pel[3] = a;
|
pel[3] = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vips_free( buf );
|
vips_free( buf );
|
||||||
|
|
||||||
error = openslide_get_error( osr );
|
error = openslide_get_error( rslide->osr );
|
||||||
if( error ) {
|
if( error ) {
|
||||||
vips_error( "im_openslide2vips", _( "reading region: %s" ),
|
vips_error( "im_openslide2vips", _( "reading region: %s" ),
|
||||||
error );
|
error );
|
||||||
|
@ -155,19 +165,31 @@ openslide2vips_header( const char *filename, VipsImage *out )
|
||||||
static int
|
static int
|
||||||
im_openslide2vips( const char *filename, VipsImage *out )
|
im_openslide2vips( const char *filename, VipsImage *out )
|
||||||
{
|
{
|
||||||
openslide_t *osr;
|
ReadSlide *rslide;
|
||||||
|
const char *background;
|
||||||
|
|
||||||
osr = openslide_open( filename );
|
rslide = VIPS_NEW( out, ReadSlide );
|
||||||
if( osr == NULL ) {
|
|
||||||
|
rslide->osr = openslide_open( filename );
|
||||||
|
if( rslide->osr == NULL ) {
|
||||||
vips_error( "im_openslide2vips", _( "failure opening slide" ));
|
vips_error( "im_openslide2vips", _( "failure opening slide" ));
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
g_signal_connect( out, "close", G_CALLBACK( close_slide ), osr );
|
g_signal_connect( out, "close", G_CALLBACK( close_slide ),
|
||||||
|
rslide->osr );
|
||||||
|
|
||||||
if( load_header( osr, out ) || vips_image_pio_output( out ))
|
background = openslide_get_property_value( rslide->osr,
|
||||||
|
OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR );
|
||||||
|
if( background != NULL )
|
||||||
|
rslide->background = strtoul( background, NULL, 16 );
|
||||||
|
else
|
||||||
|
rslide->background = 0xffffff;
|
||||||
|
|
||||||
|
if( load_header( rslide->osr, out ) || vips_image_pio_output( out ))
|
||||||
return( -1 );
|
return( -1 );
|
||||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||||
return vips_image_generate( out, NULL, fill_region, NULL, osr, NULL );
|
return vips_image_generate( out, NULL, fill_region, NULL, rslide,
|
||||||
|
NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue