faster tiled tiff read, faster im_tile_cache()
This commit is contained in:
parent
7966a36446
commit
f70ae48de3
@ -113,6 +113,8 @@
|
|||||||
* subsampling schemes (esp. subsampled YCbCr), and it's a bit quicker
|
* subsampling schemes (esp. subsampled YCbCr), and it's a bit quicker
|
||||||
* 4/2/10
|
* 4/2/10
|
||||||
* - gtkdoc
|
* - gtkdoc
|
||||||
|
* 12/12/10
|
||||||
|
* - oops, we can just memcpy() now heh
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -167,7 +169,6 @@ im_tiff2vips( const char *tiffile, IMAGE *im )
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/internal.h>
|
#include <vips/internal.h>
|
||||||
@ -181,7 +182,7 @@ im_tiff2vips( const char *tiffile, IMAGE *im )
|
|||||||
|
|
||||||
/* Scanline-type process function.
|
/* Scanline-type process function.
|
||||||
*/
|
*/
|
||||||
typedef void (*scanline_process_fn)( PEL *q, PEL *p, int n, void *user );
|
typedef void (*scanline_process_fn)( PEL *q, PEL *p, int n, void *client );
|
||||||
|
|
||||||
/* Stuff we track during a read.
|
/* Stuff we track during a read.
|
||||||
*/
|
*/
|
||||||
@ -204,6 +205,10 @@ typedef struct {
|
|||||||
scanline_process_fn sfn;
|
scanline_process_fn sfn;
|
||||||
void *client;
|
void *client;
|
||||||
|
|
||||||
|
/* Set this is the processfn is just doing a memcpy.
|
||||||
|
*/
|
||||||
|
gboolean memcpy;
|
||||||
|
|
||||||
/* Geometry.
|
/* Geometry.
|
||||||
*/
|
*/
|
||||||
int twidth, theight; /* Tile size */
|
int twidth, theight; /* Tile size */
|
||||||
@ -356,7 +361,6 @@ parse_labpack( ReadTiff *rtiff, IMAGE *out )
|
|||||||
out->Type = IM_TYPE_LAB;
|
out->Type = IM_TYPE_LAB;
|
||||||
|
|
||||||
rtiff->sfn = labpack_line;
|
rtiff->sfn = labpack_line;
|
||||||
rtiff->client = NULL;
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -395,7 +399,6 @@ parse_labs( ReadTiff *rtiff, IMAGE *out )
|
|||||||
out->Type = IM_TYPE_LABS;
|
out->Type = IM_TYPE_LABS;
|
||||||
|
|
||||||
rtiff->sfn = labs_line;
|
rtiff->sfn = labs_line;
|
||||||
rtiff->client = NULL;
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -554,17 +557,14 @@ parse_greyscale16( ReadTiff *rtiff, int pm, IMAGE *out )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-scanline process function for 32-bit floating point greyscale images.
|
/* Per-scanline process function when we just need to copy.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
greyscale32f_line( PEL *q, PEL *p, int n )
|
memcpy_line( PEL *q, PEL *p, int n, void *client )
|
||||||
{
|
{
|
||||||
float *p1 = (float *) p;
|
IMAGE *im = (IMAGE *) client;
|
||||||
float *q1 = (float *) q;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for( x = 0; x < n; x++ )
|
memcpy( q, p, n * IM_IMAGE_SIZEOF_PEL( im ) );
|
||||||
q1[x] = p1[x];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a 32-bit floating point greyscale TIFF image. What do we do about
|
/* Read a 32-bit floating point greyscale TIFF image. What do we do about
|
||||||
@ -582,8 +582,9 @@ parse_greyscale32f( ReadTiff *rtiff, int pm, IMAGE *out )
|
|||||||
out->Coding = IM_CODING_NONE;
|
out->Coding = IM_CODING_NONE;
|
||||||
out->Type = IM_TYPE_B_W;
|
out->Type = IM_TYPE_B_W;
|
||||||
|
|
||||||
rtiff->sfn = (scanline_process_fn) greyscale32f_line;
|
rtiff->sfn = memcpy_line;
|
||||||
rtiff->client = NULL;
|
rtiff->client = out;
|
||||||
|
rtiff->memcpy = TRUE;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -662,22 +663,6 @@ parse_palette( ReadTiff *rtiff, IMAGE *out )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-scanline process function for 8-bit RGB/RGBA/CMYK/CMYKA/etc.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
rgbcmyk8_line( PEL *q, PEL *p, int n, IMAGE *im )
|
|
||||||
{
|
|
||||||
int x, b;
|
|
||||||
|
|
||||||
for( x = 0; x < n; x++ ) {
|
|
||||||
for( b = 0; b < im->Bands; b++ )
|
|
||||||
q[b] = p[b];
|
|
||||||
|
|
||||||
q += im->Bands;
|
|
||||||
p += im->Bands;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read an 8-bit RGB/RGBA image.
|
/* Read an 8-bit RGB/RGBA image.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -702,30 +687,13 @@ parse_rgb8( ReadTiff *rtiff, IMAGE *out )
|
|||||||
out->Coding = IM_CODING_NONE;
|
out->Coding = IM_CODING_NONE;
|
||||||
out->Type = IM_TYPE_sRGB;
|
out->Type = IM_TYPE_sRGB;
|
||||||
|
|
||||||
rtiff->sfn = (scanline_process_fn) rgbcmyk8_line;
|
rtiff->sfn = memcpy_line;
|
||||||
rtiff->client = out;
|
rtiff->client = out;
|
||||||
|
rtiff->memcpy = TRUE;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-scanline process function for RGB/RGBA 16.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
rgb16_line( PEL *q, PEL *p, int n, IMAGE *im )
|
|
||||||
{
|
|
||||||
int x, b;
|
|
||||||
unsigned short *p1 = (unsigned short *) p;
|
|
||||||
unsigned short *q1 = (unsigned short *) q;
|
|
||||||
|
|
||||||
for( x = 0; x < n; x++ ) {
|
|
||||||
for( b = 0; b < im->Bands; b++ )
|
|
||||||
q1[b] = p1[b];
|
|
||||||
|
|
||||||
q1 += im->Bands;
|
|
||||||
p1 += im->Bands;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a 16-bit RGB/RGBA image.
|
/* Read a 16-bit RGB/RGBA image.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -750,31 +718,13 @@ parse_rgb16( ReadTiff *rtiff, IMAGE *out )
|
|||||||
out->Coding = IM_CODING_NONE;
|
out->Coding = IM_CODING_NONE;
|
||||||
out->Type = IM_TYPE_RGB16;
|
out->Type = IM_TYPE_RGB16;
|
||||||
|
|
||||||
rtiff->sfn = (scanline_process_fn) rgb16_line;
|
rtiff->sfn = memcpy_line;
|
||||||
rtiff->client = out;
|
rtiff->client = out;
|
||||||
|
rtiff->memcpy = TRUE;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-scanline process function for 32f.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
r32f_line( PEL *q, PEL *p, int n, void *dummy )
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
float *p1 = (float *) p;
|
|
||||||
float *q1 = (float *) q;
|
|
||||||
|
|
||||||
for( x = 0; x < n; x++ ) {
|
|
||||||
q1[0] = p1[0];
|
|
||||||
q1[1] = p1[1];
|
|
||||||
q1[2] = p1[2];
|
|
||||||
|
|
||||||
q1 += 3;
|
|
||||||
p1 += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a 32-bit float image. RGB or LAB, with or without alpha.
|
/* Read a 32-bit float image. RGB or LAB, with or without alpha.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -788,7 +738,7 @@ parse_32f( ReadTiff *rtiff, int pm, IMAGE *out )
|
|||||||
|
|
||||||
/* Can be 4 for images with an alpha channel.
|
/* Can be 4 for images with an alpha channel.
|
||||||
*/
|
*/
|
||||||
assert( bands == 3 || bands == 4 );
|
g_assert( bands == 3 || bands == 4 );
|
||||||
|
|
||||||
out->Bands = bands;
|
out->Bands = bands;
|
||||||
out->BandFmt = IM_BANDFMT_FLOAT;
|
out->BandFmt = IM_BANDFMT_FLOAT;
|
||||||
@ -804,11 +754,12 @@ parse_32f( ReadTiff *rtiff, int pm, IMAGE *out )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( 0 );
|
g_assert( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
rtiff->sfn = r32f_line;
|
rtiff->sfn = memcpy_line;
|
||||||
rtiff->client = NULL;
|
rtiff->client = out;
|
||||||
|
rtiff->memcpy = TRUE;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -838,8 +789,9 @@ parse_cmyk( ReadTiff *rtiff, IMAGE *out )
|
|||||||
out->Coding = IM_CODING_NONE;
|
out->Coding = IM_CODING_NONE;
|
||||||
out->Type = IM_TYPE_CMYK;
|
out->Type = IM_TYPE_CMYK;
|
||||||
|
|
||||||
rtiff->sfn = (scanline_process_fn) rgbcmyk8_line;
|
rtiff->sfn = memcpy_line;
|
||||||
rtiff->client = out;
|
rtiff->client = out;
|
||||||
|
rtiff->memcpy = TRUE;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -1108,7 +1060,7 @@ parse_header( ReadTiff *rtiff, IMAGE *out )
|
|||||||
* to vips in parallel.
|
* to vips in parallel.
|
||||||
*/
|
*/
|
||||||
static void *
|
static void *
|
||||||
seq_start( IMAGE *out, void *a, void *b )
|
tiff_seq_start( IMAGE *out, void *a, void *b )
|
||||||
{
|
{
|
||||||
ReadTiff *rtiff = (ReadTiff *) a;
|
ReadTiff *rtiff = (ReadTiff *) a;
|
||||||
tdata_t *buf;
|
tdata_t *buf;
|
||||||
@ -1119,10 +1071,41 @@ seq_start( IMAGE *out, void *a, void *b )
|
|||||||
return( (void *) buf );
|
return( (void *) buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Paint a tile from the file. This is a
|
||||||
|
* special-case for a region is exactly a tiff tile, and pixels need no
|
||||||
|
* conversion. In this case, libtiff can read tiles directly to our output
|
||||||
|
* region.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tiff_fill_region_aligned( REGION *out, void *seq, void *a, void *b )
|
||||||
|
{
|
||||||
|
ReadTiff *rtiff = (ReadTiff *) a;
|
||||||
|
Rect *r = &out->valid;
|
||||||
|
|
||||||
|
g_assert( (r->left % rtiff->twidth) == 0 );
|
||||||
|
g_assert( (r->top % rtiff->theight) == 0 );
|
||||||
|
g_assert( r->width == rtiff->twidth );
|
||||||
|
g_assert( r->height == rtiff->theight );
|
||||||
|
g_assert( IM_REGION_LSKIP( out ) == IM_REGION_SIZEOF_LINE( out ) );
|
||||||
|
|
||||||
|
/* Read that tile directly into the vips tile.
|
||||||
|
*/
|
||||||
|
g_mutex_lock( rtiff->tlock );
|
||||||
|
if( TIFFReadTile( rtiff->tiff,
|
||||||
|
IM_REGION_ADDR( out, r->left, r->top ),
|
||||||
|
r->left, r->top, 0, 0 ) < 0 ) {
|
||||||
|
g_mutex_unlock( rtiff->tlock );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
g_mutex_unlock( rtiff->tlock );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* Loop over the output region, painting in tiles from the file.
|
/* Loop over the output region, painting in tiles from the file.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
fill_region( REGION *out, void *seq, void *a, void *b )
|
tiff_fill_region( REGION *out, void *seq, void *a, void *b )
|
||||||
{
|
{
|
||||||
tdata_t *buf = (tdata_t *) seq;
|
tdata_t *buf = (tdata_t *) seq;
|
||||||
ReadTiff *rtiff = (ReadTiff *) a;
|
ReadTiff *rtiff = (ReadTiff *) a;
|
||||||
@ -1147,6 +1130,17 @@ fill_region( REGION *out, void *seq, void *a, void *b )
|
|||||||
|
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
|
|
||||||
|
/* Special case: we are filling a single tile exactly sizeed to match
|
||||||
|
* the tiff tile, and we have no repacking to do for this format.
|
||||||
|
*/
|
||||||
|
if( rtiff->memcpy &&
|
||||||
|
r->left % rtiff->twidth == 0 &&
|
||||||
|
r->top % rtiff->theight == 0 &&
|
||||||
|
r->width == rtiff->twidth &&
|
||||||
|
r->height == rtiff->theight &&
|
||||||
|
IM_REGION_LSKIP( out ) == IM_REGION_SIZEOF_LINE( out ) )
|
||||||
|
return( tiff_fill_region_aligned( out, seq, a, b ) );
|
||||||
|
|
||||||
for( y = ys; y < IM_RECT_BOTTOM( r ); y += rtiff->theight )
|
for( y = ys; y < IM_RECT_BOTTOM( r ); y += rtiff->theight )
|
||||||
for( x = xs; x < IM_RECT_RIGHT( r ); x += rtiff->twidth ) {
|
for( x = xs; x < IM_RECT_RIGHT( r ); x += rtiff->twidth ) {
|
||||||
Rect tile;
|
Rect tile;
|
||||||
@ -1191,7 +1185,7 @@ fill_region( REGION *out, void *seq, void *a, void *b )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
seq_stop( void *seq, void *a, void *b )
|
tiff_seq_stop( void *seq, void *a, void *b )
|
||||||
{
|
{
|
||||||
im_free( seq );
|
im_free( seq );
|
||||||
|
|
||||||
@ -1233,7 +1227,8 @@ read_tilewise( ReadTiff *rtiff, IMAGE *out )
|
|||||||
*/
|
*/
|
||||||
if( im_demand_hint( raw, IM_SMALLTILE, NULL ) ||
|
if( im_demand_hint( raw, IM_SMALLTILE, NULL ) ||
|
||||||
im_generate( raw,
|
im_generate( raw,
|
||||||
seq_start, fill_region, seq_stop, rtiff, NULL ) )
|
tiff_seq_start, tiff_fill_region, tiff_seq_stop,
|
||||||
|
rtiff, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Copy to out, adding a cache. Enough tiles for two complete rows.
|
/* Copy to out, adding a cache. Enough tiles for two complete rows.
|
||||||
@ -1348,6 +1343,7 @@ readtiff_new( const char *filename, IMAGE *out )
|
|||||||
rtiff->tiff = NULL;
|
rtiff->tiff = NULL;
|
||||||
rtiff->sfn = NULL;
|
rtiff->sfn = NULL;
|
||||||
rtiff->client = NULL;
|
rtiff->client = NULL;
|
||||||
|
rtiff->memcpy = FALSE;
|
||||||
rtiff->twidth = 0;
|
rtiff->twidth = 0;
|
||||||
rtiff->theight = 0;
|
rtiff->theight = 0;
|
||||||
rtiff->tlock = g_mutex_new();
|
rtiff->tlock = g_mutex_new();
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
* threads
|
* threads
|
||||||
* 4/2/10
|
* 4/2/10
|
||||||
* - gtkdoc
|
* - gtkdoc
|
||||||
|
* 12/12/10
|
||||||
|
* - use im_prepare_to() and avoid making a sequence for every cache tile
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -51,7 +53,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/thread.h>
|
#include <vips/thread.h>
|
||||||
@ -103,7 +104,7 @@ tile_destroy( Tile *tile )
|
|||||||
|
|
||||||
read->cache = g_slist_remove( read->cache, tile );
|
read->cache = g_slist_remove( read->cache, tile );
|
||||||
read->ntiles -= 1;
|
read->ntiles -= 1;
|
||||||
assert( read->ntiles >= 0 );
|
g_assert( read->ntiles >= 0 );
|
||||||
tile->read = NULL;
|
tile->read = NULL;
|
||||||
|
|
||||||
IM_FREEF( im_region_free, tile->region );
|
IM_FREEF( im_region_free, tile->region );
|
||||||
@ -166,17 +167,37 @@ tile_new( Read *read )
|
|||||||
tile->x = -1;
|
tile->x = -1;
|
||||||
tile->y = -1;
|
tile->y = -1;
|
||||||
read->cache = g_slist_prepend( read->cache, tile );
|
read->cache = g_slist_prepend( read->cache, tile );
|
||||||
assert( read->ntiles >= 0 );
|
g_assert( read->ntiles >= 0 );
|
||||||
read->ntiles += 1;
|
read->ntiles += 1;
|
||||||
|
|
||||||
if( !(tile->region = im_region_create( read->in )) ) {
|
if( !(tile->region = im_region_create( read->in )) ) {
|
||||||
tile_destroy( tile );
|
tile_destroy( tile );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
im__region_no_ownership( tile->region );
|
||||||
|
|
||||||
return( tile );
|
return( tile );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tile_move( Tile *tile, int x, int y )
|
||||||
|
{
|
||||||
|
Rect area;
|
||||||
|
|
||||||
|
tile->x = x;
|
||||||
|
tile->y = y;
|
||||||
|
|
||||||
|
area.left = x;
|
||||||
|
area.top = y;
|
||||||
|
area.width = tile->read->tile_width;
|
||||||
|
area.height = tile->read->tile_height;
|
||||||
|
|
||||||
|
if( im_region_buffer( tile->region, &area ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* Do we have a tile in the cache?
|
/* Do we have a tile in the cache?
|
||||||
*/
|
*/
|
||||||
static Tile *
|
static Tile *
|
||||||
@ -197,7 +218,7 @@ tile_search( Read *read, int x, int y )
|
|||||||
static void
|
static void
|
||||||
tile_touch( Tile *tile )
|
tile_touch( Tile *tile )
|
||||||
{
|
{
|
||||||
assert( tile->read->ntiles >= 0 );
|
g_assert( tile->read->ntiles >= 0 );
|
||||||
|
|
||||||
tile->time = tile->read->time++;
|
tile->time = tile->read->time++;
|
||||||
}
|
}
|
||||||
@ -205,28 +226,21 @@ tile_touch( Tile *tile )
|
|||||||
/* Fill a tile with pixels.
|
/* Fill a tile with pixels.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
tile_fill( Tile *tile, int x, int y )
|
tile_fill( Tile *tile, REGION *in )
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
tile->x = x;
|
|
||||||
tile->y = y;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "im_tile_cache: 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*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
area.left = x;
|
area.left = tile->x;
|
||||||
area.top = y;
|
area.top = tile->y;
|
||||||
area.width = tile->read->tile_width;
|
area.width = tile->read->tile_width;
|
||||||
area.height = tile->read->tile_height;
|
area.height = tile->read->tile_height;
|
||||||
if( im_prepare( tile->region, &area ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
/* Make sure these pixels aren't part of this thread's buffer cache
|
if( im_prepare_to( in, tile->region, &area, area.left, area.top ) )
|
||||||
* ... they may be read out by another thread.
|
return( -1 );
|
||||||
*/
|
|
||||||
im__region_no_ownership( tile->region );
|
|
||||||
|
|
||||||
tile_touch( tile );
|
tile_touch( tile );
|
||||||
|
|
||||||
@ -237,7 +251,7 @@ tile_fill( Tile *tile, int x, int y )
|
|||||||
* reuse LRU.
|
* reuse LRU.
|
||||||
*/
|
*/
|
||||||
static Tile *
|
static Tile *
|
||||||
tile_find( Read *read, int x, int y )
|
tile_find( Read *read, REGION *in, int x, int y )
|
||||||
{
|
{
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
int oldest;
|
int oldest;
|
||||||
@ -256,7 +270,8 @@ tile_find( Read *read, int x, int y )
|
|||||||
if( read->max_tiles == -1 ||
|
if( read->max_tiles == -1 ||
|
||||||
read->ntiles < read->max_tiles ) {
|
read->ntiles < read->max_tiles ) {
|
||||||
if( !(tile = tile_new( read )) ||
|
if( !(tile = tile_new( read )) ||
|
||||||
tile_fill( tile, x, y ) )
|
tile_move( tile, x, y ) ||
|
||||||
|
tile_fill( tile, in ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
return( tile );
|
return( tile );
|
||||||
@ -275,20 +290,14 @@ tile_find( Read *read, int x, int y )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( tile );
|
g_assert( tile );
|
||||||
|
|
||||||
/* The tile may have been created by another thread if we are sharing
|
|
||||||
* the tile cache between several readers. Take ownership of the tile
|
|
||||||
* to stop assert() failures in im_prepare(). This is safe, since we
|
|
||||||
* are in a mutex.
|
|
||||||
*/
|
|
||||||
im__region_take_ownership( tile->region );
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "im_tile_cache: 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*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( tile_fill( tile, x, y ) )
|
if( tile_move( tile, x, y ) ||
|
||||||
|
tile_fill( tile, in ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
return( tile );
|
return( tile );
|
||||||
@ -303,8 +312,8 @@ copy_region( REGION *from, REGION *to, Rect *area )
|
|||||||
|
|
||||||
/* Area should be inside both from and to.
|
/* Area should be inside both from and to.
|
||||||
*/
|
*/
|
||||||
assert( im_rect_includesrect( &from->valid, area ) );
|
g_assert( im_rect_includesrect( &from->valid, area ) );
|
||||||
assert( im_rect_includesrect( &to->valid, area ) );
|
g_assert( im_rect_includesrect( &to->valid, area ) );
|
||||||
|
|
||||||
/* Loop down common area, copying.
|
/* Loop down common area, copying.
|
||||||
*/
|
*/
|
||||||
@ -319,9 +328,10 @@ copy_region( REGION *from, REGION *to, Rect *area )
|
|||||||
/* Loop over the output region, filling with data from cache.
|
/* Loop over the output region, filling with data from cache.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
fill_region( REGION *out, void *seq, void *a, void *b )
|
tile_cache_fill( REGION *out, void *seq, void *a, void *b )
|
||||||
{
|
{
|
||||||
Read *read = (Read *) a;
|
REGION *in = (REGION *) seq;
|
||||||
|
Read *read = (Read *) b;
|
||||||
const int tw = read->tile_width;
|
const int tw = read->tile_width;
|
||||||
const int th = read->tile_height;
|
const int th = read->tile_height;
|
||||||
Rect *r = &out->valid;
|
Rect *r = &out->valid;
|
||||||
@ -341,7 +351,7 @@ fill_region( REGION *out, void *seq, void *a, void *b )
|
|||||||
Rect tarea;
|
Rect tarea;
|
||||||
Rect hit;
|
Rect hit;
|
||||||
|
|
||||||
if( !(tile = tile_find( read, x, y )) ) {
|
if( !(tile = tile_find( read, in, x, y )) ) {
|
||||||
g_mutex_unlock( read->lock );
|
g_mutex_unlock( read->lock );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -405,7 +415,7 @@ im_tile_cache( IMAGE *in, IMAGE *out,
|
|||||||
!(read = read_new( in, out,
|
!(read = read_new( in, out,
|
||||||
tile_width, tile_height, max_tiles )) ||
|
tile_width, tile_height, max_tiles )) ||
|
||||||
im_generate( out,
|
im_generate( out,
|
||||||
NULL, fill_region, NULL, read, NULL ) )
|
im_start_one, tile_cache_fill, im_stop_one, in, read ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -1066,7 +1066,8 @@ mask_fill( REGION *out, void *seq, void *a, void *b )
|
|||||||
* im_prepare() on @out will always block until the pixels have been
|
* im_prepare() on @out will always block until the pixels have been
|
||||||
* calculated.
|
* calculated.
|
||||||
*
|
*
|
||||||
* See also: im_cache(), im_prepare(), vips_sink_disc(), vips_sink().
|
* See also: im_cache(), im_tile_cache(), im_prepare(), vips_sink_disc(),
|
||||||
|
* vips_sink().
|
||||||
*
|
*
|
||||||
* Returns: 0 on sucess, -1 on error.
|
* Returns: 0 on sucess, -1 on error.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user