fix up openslideload
there was a problem with the tile cache ... plus some small tidies
This commit is contained in:
parent
230e9ce63e
commit
05fbb6b3bc
@ -12,7 +12,8 @@
|
|||||||
im_rint(), im_equal*(), im_notequal*(), im_less*(), im_lesseq*(), im_more*(),
|
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_moreeq*(), im_remainder*(), im_and*(), im_or*(), im_eor*(), im_shift*(),
|
||||||
im_pow*(), im_exp*(), im_ifthenelse(), im_blend(), im_c2amph(), im_c2rect(),
|
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
|
redone as classes
|
||||||
- added argument priorites to help control arg ordering
|
- added argument priorites to help control arg ordering
|
||||||
- generate has a 'stop' param to signal successful early termination
|
- generate has a 'stop' param to signal successful early termination
|
||||||
|
10
TODO
10
TODO
@ -1,10 +1,6 @@
|
|||||||
- still some size_t that should be guint64, search for all use of
|
- still some size_t that should be guint64, search for all use of
|
||||||
VIPS_IMAGE_SIZEOF_IMAGE(), vips__parse_size()
|
VIPS_IMAGE_SIZEOF_IMAGE(), vips__parse_size()
|
||||||
|
|
||||||
- some mysterious error in tilecahce for new-style openslide read
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- how about
|
- 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
|
- openslide sets a g_log() handler, argh, must just set temp
|
||||||
|
|
||||||
- make an argb coding type, add to nip2 and known coding
|
- make an argb coding type, add to nip2 and known coding
|
||||||
|
@ -207,9 +207,7 @@ tile_fill( Tile *tile, VipsRegion *in )
|
|||||||
{
|
{
|
||||||
VipsRect area;
|
VipsRect area;
|
||||||
|
|
||||||
#ifdef DEBUG
|
VIPS_DEBUG_MSG( "tilecache: filling tile %d x %d\n", tile->x, tile->y );
|
||||||
printf( "im_tile_cache: filling tile %d x %d\n", tile->x, tile->y );
|
|
||||||
#endif /*DEBUG*/
|
|
||||||
|
|
||||||
area.left = tile->x;
|
area.left = tile->x;
|
||||||
area.top = tile->y;
|
area.top = tile->y;
|
||||||
@ -270,9 +268,7 @@ tile_find( VipsTileCache *cache, VipsRegion *in, int x, int y )
|
|||||||
|
|
||||||
g_assert( tile );
|
g_assert( tile );
|
||||||
|
|
||||||
#ifdef DEBUG
|
VIPS_DEBUG_MSG( "tilecache: reusing tile %d x %d\n", tile->x, tile->y );
|
||||||
printf( "im_tile_cache: reusing tile %d x %d\n", tile->x, tile->y );
|
|
||||||
#endif /*DEBUG*/
|
|
||||||
|
|
||||||
if( tile_move( tile, x, y ) ||
|
if( tile_move( tile, x, y ) ||
|
||||||
tile_fill( tile, in ) )
|
tile_fill( tile, in ) )
|
||||||
@ -360,6 +356,8 @@ vips_tile_cache_build( VipsObject *object )
|
|||||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||||
VipsTileCache *cache = (VipsTileCache *) object;
|
VipsTileCache *cache = (VipsTileCache *) object;
|
||||||
|
|
||||||
|
VIPS_DEBUG_MSG( "vips_tile_cache_build\n" );
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_tile_cache_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_tile_cache_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -457,7 +455,7 @@ vips_tile_cache_init( VipsTileCache *cache )
|
|||||||
* will cache up to 1,000 tiles.
|
* will cache up to 1,000 tiles.
|
||||||
*
|
*
|
||||||
* This is a lower-level operation than vips_image_cache() since it does no
|
* 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.
|
* the output of operations like exr2vips() on tiled images.
|
||||||
*
|
*
|
||||||
* See also: vips_image_cache().
|
* See also: vips_image_cache().
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
noinst_LTLIBRARIES = libforeign.la
|
noinst_LTLIBRARIES = libforeign.la
|
||||||
|
|
||||||
libforeign_la_SOURCES = \
|
libforeign_la_SOURCES = \
|
||||||
vipsopenslide.h \
|
openslide2vips.h \
|
||||||
vipsopenslide.c \
|
openslide2vips.c \
|
||||||
openslideload.c \
|
openslideload.c \
|
||||||
tiff.h \
|
tiff.h \
|
||||||
vips2tiff.c \
|
vips2tiff.c \
|
||||||
|
@ -573,6 +573,10 @@ read_jpeg_header( struct jpeg_decompress_struct *cinfo,
|
|||||||
interpretation,
|
interpretation,
|
||||||
1.0, 1.0 );
|
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
|
/* Interlaced jpegs need lots of memory to read, so our caller needs
|
||||||
* to know.
|
* to know.
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
#include <openslide.h>
|
#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
|
/* We run our own tile cache. The OpenSlide one can't always keep enough for a
|
||||||
* complete lines of pixels.
|
* complete lines of pixels.
|
||||||
@ -90,21 +90,19 @@ vips__openslide_isslide( const char *filename )
|
|||||||
const char *vendor;
|
const char *vendor;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
ok = 1;
|
ok = 0;
|
||||||
osr = openslide_open( filename );
|
if( (osr = openslide_open( filename )) ) {
|
||||||
if( osr != NULL ) {
|
/* Generic tiled tiff images can be opened by openslide as
|
||||||
/* If this is a generic tiled TIFF image, decline to support
|
* well. Only offer to load this file if it's not a generic
|
||||||
* it, since im_tiff2vips can do better.
|
* tiff since we want vips_tiffload() to handle these.
|
||||||
*/
|
*/
|
||||||
vendor = openslide_get_property_value( osr,
|
vendor = openslide_get_property_value( osr,
|
||||||
OPENSLIDE_PROPERTY_NAME_VENDOR );
|
OPENSLIDE_PROPERTY_NAME_VENDOR );
|
||||||
if( vendor == NULL ||
|
if( vendor &&
|
||||||
strcmp( vendor, "generic-tiff" ) == 0 )
|
strcmp( vendor, "generic-tiff" ) != 0 )
|
||||||
ok = 0;
|
ok = 1;
|
||||||
openslide_close( osr );
|
openslide_close( osr );
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ok = 0;
|
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
|
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 )
|
if( strcmp( *associated, name ) == 0 )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "invalid associated image name" ) );
|
"%s", _( "invalid associated image name" ) );
|
||||||
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -153,21 +151,21 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
|
|
||||||
rslide->osr = openslide_open( filename );
|
rslide->osr = openslide_open( filename );
|
||||||
if( rslide->osr == NULL ) {
|
if( rslide->osr == NULL ) {
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "failure opening slide" ) );
|
"%s", _( "failure opening slide" ) );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( layer < 0 ||
|
if( layer < 0 ||
|
||||||
layer >= openslide_get_layer_count( rslide->osr ) ) {
|
layer >= openslide_get_layer_count( rslide->osr ) ) {
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "invalid slide layer" ) );
|
"%s", _( "invalid slide layer" ) );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( associated &&
|
if( associated &&
|
||||||
check_associated_image( rslide->osr, associated ) )
|
check_associated_image( rslide->osr, associated ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
if( associated ) {
|
if( associated ) {
|
||||||
openslide_get_associated_image_dimensions( rslide->osr,
|
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,
|
background = openslide_get_property_value( rslide->osr,
|
||||||
OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR );
|
OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR );
|
||||||
if( background != NULL )
|
if( background != NULL )
|
||||||
im_meta_set_int( out,
|
vips_image_set_int( out,
|
||||||
"background-rgb", strtoul( background, NULL, 16 ) );
|
"background-rgb", strtoul( background, NULL, 16 ) );
|
||||||
else
|
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 ) {
|
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 ) );
|
openslide_get_error( rslide->osr ) );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
if( w > INT_MAX ||
|
if( w > INT_MAX ||
|
||||||
h > INT_MAX ) {
|
h > INT_MAX ) {
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "image dimensions overflow int" ) );
|
"%s", _( "image dimensions overflow int" ) );
|
||||||
return( NULL );
|
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 );
|
VIPS_CODING_NONE, VIPS_INTERPRETATION_RGB, 1.0, 1.0 );
|
||||||
|
|
||||||
for( properties = openslide_get_property_names( rslide->osr );
|
for( properties = openslide_get_property_names( rslide->osr );
|
||||||
@ -245,11 +243,11 @@ vips__openslide_generate( VipsRegion *out,
|
|||||||
const char *error;
|
const char *error;
|
||||||
int x, y;
|
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 );
|
r->width, r->height, r->left, r->top );
|
||||||
|
|
||||||
/* Fill in tile-sized chunks. Some versions of OpenSlide can fail for
|
/* 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( y = 0; y < r->height; y += TILE_HEIGHT )
|
||||||
for( x = 0; x < r->width; x += TILE_WIDTH ) {
|
for( x = 0; x < r->width; x += TILE_WIDTH ) {
|
||||||
@ -267,7 +265,7 @@ vips__openslide_generate( VipsRegion *out,
|
|||||||
|
|
||||||
error = openslide_get_error( rslide->osr );
|
error = openslide_get_error( rslide->osr );
|
||||||
if( error ) {
|
if( error ) {
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
_( "reading region: %s" ), error );
|
_( "reading region: %s" ), error );
|
||||||
|
|
||||||
return( -1 );
|
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",
|
VIPS_DEBUG_MSG( "vips__openslide_read: %s %d\n",
|
||||||
filename, layer );
|
filename, layer );
|
||||||
|
|
||||||
/* Tile cache: keep enough for two complete rows of tiles.
|
/* Tile cache: keep enough for two complete rows of tiles. OpenSlide
|
||||||
* This lets us do (smallish) area ops, like im_conv(), while
|
* has its own tile cache, but it's not large enough for a complete
|
||||||
* still only hitting each tile once.
|
* scan line.
|
||||||
*/
|
*/
|
||||||
raw = vips_image_new();
|
raw = vips_image_new();
|
||||||
vips_object_local( out, raw );
|
vips_object_local( out, raw );
|
||||||
@ -307,7 +305,7 @@ vips__openslide_read( const char *filename, VipsImage *out, int layer )
|
|||||||
if( vips_tilecache( raw, &t,
|
if( vips_tilecache( raw, &t,
|
||||||
"tile_width", TILE_WIDTH,
|
"tile_width", TILE_WIDTH,
|
||||||
"tile_height", 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 ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips_image_write( t, out ) ) {
|
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 ) );
|
(uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 ) );
|
||||||
error = openslide_get_error( rslide->osr );
|
error = openslide_get_error( rslide->osr );
|
||||||
if( error ) {
|
if( error ) {
|
||||||
vips_error( "im_openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
_( "reading associated image: %s" ), error );
|
_( "reading associated image: %s" ), error );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
@ -27,8 +27,8 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIPS_OPENSLIDE_H
|
#ifndef VIPS_OPENSLIDE2VIPS_H
|
||||||
#define VIPS_OPENSLIDE_H
|
#define VIPS_OPENSLIDE2VIPS_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -46,4 +46,4 @@ int vips__openslide_read_associated( const char *filename, VipsImage *out,
|
|||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
#endif /*VIPS_OPENSLIDE_H*/
|
#endif /*VIPS_OPENSLIDE2VIPS_H*/
|
@ -47,7 +47,7 @@
|
|||||||
#include <vips/buf.h>
|
#include <vips/buf.h>
|
||||||
#include <vips/internal.h>
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "vipsopenslide.h"
|
#include "openslide2vips.h"
|
||||||
|
|
||||||
typedef struct _VipsForeignLoadOpenslide {
|
typedef struct _VipsForeignLoadOpenslide {
|
||||||
VipsForeignLoad parent_object;
|
VipsForeignLoad parent_object;
|
||||||
|
@ -146,6 +146,9 @@ typedef struct _VipsForeignLoadClass {
|
|||||||
/* Set the header fields in @out from @filename. If you can read the
|
/* Set the header fields in @out from @filename. If you can read the
|
||||||
* whole image as well with no performance cost (as with vipsload),
|
* whole image as well with no performance cost (as with vipsload),
|
||||||
* leave ->load() NULL and only @header will be used.
|
* 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 * );
|
int (*header)( VipsForeignLoad * );
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
|
||||||
#define VIPS_DEBUG
|
#define VIPS_DEBUG
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user