seems to be done!
This commit is contained in:
parent
2b72244a45
commit
79c21dfcf8
@ -25,7 +25,7 @@
|
|||||||
- add compute reordering, plus some new API to support it:
|
- add compute reordering, plus some new API to support it:
|
||||||
vips_reorder_margin_hint() and vips_reorder_prepare_many(), thanks
|
vips_reorder_margin_hint() and vips_reorder_prepare_many(), thanks
|
||||||
aferrero2707
|
aferrero2707
|
||||||
- kick jpg, tif, png load operations from cache on read error, thanks gaillard
|
- kick load operations from cache on read error, thanks gaillard
|
||||||
|
|
||||||
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
|
||||||
|
14
TODO
14
TODO
@ -1,17 +1,3 @@
|
|||||||
|
|
||||||
- jpegload should put a pointer to the load operation inside the output image
|
|
||||||
somewhere
|
|
||||||
|
|
||||||
can we do this in the base class?
|
|
||||||
|
|
||||||
then the loaders can use this if they get a read error from the lib to
|
|
||||||
invalidate the load operation and knock it out of cache
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- not sure about utf8 error messages on win
|
- not sure about utf8 error messages on win
|
||||||
|
|
||||||
- strange:
|
- strange:
|
||||||
|
@ -1021,7 +1021,7 @@ vips_foreign_load_init( VipsForeignLoad *load )
|
|||||||
*
|
*
|
||||||
* Loaders can call this on the image they are making if they see a read error
|
* Loaders can call this on the image they are making if they see a read error
|
||||||
* from the load library. It signals "invalidate" on the load operation and
|
* from the load library. It signals "invalidate" on the load operation and
|
||||||
* will cause it for be dropped from cache.
|
* will cause it to be dropped from cache.
|
||||||
*
|
*
|
||||||
* If we know a file will cause a read error, we don't want to cache the
|
* If we know a file will cause a read error, we don't want to cache the
|
||||||
* failing operation, we want to make sure the image will really be opened
|
* failing operation, we want to make sure the image will really be opened
|
||||||
|
@ -718,6 +718,7 @@ magick_fill_region( VipsRegion *out,
|
|||||||
g_mutex_unlock( read->lock );
|
g_mutex_unlock( read->lock );
|
||||||
|
|
||||||
if( !pixels ) {
|
if( !pixels ) {
|
||||||
|
vips_foreign_load_invalidate( read->im );
|
||||||
vips_error( "magick2vips",
|
vips_error( "magick2vips",
|
||||||
"%s", _( "unable to read pixels" ) );
|
"%s", _( "unable to read pixels" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -285,6 +285,7 @@ vips__openexr_generate( VipsRegion *out,
|
|||||||
(read->window.left + x) -
|
(read->window.left + x) -
|
||||||
(read->window.top + y) * tw,
|
(read->window.top + y) * tw,
|
||||||
1, tw ) ) {
|
1, tw ) ) {
|
||||||
|
vips_foreign_load_invalidate( read->out );
|
||||||
get_imf_error();
|
get_imf_error();
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
* - do argb -> rgba for associated as well
|
* - do argb -> rgba for associated as well
|
||||||
* 27/1/15
|
* 27/1/15
|
||||||
* - unpremultiplication speedups for fully opaque/transparent pixels
|
* - unpremultiplication speedups for fully opaque/transparent pixels
|
||||||
|
* 18/1/17
|
||||||
|
* - reorganise to support invalidate on read error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -94,18 +96,22 @@
|
|||||||
#include <openslide.h>
|
#include <openslide.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
openslide_t *osr;
|
/* Params.
|
||||||
|
*/
|
||||||
|
char *filename;
|
||||||
|
VipsImage *out;
|
||||||
|
int32_t level;
|
||||||
|
gboolean autocrop;
|
||||||
char *associated;
|
char *associated;
|
||||||
|
|
||||||
|
openslide_t *osr;
|
||||||
|
|
||||||
/* Crop to image bounds if @autocrop is set.
|
/* Crop to image bounds if @autocrop is set.
|
||||||
*/
|
*/
|
||||||
gboolean autocrop;
|
|
||||||
VipsRect bounds;
|
VipsRect bounds;
|
||||||
|
|
||||||
/* Only valid if associated == NULL.
|
/* Only valid if associated == NULL.
|
||||||
*/
|
*/
|
||||||
int32_t level;
|
|
||||||
double downsample;
|
double downsample;
|
||||||
uint32_t bg;
|
uint32_t bg;
|
||||||
|
|
||||||
@ -171,6 +177,8 @@ readslide_destroy_cb( VipsImage *image, ReadSlide *rslide )
|
|||||||
{
|
{
|
||||||
VIPS_FREEF( openslide_close, rslide->osr );
|
VIPS_FREEF( openslide_close, rslide->osr );
|
||||||
VIPS_FREE( rslide->associated );
|
VIPS_FREE( rslide->associated );
|
||||||
|
VIPS_FREE( rslide->filename );
|
||||||
|
VIPS_FREE( rslide );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -224,11 +232,6 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
int level, gboolean autocrop, const char *associated )
|
int level, gboolean autocrop, const char *associated )
|
||||||
{
|
{
|
||||||
ReadSlide *rslide;
|
ReadSlide *rslide;
|
||||||
int64_t w, h;
|
|
||||||
const char *error;
|
|
||||||
const char *background;
|
|
||||||
const char * const *properties;
|
|
||||||
char *associated_names;
|
|
||||||
|
|
||||||
if( level &&
|
if( level &&
|
||||||
associated ) {
|
associated ) {
|
||||||
@ -238,72 +241,86 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
rslide = VIPS_NEW( out, ReadSlide );
|
rslide = VIPS_NEW( NULL, ReadSlide );
|
||||||
memset( rslide, 0, sizeof( *rslide ) );
|
memset( rslide, 0, sizeof( *rslide ) );
|
||||||
g_signal_connect( out, "close", G_CALLBACK( readslide_destroy_cb ),
|
g_signal_connect( out, "close", G_CALLBACK( readslide_destroy_cb ),
|
||||||
rslide );
|
rslide );
|
||||||
|
|
||||||
|
rslide->filename = g_strdup( filename );
|
||||||
|
rslide->out = out;
|
||||||
rslide->level = level;
|
rslide->level = level;
|
||||||
rslide->autocrop = autocrop;
|
rslide->autocrop = autocrop;
|
||||||
rslide->associated = g_strdup( associated );
|
rslide->associated = g_strdup( associated );
|
||||||
|
|
||||||
/* Non-crazy defaults, override below if we can.
|
/* Non-crazy defaults, override in _parse() if we can.
|
||||||
*/
|
*/
|
||||||
rslide->tile_width = 256;
|
rslide->tile_width = 256;
|
||||||
rslide->tile_height = 256;
|
rslide->tile_height = 256;
|
||||||
|
|
||||||
rslide->osr = openslide_open( filename );
|
return( rslide );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
readslide_parse( ReadSlide *rslide, VipsImage *image )
|
||||||
|
{
|
||||||
|
int64_t w, h;
|
||||||
|
const char *error;
|
||||||
|
const char *background;
|
||||||
|
const char * const *properties;
|
||||||
|
char *associated_names;
|
||||||
|
|
||||||
|
rslide->osr = openslide_open( rslide->filename );
|
||||||
if( rslide->osr == NULL ) {
|
if( rslide->osr == NULL ) {
|
||||||
vips_error( "openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "unsupported slide format" ) );
|
"%s", _( "unsupported slide format" ) );
|
||||||
return( NULL );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
error = openslide_get_error( rslide->osr );
|
error = openslide_get_error( rslide->osr );
|
||||||
if( error ) {
|
if( error ) {
|
||||||
vips_error( "openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
_( "opening slide: %s" ), error );
|
_( "opening slide: %s" ), error );
|
||||||
return( NULL );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( level < 0 ||
|
if( rslide->level < 0 ||
|
||||||
level >= openslide_get_level_count( rslide->osr ) ) {
|
rslide->level >= openslide_get_level_count( rslide->osr ) ) {
|
||||||
vips_error( "openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "invalid slide level" ) );
|
"%s", _( "invalid slide level" ) );
|
||||||
return( NULL );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( associated &&
|
if( rslide->associated &&
|
||||||
check_associated_image( rslide->osr, associated ) )
|
check_associated_image( rslide->osr, rslide->associated ) )
|
||||||
return( NULL );
|
return( -1 );
|
||||||
|
|
||||||
if( associated ) {
|
if( rslide->associated ) {
|
||||||
openslide_get_associated_image_dimensions( rslide->osr,
|
openslide_get_associated_image_dimensions( rslide->osr,
|
||||||
associated, &w, &h );
|
rslide->associated, &w, &h );
|
||||||
vips_image_set_string( out, "slide-associated-image",
|
vips_image_set_string( image, "slide-associated-image",
|
||||||
associated );
|
rslide->associated );
|
||||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
openslide_get_level_dimensions( rslide->osr,
|
openslide_get_level_dimensions( rslide->osr,
|
||||||
level, &w, &h );
|
rslide->level, &w, &h );
|
||||||
rslide->downsample = openslide_get_level_downsample(
|
rslide->downsample = openslide_get_level_downsample(
|
||||||
rslide->osr, level );
|
rslide->osr, rslide->level );
|
||||||
vips_image_set_int( out, "slide-level", level );
|
vips_image_set_int( image, "slide-level", rslide->level );
|
||||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||||
|
|
||||||
/* Try to get tile width/height. An undocumented, experimental
|
/* Try to get tile width/height. An undocumented, experimental
|
||||||
* feature.
|
* feature.
|
||||||
*/
|
*/
|
||||||
vips_snprintf( buf, 256,
|
vips_snprintf( buf, 256,
|
||||||
"openslide.level[%d].tile-width", level );
|
"openslide.level[%d].tile-width", rslide->level );
|
||||||
if( (value = openslide_get_property_value( rslide->osr, buf )) )
|
if( (value = openslide_get_property_value( rslide->osr, buf )) )
|
||||||
rslide->tile_width = atoi( value );
|
rslide->tile_width = atoi( value );
|
||||||
vips_snprintf( buf, 256,
|
vips_snprintf( buf, 256,
|
||||||
"openslide.level[%d].tile-height", level );
|
"openslide.level[%d].tile-height", rslide->level );
|
||||||
if( (value = openslide_get_property_value( rslide->osr, buf )) )
|
if( (value = openslide_get_property_value( rslide->osr, buf )) )
|
||||||
rslide->tile_height = atoi( value );
|
rslide->tile_height = atoi( value );
|
||||||
if( value )
|
if( value )
|
||||||
@ -316,7 +333,7 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
if( !get_bounds( rslide->osr, &rslide->bounds ) )
|
if( !get_bounds( rslide->osr, &rslide->bounds ) )
|
||||||
rslide->autocrop = FALSE;
|
rslide->autocrop = FALSE;
|
||||||
if( rslide->autocrop ) {
|
if( rslide->autocrop ) {
|
||||||
VipsRect image;
|
VipsRect whole;
|
||||||
|
|
||||||
rslide->bounds.left /= rslide->downsample;
|
rslide->bounds.left /= rslide->downsample;
|
||||||
rslide->bounds.top /= rslide->downsample;
|
rslide->bounds.top /= rslide->downsample;
|
||||||
@ -325,11 +342,11 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
|
|
||||||
/* Clip against image size.
|
/* Clip against image size.
|
||||||
*/
|
*/
|
||||||
image.left = 0;
|
whole.left = 0;
|
||||||
image.top = 0;
|
whole.top = 0;
|
||||||
image.width = w;
|
whole.width = w;
|
||||||
image.height = h;
|
whole.height = h;
|
||||||
vips_rect_intersectrect( &rslide->bounds, &image,
|
vips_rect_intersectrect( &rslide->bounds, &whole,
|
||||||
&rslide->bounds );
|
&rslide->bounds );
|
||||||
|
|
||||||
/* If we've clipped to nothing, ignore bounds.
|
/* If we've clipped to nothing, ignore bounds.
|
||||||
@ -353,13 +370,13 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
rslide->downsample < 0 ) {
|
rslide->downsample < 0 ) {
|
||||||
vips_error( "openslide2vips", _( "getting dimensions: %s" ),
|
vips_error( "openslide2vips", _( "getting dimensions: %s" ),
|
||||||
openslide_get_error( rslide->osr ) );
|
openslide_get_error( rslide->osr ) );
|
||||||
return( NULL );
|
return( -1 );
|
||||||
}
|
}
|
||||||
if( w > INT_MAX ||
|
if( w > INT_MAX ||
|
||||||
h > INT_MAX ) {
|
h > INT_MAX ) {
|
||||||
vips_error( "openslide2vips",
|
vips_error( "openslide2vips",
|
||||||
"%s", _( "image dimensions overflow int" ) );
|
"%s", _( "image dimensions overflow int" ) );
|
||||||
return( NULL );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !rslide->autocrop ) {
|
if( !rslide->autocrop ) {
|
||||||
@ -369,29 +386,33 @@ readslide_new( const char *filename, VipsImage *out,
|
|||||||
rslide->bounds.height = h;
|
rslide->bounds.height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
vips_image_init_fields( out, w, h, 4, VIPS_FORMAT_UCHAR,
|
vips_image_init_fields( image, 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 );
|
||||||
*properties != NULL; properties++ )
|
*properties != NULL; properties++ )
|
||||||
vips_image_set_string( out, *properties,
|
vips_image_set_string( image, *properties,
|
||||||
openslide_get_property_value( rslide->osr,
|
openslide_get_property_value( rslide->osr,
|
||||||
*properties ) );
|
*properties ) );
|
||||||
|
|
||||||
associated_names = g_strjoinv( ", ", (char **)
|
associated_names = g_strjoinv( ", ", (char **)
|
||||||
openslide_get_associated_image_names( rslide->osr ) );
|
openslide_get_associated_image_names( rslide->osr ) );
|
||||||
vips_image_set_string( out,
|
vips_image_set_string( image,
|
||||||
"slide-associated-images", associated_names );
|
"slide-associated-images", associated_names );
|
||||||
VIPS_FREE( associated_names );
|
VIPS_FREE( associated_names );
|
||||||
|
|
||||||
return( rslide );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips__openslide_read_header( const char *filename, VipsImage *out,
|
vips__openslide_read_header( const char *filename, VipsImage *out,
|
||||||
int level, gboolean autocrop, char *associated )
|
int level, gboolean autocrop, char *associated )
|
||||||
{
|
{
|
||||||
if( !readslide_new( filename, out, level, autocrop, associated ) )
|
ReadSlide *rslide;
|
||||||
|
|
||||||
|
if( !(rslide = readslide_new( filename,
|
||||||
|
out, level, autocrop, associated )) ||
|
||||||
|
readslide_parse( rslide, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -503,15 +524,15 @@ vips__openslide_read( const char *filename, VipsImage *out,
|
|||||||
VIPS_DEBUG_MSG( "vips__openslide_read: %s %d\n",
|
VIPS_DEBUG_MSG( "vips__openslide_read: %s %d\n",
|
||||||
filename, level );
|
filename, level );
|
||||||
|
|
||||||
|
if( !(rslide = readslide_new( filename, out, level, autocrop, NULL )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
raw = vips_image_new();
|
raw = vips_image_new();
|
||||||
vips_object_local( out, raw );
|
vips_object_local( out, raw );
|
||||||
|
|
||||||
if( !(rslide = readslide_new( filename, raw,
|
if( readslide_parse( rslide, raw ) ||
|
||||||
level, autocrop, NULL )) )
|
vips_image_generate( raw,
|
||||||
return( -1 );
|
NULL, vips__openslide_generate, NULL, rslide, NULL ) )
|
||||||
|
|
||||||
if( vips_image_generate( raw,
|
|
||||||
NULL, vips__openslide_generate, NULL, rslide, NULL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Copy to out, adding a cache. Enough tiles for a complete row, plus
|
/* Copy to out, adding a cache. Enough tiles for a complete row, plus
|
||||||
@ -546,14 +567,18 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
|
|||||||
VIPS_DEBUG_MSG( "vips__openslide_read_associated: %s %s\n",
|
VIPS_DEBUG_MSG( "vips__openslide_read_associated: %s %s\n",
|
||||||
filename, associated );
|
filename, associated );
|
||||||
|
|
||||||
|
if( !(rslide = readslide_new( filename, out, 0, FALSE, associated )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
/* Memory buffer. Get associated directly to this, then copy to out.
|
/* Memory buffer. Get associated directly to this, then copy to out.
|
||||||
*/
|
*/
|
||||||
raw = vips_image_new_memory();
|
raw = vips_image_new_memory();
|
||||||
vips_object_local( out, raw );
|
vips_object_local( out, raw );
|
||||||
|
|
||||||
if( !(rslide = readslide_new( filename, raw, 0, FALSE, associated )) ||
|
if( readslide_parse( rslide, raw ) ||
|
||||||
vips_image_write_prepare( raw ) )
|
vips_image_write_prepare( raw ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
buf = (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 );
|
buf = (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 );
|
||||||
openslide_read_associated_image( rslide->osr, rslide->associated, buf );
|
openslide_read_associated_image( rslide->osr, rslide->associated, buf );
|
||||||
error = openslide_get_error( rslide->osr );
|
error = openslide_get_error( rslide->osr );
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
* - from svgload.c
|
* - from svgload.c
|
||||||
* 1/8/16 felixbuenemann
|
* 1/8/16 felixbuenemann
|
||||||
* - add svgz support
|
* - add svgz support
|
||||||
|
* 18/1/17
|
||||||
|
* - invalidate operation on read error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -200,6 +202,7 @@ vips_foreign_load_svg_generate( VipsRegion *or,
|
|||||||
* running inside a non-threaded tilecache.
|
* running inside a non-threaded tilecache.
|
||||||
*/
|
*/
|
||||||
if( !rsvg_handle_render_cairo( svg->page, cr ) ) {
|
if( !rsvg_handle_render_cairo( svg->page, cr ) ) {
|
||||||
|
vips_operation_invalidate( VIPS_OPERATION( svg ) );
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
"%s", _( "SVG rendering failed" ) );
|
"%s", _( "SVG rendering failed" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -229,6 +229,8 @@ gboolean vips_foreign_is_a( const char *loader, const char *filename );
|
|||||||
gboolean vips_foreign_is_a_buffer( const char *loader,
|
gboolean vips_foreign_is_a_buffer( const char *loader,
|
||||||
const void *data, size_t size );
|
const void *data, size_t size );
|
||||||
|
|
||||||
|
void vips_foreign_load_invalidate( VipsImage *image );
|
||||||
|
|
||||||
#define VIPS_TYPE_FOREIGN_SAVE (vips_foreign_save_get_type())
|
#define VIPS_TYPE_FOREIGN_SAVE (vips_foreign_save_get_type())
|
||||||
#define VIPS_FOREIGN_SAVE( obj ) \
|
#define VIPS_FOREIGN_SAVE( obj ) \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
|
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
|
||||||
|
@ -244,7 +244,6 @@ typedef struct _VipsImagePixels {
|
|||||||
gint64 npels; /* Number of pels calculated so far */
|
gint64 npels; /* Number of pels calculated so far */
|
||||||
} VipsImagePixels;
|
} VipsImagePixels;
|
||||||
|
|
||||||
void vips_foreign_load_invalidate( VipsImage *image );
|
|
||||||
int vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
|
int vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
|
||||||
VipsSaveable saveable, VipsBandFormat *format, VipsCoding *coding,
|
VipsSaveable saveable, VipsBandFormat *format, VipsCoding *coding,
|
||||||
VipsArrayDouble *background );
|
VipsArrayDouble *background );
|
||||||
|
Loading…
Reference in New Issue
Block a user