add pyr tiff shrink-on-load for thumbnail
This commit is contained in:
parent
26d0e312c6
commit
6b9d89b103
@ -6,6 +6,7 @@
|
|||||||
- implement thumbnail shrink-on-load for openslide images [jcupitt]
|
- implement thumbnail shrink-on-load for openslide images [jcupitt]
|
||||||
- revise vips_cast() to improve behaviour with uint images [erdmann]
|
- revise vips_cast() to improve behaviour with uint images [erdmann]
|
||||||
- add bandand()/or()/eor() to cplusplus binding [clcaalu]
|
- add bandand()/or()/eor() to cplusplus binding [clcaalu]
|
||||||
|
- implement shrink-on-load for tiff pyramids [jcupitt]
|
||||||
|
|
||||||
23/9/18 started 8.7.1
|
23/9/18 started 8.7.1
|
||||||
- update function list in docs [janko-m]
|
- update function list in docs [janko-m]
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* 31/10/18
|
* 31/10/18
|
||||||
* - deprecate auto_rotate, add no_rotate
|
* - deprecate auto_rotate, add no_rotate
|
||||||
* - implement shrink-on-load for openslide images
|
* - implement shrink-on-load for openslide images
|
||||||
|
* 16/11/18
|
||||||
|
* - implement shrink-on-load for tiff pyramid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,6 +109,10 @@ typedef struct _VipsThumbnail {
|
|||||||
int level_width[MAX_LEVELS];
|
int level_width[MAX_LEVELS];
|
||||||
int level_height[MAX_LEVELS];
|
int level_height[MAX_LEVELS];
|
||||||
|
|
||||||
|
/* Try to get n-pages too, for pyr tiff load.
|
||||||
|
*/
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
} VipsThumbnail;
|
} VipsThumbnail;
|
||||||
|
|
||||||
typedef struct _VipsThumbnailClass {
|
typedef struct _VipsThumbnailClass {
|
||||||
@ -174,6 +180,14 @@ vips_thumbnail_read_header( VipsThumbnail *thumbnail, VipsImage *image )
|
|||||||
thumbnail->input_height = image->Ysize;
|
thumbnail->input_height = image->Ysize;
|
||||||
thumbnail->angle = vips_autorot_get_angle( image );
|
thumbnail->angle = vips_autorot_get_angle( image );
|
||||||
|
|
||||||
|
if( vips_image_get_typeof( image, "n-pages" ) ) {
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
|
if( !vips_image_get_int( image, "n-pages", &n_pages ) )
|
||||||
|
thumbnail->n_pages =
|
||||||
|
VIPS_CLIP( 1, n_pages, MAX_LEVELS );
|
||||||
|
}
|
||||||
|
|
||||||
/* For openslide, read out the level structure too.
|
/* For openslide, read out the level structure too.
|
||||||
*/
|
*/
|
||||||
if( vips_isprefix( "VipsForeignLoadOpenslide", thumbnail->loader ) ) {
|
if( vips_isprefix( "VipsForeignLoadOpenslide", thumbnail->loader ) ) {
|
||||||
@ -199,6 +213,55 @@ vips_thumbnail_read_header( VipsThumbnail *thumbnail, VipsImage *image )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This may not be a pyr tiff, so no error if we can't find the layers.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_thumbnail_get_tiff_pyramid( VipsThumbnail *thumbnail )
|
||||||
|
{
|
||||||
|
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < thumbnail->n_pages; i++ ) {
|
||||||
|
VipsImage *page;
|
||||||
|
int level_width;
|
||||||
|
int level_height;
|
||||||
|
int expected_level_width;
|
||||||
|
int expected_level_height;
|
||||||
|
|
||||||
|
if( !(page = class->open( thumbnail, i )) )
|
||||||
|
return;
|
||||||
|
level_width = page->Xsize;
|
||||||
|
level_height = page->Ysize;
|
||||||
|
VIPS_UNREF( page );
|
||||||
|
|
||||||
|
/* Try to sanity-check the size of the pages. Do they look
|
||||||
|
* like a pyramid?
|
||||||
|
*/
|
||||||
|
expected_level_width = thumbnail->input_width / (1 << i);
|
||||||
|
expected_level_height = thumbnail->input_height / (1 << i);
|
||||||
|
|
||||||
|
/* Won't be exact due to rounding etc.
|
||||||
|
*/
|
||||||
|
if( abs( level_width - expected_level_width ) > 5 ||
|
||||||
|
level_width < 2 )
|
||||||
|
return;
|
||||||
|
if( abs( level_height - expected_level_height ) > 5 ||
|
||||||
|
level_height < 2 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
thumbnail->level_width[i] = level_width;
|
||||||
|
thumbnail->level_height[i] = level_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now set level_count. This signals that we've found a pyramid.
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips_thumbnail_get_tiff_pyramid: %d layer pyramid detected\n",
|
||||||
|
thumbnail->n_pages );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
thumbnail->level_count = thumbnail->n_pages;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the shrink factor, taking into account auto-rotate, the fit mode,
|
/* Calculate the shrink factor, taking into account auto-rotate, the fit mode,
|
||||||
* and so on.
|
* and so on.
|
||||||
*
|
*
|
||||||
@ -313,7 +376,7 @@ vips_thumbnail_find_jpegshrink( VipsThumbnail *thumbnail,
|
|||||||
/* Find the best openslide level.
|
/* Find the best openslide level.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
vips_thumbnail_find_openslidelevel( VipsThumbnail *thumbnail,
|
vips_thumbnail_find_pyrlevel( VipsThumbnail *thumbnail,
|
||||||
int width, int height )
|
int width, int height )
|
||||||
{
|
{
|
||||||
int level;
|
int level;
|
||||||
@ -349,6 +412,12 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
g_info( "input size is %d x %d",
|
g_info( "input size is %d x %d",
|
||||||
thumbnail->input_width, thumbnail->input_height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
|
|
||||||
|
/* For tiff, we need to make a separate get_info() for each page to
|
||||||
|
* get all the pyramid levels.
|
||||||
|
*/
|
||||||
|
if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) )
|
||||||
|
vips_thumbnail_get_tiff_pyramid( thumbnail );
|
||||||
|
|
||||||
factor = 1.0;
|
factor = 1.0;
|
||||||
|
|
||||||
if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) {
|
if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) {
|
||||||
@ -357,12 +426,12 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
|
|
||||||
g_info( "loading jpeg with factor %g pre-shrink", factor );
|
g_info( "loading jpeg with factor %g pre-shrink", factor );
|
||||||
}
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadOpenslide",
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ||
|
||||||
thumbnail->loader ) ) {
|
vips_isprefix( "VipsForeignLoadOpenslide", thumbnail->loader ) ) {
|
||||||
factor = vips_thumbnail_find_openslidelevel( thumbnail,
|
factor = vips_thumbnail_find_pyrlevel( thumbnail,
|
||||||
thumbnail->input_width, thumbnail->input_height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
|
|
||||||
g_info( "loading openslide level %g", factor );
|
g_info( "loading pyr level %g", factor );
|
||||||
}
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) ||
|
else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) ||
|
||||||
vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) {
|
vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) {
|
||||||
@ -385,6 +454,8 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
if( !(im = class->open( thumbnail, factor )) )
|
if( !(im = class->open( thumbnail, factor )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
|
g_info( "pre-shrunk size is %d x %d", im->Xsize, im->Ysize );
|
||||||
|
|
||||||
return( im );
|
return( im );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,6 +858,12 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"scale", factor,
|
"scale", factor,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
||||||
|
return( vips_image_new_from_file( file->filename,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"page", (int) factor,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return( vips_image_new_from_file( file->filename,
|
return( vips_image_new_from_file( file->filename,
|
||||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
@ -968,6 +1045,13 @@ vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"scale", factor,
|
"scale", factor,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length, "",
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"page", (int) factor,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return( vips_image_new_from_buffer(
|
return( vips_image_new_from_buffer(
|
||||||
buffer->buf->data, buffer->buf->length, "",
|
buffer->buf->data, buffer->buf->length, "",
|
||||||
|
Loading…
Reference in New Issue
Block a user