change @whole_slide to @autocrop

on seconds thoughts, make openslide crop-on-load an option, not the
default

also, clip image bounds against image size
This commit is contained in:
John Cupitt 2014-07-31 09:04:32 +01:00
parent 639c22bf53
commit 9ddca0e99e
5 changed files with 45 additions and 29 deletions

View File

@ -2,7 +2,7 @@
- fix a race in im_maxpos_avg()
- limit n_thr on tiny images
- don't exit() on memleak detected, just warn
- add "whole_slide" option to openslide load
- add "autocrop" option to openslide load
4/7/14 started 7.40.4
- fix vips_rawsave_fd(), thanks aferrero2707

View File

@ -2307,6 +2307,7 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
*
* @level: load this level
* @associated: load this associated image
* @autocrop: crop to image bounds
*
* Read a virtual slide supported by the OpenSlide library into a VIPS image.
* OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle,
@ -2324,8 +2325,7 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
* A slide's associated images are listed in the
* "slide-associated-images" metadata item.
*
* The output of this operator is in pre-multipled ARGB format. Use
* im_argb2rgba() to decode to png-style RGBA.
* The output of this operator is always RGBA.
*
* See also: vips_image_new_from_file().
*

View File

@ -42,7 +42,7 @@
* 25/1/14
* - use openslide_detect_vendor() on >= 3.4.0
* 30/7/14
* - add whole_slide toggle
* - add autocrop toggle
*/
/*
@ -94,10 +94,9 @@ typedef struct {
char *associated;
/* Normally we crop to image bounds, if set. @whole_slide means, get the
* whole image.
/* Crop to image bounds if @autocrop is set.
*/
gboolean whole_slide;
gboolean autocrop;
VipsRect bounds;
/* Only valid if associated == NULL.
@ -218,7 +217,7 @@ get_bounds( openslide_t *osr, VipsRect *rect )
static ReadSlide *
readslide_new( const char *filename, VipsImage *out,
int level, gboolean whole_slide, const char *associated )
int level, gboolean autocrop, const char *associated )
{
ReadSlide *rslide;
int64_t w, h;
@ -240,7 +239,7 @@ readslide_new( const char *filename, VipsImage *out,
rslide );
rslide->level = level;
rslide->whole_slide = whole_slide;
rslide->autocrop = autocrop;
rslide->associated = g_strdup( associated );
/* Non-crazy defaults, override below if we can.
@ -305,18 +304,35 @@ readslide_new( const char *filename, VipsImage *out,
if( value )
VIPS_DEBUG_MSG( "readslide_new: found tile-size\n" );
/* Some images have a bounds in the header. Try to crop to
* that, unless whole_slide is set.
/* Some images have a bounds in the header. Crop to
* that if autocrop is set.
*/
if( !rslide->whole_slide )
if( rslide->autocrop )
if( !get_bounds( rslide->osr, &rslide->bounds ) )
rslide->whole_slide = TRUE;
if( !rslide->whole_slide ) {
rslide->autocrop = FALSE;
if( rslide->autocrop ) {
VipsRect image;
rslide->bounds.left /= rslide->downsample;
rslide->bounds.top /= rslide->downsample;
rslide->bounds.width /= rslide->downsample;
rslide->bounds.height /= rslide->downsample;
/* Clip against image size.
*/
image.left = 0;
image.top = 0;
image.width = w;
image.height = h;
vips_rect_intersectrect( &rslide->bounds, &image,
&rslide->bounds );
/* If we've clipped to nothing, ignore bounds.
*/
if( vips_rect_isempty( &rslide->bounds ) )
rslide->autocrop = FALSE;
}
if( rslide->autocrop ) {
w = rslide->bounds.width;
h = rslide->bounds.height;
}
@ -341,7 +357,7 @@ readslide_new( const char *filename, VipsImage *out,
return( NULL );
}
if( rslide->whole_slide ) {
if( !rslide->autocrop ) {
rslide->bounds.left = 0;
rslide->bounds.top = 0;
rslide->bounds.width = w;
@ -366,9 +382,9 @@ readslide_new( const char *filename, VipsImage *out,
int
vips__openslide_read_header( const char *filename, VipsImage *out,
int level, gboolean whole_slide, char *associated )
int level, gboolean autocrop, char *associated )
{
if( !readslide_new( filename, out, level, whole_slide, associated ) )
if( !readslide_new( filename, out, level, autocrop, associated ) )
return( -1 );
return( 0 );
@ -457,7 +473,7 @@ vips__openslide_generate( VipsRegion *out,
int
vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean whole_slide )
int level, gboolean autocrop )
{
ReadSlide *rslide;
VipsImage *raw;
@ -470,7 +486,7 @@ vips__openslide_read( const char *filename, VipsImage *out,
vips_object_local( out, raw );
if( !(rslide = readslide_new( filename, raw,
level, whole_slide, NULL )) )
level, autocrop, NULL )) )
return( -1 );
if( vips_image_generate( raw,

View File

@ -37,9 +37,9 @@ extern "C" {
int vips__openslide_isslide( const char *filename );
int vips__openslide_read_header( const char *filename, VipsImage *out,
int level, gboolean whole_slide, char *associated );
int level, gboolean autocrop, char *associated );
int vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean whole_slide );
int level, gboolean autocrop );
int vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated );

View File

@ -70,9 +70,9 @@ typedef struct _VipsForeignLoadOpenslide {
*/
int level;
/* Don't crop to image bounds.
/* Crop to image bounds.
*/
gboolean whole_slide;
gboolean autocrop;
/* Load this associated image.
*/
@ -113,7 +113,7 @@ vips_foreign_load_openslide_header( VipsForeignLoad *load )
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( vips__openslide_read_header( openslide->filename, load->out,
openslide->level, openslide->whole_slide,
openslide->level, openslide->autocrop,
openslide->associated ) )
return( -1 );
@ -129,7 +129,7 @@ vips_foreign_load_openslide_load( VipsForeignLoad *load )
if( !openslide->associated ) {
if( vips__openslide_read( openslide->filename, load->real,
openslide->level, openslide->whole_slide ) )
openslide->level, openslide->autocrop ) )
return( -1 );
}
else {
@ -195,11 +195,11 @@ vips_foreign_load_openslide_class_init( VipsForeignLoadOpenslideClass *class )
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, level ),
0, 100000, 0 );
VIPS_ARG_BOOL( class, "whole_slide", 11,
_( "Whole slide" ),
_( "Output entire side area" ),
VIPS_ARG_BOOL( class, "autocrop", 11,
_( "Autocrop" ),
_( "Crop to image bounds" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, whole_slide ),
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, autocrop ),
FALSE );
VIPS_ARG_STRING( class, "associated", 12,