more sequential improvements

always do everything on first pixel access if there's a @load() method
This commit is contained in:
John Cupitt 2012-02-16 16:04:19 +00:00
parent b6c56e980c
commit f38c94ca65
3 changed files with 58 additions and 78 deletions

View File

@ -684,7 +684,27 @@ vips_foreign_load_temp( VipsForeignLoad *load )
const guint64 disc_threshold = vips_get_disc_threshold();
const guint64 image_size = VIPS_IMAGE_SIZEOF_IMAGE( load->out );
VipsImage *temp;
/* If this is a partial operation, we can open directly.
*/
if( load->flags & VIPS_FOREIGN_PARTIAL ) {
#ifdef DEBUG
printf( "vips_foreign_load_temp: partial temp\n" );
#endif /*DEBUG*/
return( vips_image_new() );
}
/* If it can do sequential access and it's been requested, we can open
* directly.
*/
if( (load->flags & VIPS_FOREIGN_SEQUENTIAL) &&
load->sequential ) {
#ifdef DEBUG
printf( "vips_foreign_load_temp: partial sequential temp\n" );
#endif /*DEBUG*/
return( vips_image_new() );
}
/* We open via disc if:
* - 'disc' is set
@ -696,23 +716,19 @@ vips_foreign_load_temp( VipsForeignLoad *load )
disc_threshold &&
image_size > disc_threshold ) {
#ifdef DEBUG
printf( "vips_foreign_load_temp: making disc temp\n" );
printf( "vips_foreign_load_temp: disc temp\n" );
#endif /*DEBUG*/
if( !(temp = vips_image_new_disc_temp( "%s.v" )) )
return( NULL );
return( vips_image_new_disc_temp( "%s.v" ) );
}
else {
#ifdef DEBUG
printf( "vips_foreign_load_start: making 'p' temp\n" );
printf( "vips_foreign_load_temp: memory temp\n" );
#endif /*DEBUG*/
/* Otherwise, fall back to a "p".
*/
temp = vips_image_new();
}
return( temp );
/* Otherwise, fall back to a memory buffer.
*/
return( vips_image_new_buffer() );
}
/* Check two images for compatibility: their geometries need to match.
@ -839,48 +855,12 @@ vips_foreign_load_build( VipsObject *object )
* everything. Otherwise, it's just set fields and we must also
* load pixels.
*
* If it's a partial loader, or if it's a sequiential loader and
* sequential load has been requested, we can load here.
*
* Otherwise, it's a whole-image read and we delay until first pixel
* access.
* Delay the load until the first pixel is requested by doing the work
* in the start function of the copy.
*/
if( class->load &&
((load->flags & VIPS_FOREIGN_PARTIAL) ||
((load->flags & VIPS_FOREIGN_SEQUENTIAL) &&
load->sequential)) ) {
if( class->load ) {
#ifdef DEBUG
printf( "vips_foreign_load_build: partial read\n" );
#endif /*DEBUG*/
/* Read the image to @real.
*/
load->real = vips_image_new();
if( class->load( load ) ||
vips_image_pio_input( load->real ) )
return( -1 );
/* Must match ->header().
*/
if( !vips_foreign_load_iscompat( load->real, load->out ) )
return( -1 );
/* ->header() should set the dhint. It'll default to the safe
* SMALLTILE if ->header() did not set it.
*/
vips_demand_hint( load->out, load->out->dhint,
load->real, NULL );
if( vips_image_generate( load->out,
vips_start_one,
vips_foreign_load_generate,
vips_stop_one,
load->real, load ) )
return( -1 );
}
else if( class->load ) {
#ifdef DEBUG
printf( "vips_foreign_load_build: whole-image read\n" );
printf( "vips_foreign_load_build: delaying read ...\n" );
#endif /*DEBUG*/
/* ->header() should set the dhint. It'll default to the safe

View File

@ -112,7 +112,6 @@ typedef struct {
png_structp pPng;
png_infop pInfo;
png_bytep *row_pointer;
int interlace_type;
} Read;
static void
@ -138,7 +137,6 @@ read_new( const char *name, VipsImage *out )
read->pPng = NULL;
read->pInfo = NULL;
read->row_pointer = NULL;
read->interlace_type = PNG_INTERLACE_NONE;
g_signal_connect( out, "close",
G_CALLBACK( read_destroy ), read );
@ -169,6 +167,7 @@ png2vips_header( Read *read, VipsImage *out )
{
png_uint_32 width, height;
int bit_depth, color_type;
int interlace_type;
png_uint_32 res_x, res_y;
int unit_type;
@ -184,7 +183,7 @@ png2vips_header( Read *read, VipsImage *out )
png_read_info( read->pPng, read->pInfo );
png_get_IHDR( read->pPng, read->pInfo,
&width, &height, &bit_depth, &color_type,
&read->interlace_type, NULL, NULL );
&interlace_type, NULL, NULL );
/* png_get_channels() gives us 1 band for palette images ... so look
* at colour_type for output bands.
@ -341,6 +340,13 @@ png2vips_generate( VipsRegion *or,
r->top, r->height );
#endif /*DEBUG*/
/* We're inside a tilecache where tiles are the full image width, so
* this should always be true.
*/
g_assert( r->left == 0 );
g_assert( r->width == or->im->Xsize );
g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize );
if( setjmp( png_jmpbuf( read->pPng ) ) )
return( -1 );
@ -364,12 +370,11 @@ vips__png_isinterlaced( const char *filename )
int interlace_type;
image = vips_image_new();
if( !(read = read_new( filename, image )) ||
png2vips_header( read, image ) ) {
if( !(read = read_new( filename, image )) ) {
g_object_unref( image );
return( -1 );
}
interlace_type = read->interlace_type;
interlace_type = png_get_interlace_type( read->pPng, read->pInfo );
g_object_unref( image );
return( interlace_type != PNG_INTERLACE_NONE );
@ -387,21 +392,24 @@ vips__png_read( const char *name, VipsImage *out )
printf( "png2vips: reading \"%s\"\n", name );
#endif /*DEBUG*/
t[0] = vips_image_new_buffer();
if( !(read = read_new( name, out )) ||
png2vips_header( read, t[0] ) )
if( !(read = read_new( name, out )) )
return( -1 );
if( read->interlace_type != PNG_INTERLACE_NONE ) {
/* Arg we have to read to a huge mem buffer, then copy to out.
if( png_get_interlace_type( read->pPng, read->pInfo ) !=
PNG_INTERLACE_NONE ) {
/* Arg awful interlaced image. We have to load to a huge mem
* buffer, then copy to out.
*/
t[0] = vips_image_new_buffer();
if( png2vips_interlace( read, t[0] ) ||
if( png2vips_header( read, t[0] ) ||
png2vips_interlace( read, t[0] ) ||
vips_image_write( t[0], out ) )
return( -1 );
}
else {
if( vips_image_generate( t[0],
t[0] = vips_image_new();
if( png2vips_header( read, t[0] ) ||
vips_image_generate( t[0],
NULL, png2vips_generate, NULL,
read, NULL ) ||
vips_sequential( t[0], &t[1], NULL ) ||
@ -414,6 +422,10 @@ vips__png_read( const char *name, VipsImage *out )
return( -1 );
}
#ifdef DEBUG
printf( "png2vips: done\n" );
#endif /*DEBUG*/
return( 0 );
}

View File

@ -31,8 +31,8 @@
*/
/*
#define VIPS_DEBUG
*/
#define VIPS_DEBUG
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -103,18 +103,6 @@ sink_memory_work( VipsThreadState *state, void *a )
&state->pos, state->pos.left, state->pos.top ) )
return( -1 );
#ifdef VIPS_DEBUG
{
VipsPel *p = VIPS_REGION_ADDR( state->reg,
state->pos.left, state->pos.top );
int i;
VIPS_DEBUG_MSG( "sink_memory_work: %p\n", memory );
for( i = 0; i < VIPS_IMAGE_SIZEOF_PEL( state->reg->im ); i++ )
printf( "\t%d) %02x\n", i, p[i] );
}
#endif /*VIPS_DEBUG*/
return( 0 );
}