fix up openslideload

there was a problem with the tile cache ... plus some small tidies
This commit is contained in:
John Cupitt 2011-12-12 11:34:28 +00:00
parent 230e9ce63e
commit 05fbb6b3bc
10 changed files with 47 additions and 53 deletions

View File

@ -12,7 +12,8 @@
im_rint(), im_equal*(), im_notequal*(), im_less*(), im_lesseq*(), im_more*(),
im_moreeq*(), im_remainder*(), im_and*(), im_or*(), im_eor*(), im_shift*(),
im_pow*(), im_exp*(), im_ifthenelse(), im_blend(), im_c2amph(), im_c2rect(),
im_bandmean(), im_c2real(), im_c2imag(), im_ri2c()
im_bandmean(), im_c2real(), im_c2imag(), im_ri2c(), im_jpeg*2vips(),
im_vips2jpeg*(), im_tiff2vips(), im_vips2tiff(),
redone as classes
- added argument priorites to help control arg ordering
- generate has a 'stop' param to signal successful early termination

10
TODO
View File

@ -1,10 +1,6 @@
- still some size_t that should be guint64, search for all use of
VIPS_IMAGE_SIZEOF_IMAGE(), vips__parse_size()
- some mysterious error in tilecahce for new-style openslide read
- how about
@ -18,12 +14,6 @@
- add ".ndpi" to openslide suffs? though we don't really use suffs for loaders
- check lazy load hint bug in format-hacking branch
- everywhere must set dhint in header load
- openslide sets a g_log() handler, argh, must just set temp
- make an argb coding type, add to nip2 and known coding

View File

@ -207,9 +207,7 @@ tile_fill( Tile *tile, VipsRegion *in )
{
VipsRect area;
#ifdef DEBUG
printf( "im_tile_cache: filling tile %d x %d\n", tile->x, tile->y );
#endif /*DEBUG*/
VIPS_DEBUG_MSG( "tilecache: filling tile %d x %d\n", tile->x, tile->y );
area.left = tile->x;
area.top = tile->y;
@ -270,9 +268,7 @@ tile_find( VipsTileCache *cache, VipsRegion *in, int x, int y )
g_assert( tile );
#ifdef DEBUG
printf( "im_tile_cache: reusing tile %d x %d\n", tile->x, tile->y );
#endif /*DEBUG*/
VIPS_DEBUG_MSG( "tilecache: reusing tile %d x %d\n", tile->x, tile->y );
if( tile_move( tile, x, y ) ||
tile_fill( tile, in ) )
@ -360,6 +356,8 @@ vips_tile_cache_build( VipsObject *object )
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsTileCache *cache = (VipsTileCache *) object;
VIPS_DEBUG_MSG( "vips_tile_cache_build\n" );
if( VIPS_OBJECT_CLASS( vips_tile_cache_parent_class )->build( object ) )
return( -1 );
@ -457,7 +455,7 @@ vips_tile_cache_init( VipsTileCache *cache )
* will cache up to 1,000 tiles.
*
* This is a lower-level operation than vips_image_cache() since it does no
* subdivision and it single-threads it's callee. It is suitable for caching
* subdivision and it single-threads its callee. It is suitable for caching
* the output of operations like exr2vips() on tiled images.
*
* See also: vips_image_cache().

View File

@ -1,8 +1,8 @@
noinst_LTLIBRARIES = libforeign.la
libforeign_la_SOURCES = \
vipsopenslide.h \
vipsopenslide.c \
openslide2vips.h \
openslide2vips.c \
openslideload.c \
tiff.h \
vips2tiff.c \

View File

@ -573,6 +573,10 @@ read_jpeg_header( struct jpeg_decompress_struct *cinfo,
interpretation,
1.0, 1.0 );
/* Best for us, probably.
*/
vips_demand_hint( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
/* Interlaced jpegs need lots of memory to read, so our caller needs
* to know.
*/

View File

@ -65,7 +65,7 @@
#include <openslide.h>
#include "vipsopenslide.h"
#include "openslide2vips.h"
/* We run our own tile cache. The OpenSlide one can't always keep enough for a
* complete lines of pixels.
@ -90,21 +90,19 @@ vips__openslide_isslide( const char *filename )
const char *vendor;
int ok;
ok = 1;
osr = openslide_open( filename );
if( osr != NULL ) {
/* If this is a generic tiled TIFF image, decline to support
* it, since im_tiff2vips can do better.
ok = 0;
if( (osr = openslide_open( filename )) ) {
/* Generic tiled tiff images can be opened by openslide as
* well. Only offer to load this file if it's not a generic
* tiff since we want vips_tiffload() to handle these.
*/
vendor = openslide_get_property_value( osr,
OPENSLIDE_PROPERTY_NAME_VENDOR );
if( vendor == NULL ||
strcmp( vendor, "generic-tiff" ) == 0 )
ok = 0;
if( vendor &&
strcmp( vendor, "generic-tiff" ) != 0 )
ok = 1;
openslide_close( osr );
}
else
ok = 0;
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
@ -128,7 +126,7 @@ check_associated_image( openslide_t *osr, const char *name )
if( strcmp( *associated, name ) == 0 )
return( 0 );
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
"%s", _( "invalid associated image name" ) );
return( -1 );
@ -153,21 +151,21 @@ readslide_new( const char *filename, VipsImage *out,
rslide->osr = openslide_open( filename );
if( rslide->osr == NULL ) {
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
"%s", _( "failure opening slide" ) );
return( NULL );
}
if( layer < 0 ||
layer >= openslide_get_layer_count( rslide->osr ) ) {
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
"%s", _( "invalid slide layer" ) );
return( NULL );
}
if( associated &&
check_associated_image( rslide->osr, associated ) )
return( NULL );
return( NULL );
if( associated ) {
openslide_get_associated_image_dimensions( rslide->osr,
@ -190,24 +188,24 @@ readslide_new( const char *filename, VipsImage *out,
background = openslide_get_property_value( rslide->osr,
OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR );
if( background != NULL )
im_meta_set_int( out,
vips_image_set_int( out,
"background-rgb", strtoul( background, NULL, 16 ) );
else
im_meta_set_int( out, "background-rgb", 0xffffff );
vips_image_set_int( out, "background-rgb", 0xffffff );
if( w < 0 || h < 0 || rslide->downsample < 0 ) {
vips_error( "im_openslide2vips", _( "getting dimensions: %s" ),
vips_error( "openslide2vips", _( "getting dimensions: %s" ),
openslide_get_error( rslide->osr ) );
return( NULL );
}
if( w > INT_MAX ||
h > INT_MAX ) {
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
"%s", _( "image dimensions overflow int" ) );
return( NULL );
}
vips_image_init_fields( out, (int) w, (int) h, 4, VIPS_FORMAT_UCHAR,
vips_image_init_fields( out, w, h, 4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_RGB, 1.0, 1.0 );
for( properties = openslide_get_property_names( rslide->osr );
@ -245,11 +243,11 @@ vips__openslide_generate( VipsRegion *out,
const char *error;
int x, y;
VIPS_DEBUG_MSG( "fill_region: %dx%d @ %dx%d\n",
VIPS_DEBUG_MSG( "vips__openslide_generate: %dx%d @ %dx%d\n",
r->width, r->height, r->left, r->top );
/* Fill in tile-sized chunks. Some versions of OpenSlide can fail for
* very large dimensions.
* very large requests.
*/
for( y = 0; y < r->height; y += TILE_HEIGHT )
for( x = 0; x < r->width; x += TILE_WIDTH ) {
@ -267,7 +265,7 @@ vips__openslide_generate( VipsRegion *out,
error = openslide_get_error( rslide->osr );
if( error ) {
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
_( "reading region: %s" ), error );
return( -1 );
@ -286,9 +284,9 @@ vips__openslide_read( const char *filename, VipsImage *out, int layer )
VIPS_DEBUG_MSG( "vips__openslide_read: %s %d\n",
filename, layer );
/* Tile cache: keep enough for two complete rows of tiles.
* This lets us do (smallish) area ops, like im_conv(), while
* still only hitting each tile once.
/* Tile cache: keep enough for two complete rows of tiles. OpenSlide
* has its own tile cache, but it's not large enough for a complete
* scan line.
*/
raw = vips_image_new();
vips_object_local( out, raw );
@ -307,7 +305,7 @@ vips__openslide_read( const char *filename, VipsImage *out, int layer )
if( vips_tilecache( raw, &t,
"tile_width", TILE_WIDTH,
"tile_height", TILE_WIDTH,
"max_tiles", 1.5 * (1 + raw->Xsize / TILE_WIDTH),
"max_tiles", (int) (1.5 * (1 + raw->Xsize / TILE_WIDTH)),
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
@ -344,7 +342,7 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
(uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 ) );
error = openslide_get_error( rslide->osr );
if( error ) {
vips_error( "im_openslide2vips",
vips_error( "openslide2vips",
_( "reading associated image: %s" ), error );
return( -1 );
}

View File

@ -27,8 +27,8 @@
*/
#ifndef VIPS_OPENSLIDE_H
#define VIPS_OPENSLIDE_H
#ifndef VIPS_OPENSLIDE2VIPS_H
#define VIPS_OPENSLIDE2VIPS_H
#ifdef __cplusplus
extern "C" {
@ -46,4 +46,4 @@ int vips__openslide_read_associated( const char *filename, VipsImage *out,
}
#endif /*__cplusplus*/
#endif /*VIPS_OPENSLIDE_H*/
#endif /*VIPS_OPENSLIDE2VIPS_H*/

View File

@ -47,7 +47,7 @@
#include <vips/buf.h>
#include <vips/internal.h>
#include "vipsopenslide.h"
#include "openslide2vips.h"
typedef struct _VipsForeignLoadOpenslide {
VipsForeignLoad parent_object;

View File

@ -146,6 +146,9 @@ typedef struct _VipsForeignLoadClass {
/* Set the header fields in @out from @filename. If you can read the
* whole image as well with no performance cost (as with vipsload),
* leave ->load() NULL and only @header will be used.
*
* ->header() needs to set the dhint on the image .. otherwise you get
* the default SMALLTILE.
*/
int (*header)( VipsForeignLoad * );

View File

@ -28,8 +28,8 @@
*/
/*
*/
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>