region done

VipsRegion now exists, up to semaphore.c
This commit is contained in:
John Cupitt 2011-03-03 14:49:12 +00:00
parent 3d55a7876c
commit 6fa48b0e7d
18 changed files with 657 additions and 696 deletions

6
TODO
View File

@ -5,8 +5,10 @@
- im_sanity() should become a method on VipsObject, see debug.c
- REGION needs moving at the same time, since regions have to ref their image,
argh
- rename Rect to VipsRect
- remove im__handle_eval etc. from headers
- pre/post/close should be on VipsObject, not VipsImage

View File

@ -36,11 +36,6 @@
extern "C" {
#endif /*__cplusplus*/
/* IMAGE functions which use regions.
*/
int im_prepare( VipsRegion *reg, Rect *r );
int im_prepare_to( VipsRegion *reg, VipsRegion *dest, Rect *r, int x, int y );
typedef void *(*im_start_fn)( IMAGE *out, void *a, void *b );
typedef int (*im_generate_fn)( VipsRegion *out, void *seq, void *a, void *b );
typedef int (*im_stop_fn)( void *seq, void *a, void *b );
@ -90,10 +85,7 @@ int im_render_priority( IMAGE *in, IMAGE *out, IMAGE *mask,
void (*notify)( IMAGE *, Rect *, void * ), void *client );
int im_cache( IMAGE *in, IMAGE *out, int width, int height, int max );
/* WIO.
*/
int im_setupout( IMAGE *im );
int im_writeline( int ypos, IMAGE *im, PEL *linebuffer );
#ifdef __cplusplus
}

View File

@ -296,6 +296,8 @@ typedef struct _VipsImageClass {
} VipsImageClass;
GType vips_image_get_type( void );
extern const size_t vips__sizeof_bandfmt[];
/* Pixel address calculation macros.

View File

@ -79,7 +79,7 @@ typedef enum {
/* Useful flag combinations. User-visible ones are:
VIPS_ARGUMENT_REQURED_INPUT Eg. the "left" argument for an add operation
VIPS_ARGUMENT_REQUIRED_INPUT Eg. the "left" argument for an add operation
VIPS_ARGUMENT_OPTIONAL_INPUT Eg. the "caption" for an object

View File

@ -146,19 +146,19 @@ typedef enum region_type {
/* Functions on regions.
*/
struct _VipsRegion;
void im__region_take_ownership( struct _VipsRegion *reg );
void im__region_check_ownership( struct _VipsRegion *reg );
void im__region_no_ownership( struct _VipsRegion *reg );
void vips__region_take_ownership( struct _VipsRegion *reg );
void vips__region_check_ownership( struct _VipsRegion *reg );
void vips__region_no_ownership( struct _VipsRegion *reg );
void im__copy_region( struct _VipsRegion *reg, struct _VipsRegion *dest, Rect *r, int x, int y );
void im__find_demand_size( struct _VipsImage *im, int *pw, int *ph );
int im__call_start( struct _VipsRegion *reg );
void im__call_stop( struct _VipsRegion *reg );
int vips__region_start( struct _VipsRegion *reg );
void vips__region_stop( struct _VipsRegion *reg );
typedef int (*im_region_fill_fn)( struct _VipsRegion *, void * );
int im_region_fill( struct _VipsRegion *reg, Rect *r, im_region_fill_fn fn, void *a );
void im_region_print( struct _VipsRegion *region );
typedef int (*VipsRegionFillFn)( struct _VipsRegion *, void * );
int vips_region_fill( struct _VipsRegion *reg,
Rect *r, VipsRegionFillFn fn, void *a );
int im_prepare_many( struct _VipsRegion **reg, Rect *r );

View File

@ -97,6 +97,8 @@ typedef struct _VipsRegionClass {
} VipsRegionClass;
GType vips_region_get_type( void );
VipsRegion *vips_region_new( VipsImage *im );
int vips_region_buffer( VipsRegion *reg, Rect *r );
@ -111,6 +113,11 @@ void vips_region_black( VipsRegion *reg );
void vips_region_copy( VipsRegion *reg, VipsRegion *dest,
Rect *r, int x, int y );
int vips_region_prepare( VipsRegion *reg, Rect *r );
int vips_region_prepare_to( VipsRegion *reg,
VipsRegion *dest, Rect *r, int x, int y );
int vips_region_prepare_many( VipsRegion **reg, Rect *r );
/* Macros on REGIONs.
* VIPS_REGION_LSKIP() add to move down line
* VIPS_REGION_N_ELEMENTS() number of elements across region

View File

@ -15,7 +15,6 @@ libiofuncs_la_SOURCES = \
im_generate.c \
im_histlin.c \
im_mapfile.c \
im_prepare.c \
im_setupout.c \
im_guess_prefix.c \
sinkmemory.c \

View File

@ -131,7 +131,7 @@ im_start_one( IMAGE *out, void *a, void *b )
{
IMAGE *in = (IMAGE *) a;
return( im_region_create( in ) );
return( vips_region_new( in ) );
}
/**
@ -147,9 +147,9 @@ im_start_one( IMAGE *out, void *a, void *b )
int
im_stop_one( void *seq, void *a, void *b )
{
REGION *reg = (REGION *) seq;
VipsRegion *reg = (VipsRegion *) seq;
im_region_free( reg );
g_object_unref( reg );
return( 0 );
}
@ -168,13 +168,13 @@ im_stop_one( void *seq, void *a, void *b )
int
im_stop_many( void *seq, void *a, void *b )
{
REGION **ar = (REGION **) seq;
VipsRegion **ar = (VipsRegion **) seq;
if( ar ) {
int i;
for( i = 0; ar[i]; i++ )
im_region_free( ar[i] );
g_object_unref( ar[i] );
im_free( (char *) ar );
}
@ -198,7 +198,7 @@ im_start_many( IMAGE *out, void *a, void *b )
IMAGE **in = (IMAGE **) a;
int i, n;
REGION **ar;
VipsRegion **ar;
/* How many images?
*/
@ -207,13 +207,13 @@ im_start_many( IMAGE *out, void *a, void *b )
/* Alocate space for region array.
*/
if( !(ar = VIPS_ARRAY( NULL, n + 1, REGION * )) )
if( !(ar = VIPS_ARRAY( NULL, n + 1, VipsRegion * )) )
return( NULL );
/* Create a set of regions.
*/
for( i = 0; i < n; i++ )
if( !(ar[i] = im_region_create( in[i] )) ) {
if( !(ar[i] = vips_region_new( in[i] )) ) {
im_stop_many( ar, NULL, NULL );
return( NULL );
}
@ -281,7 +281,7 @@ im_allocate_input_array( IMAGE *out, ... )
/**
* im_generate_fn:
* @out: #REGION to fill
* @out: #VipsRegion to fill
* @seq: sequence value
* @a: user data
* @b: user data
@ -311,13 +311,13 @@ im_allocate_input_array( IMAGE *out, ... )
/* A write function for VIPS images. Just write() the pixel data.
*/
static int
write_vips( REGION *region, Rect *area, void *a, void *b )
write_vips( VipsRegion *region, Rect *area, void *a, void *b )
{
size_t nwritten, count;
void *buf;
count = region->bpl * area->height;
buf = IM_REGION_ADDR( region, 0, area->top );
buf = VIPS_REGION_ADDR( region, 0, area->top );
do {
nwritten = write( region->im->fd, buf, count );
if( nwritten == (size_t) -1 )

View File

@ -1,378 +0,0 @@
/* Request an area of an image for input.
*
* J.Cupitt, 17/4/93.
*
* Modified:
* 22/11/94 JC
* - check for start and stop functions removed, as can now be NULL
* 22/2/95 JC
* - im_fill_copy() added
* 18/4/95 JC
* - kill flag added for compute cases
* 27/10/95 JC
* - im_fill_copy() now only uses im_generate() mechanism if it has to
* - im_fill_copy() renamed as im_prepare_inplace()
* 18/8/99 JC
* - oops ... cache stuff removed, interacted badly with inplace ops
* 26/3/02 JC
* - better error message for im_prepare()
* 9/8/02 JC
* - im_prepare_inplace() broke with mmap() windows ... im_prepare_to()
* replaces it and is nicer
* 30/9/05
* - hmm, did not stop if a start function failed
* 7/10/09
* - gtkdoc comments
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/thread.h>
#include <vips/debug.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Generate into a region.
*/
static int
fill_region( REGION *reg )
{
IMAGE *im = reg->im;
/* Start new sequence, if necessary.
*/
if( im__call_start( reg ) )
return( -1 );
/* Ask for evaluation.
*/
if( im->generate( reg, reg->seq, im->client1, im->client2 ) )
return( -1 );
return( 0 );
}
/**
* im_prepare:
* @reg: region to prepare
* @r: #Rect of pixels you need to be able to address
*
* im_prepare() fills @reg with pixels. After calling, you can address at
* least the area @r with IM_REGION_ADDR() and get valid pixels.
*
* im_prepare() runs in-line, that is, computation is done by the calling
* thread, no new threads are involved, and computation blocks until the
* pixels are ready.
*
* Use im_prepare_thread() to calculate an area of pixels with many
* threads. Use im_render_priority() to calculate an area of pixels in the
* background.
*
* See also: im_prepare_thread(), im_render_priority(), im_prepare_to().
*
* Returns: 0 on success, or -1 on error.
*/
int
im_prepare( REGION *reg, Rect *r )
{
IMAGE *im = reg->im;
Rect save = *r;
im__region_check_ownership( reg );
if( im__test_kill( im ) )
return( -1 );
/* We use save for sanity checking valid: we test at the end that the
* pixels we have generated are indeed all the ones that were asked
* for.
*
* However, r may be clipped by the image size, so we need to clip
* save as well to make sure we don't fail the assert due to that.
*/
{
Rect image;
image.left = 0;
image.top = 0;
image.width = reg->im->Xsize;
image.height = reg->im->Ysize;
im_rect_intersectrect( &save, &image, &save );
}
#ifdef DEBUG
printf( "im_prepare: left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height );
#endif /*DEBUG*/
switch( im->dtype ) {
case VIPS_IMAGE_PARTIAL:
if( im_region_fill( reg, r,
(im_region_fill_fn) fill_region, NULL ) )
return( -1 );
break;
case VIPS_IMAGE_SETBUF:
case VIPS_IMAGE_SETBUF_FOREIGN:
case VIPS_IMAGE_MMAPIN:
case VIPS_IMAGE_MMAPINRW:
case VIPS_IMAGE_OPENIN:
/* Attach to existing buffer.
*/
if( im_region_image( reg, r ) )
return( -1 );
break;
default:
vips_error( "im_prepare", _( "unable to input from a %s image" ),
im_dtype2char( im->dtype ) );
return( -1 );
}
/* valid should now include all the pixels that were asked for.
*/
g_assert( im_rect_includesrect( &reg->valid, &save ) );
return( 0 );
}
/* We need to make pixels using reg's generate function, and write the result
* to dest.
*/
static int
im_prepare_to_generate( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
IMAGE *im = reg->im;
char *p;
if( !im->generate ) {
vips_error( "im_prepare_to", "%s", _( "incomplete header" ) );
return( -1 );
}
if( im_region_region( reg, dest, r, x, y ) )
return( -1 );
/* Remember where reg is pointing now.
*/
p = IM_REGION_ADDR( reg, reg->valid.left, reg->valid.top );
/* Run sequence into reg.
*/
if( fill_region( reg ) )
return( -1 );
/* The generate function may not have actually made any pixels ... it
* might just have redirected reg to point somewhere else. If it has,
* we need an extra copy operation.
*/
if( IM_REGION_ADDR( reg, reg->valid.left, reg->valid.top ) != p )
im_region_copy( reg, dest, r, x, y );
return( 0 );
}
/**
* im_prepare_to:
* @reg: region to prepare
* @dest: region to write to
* @r: #Rect of pixels you need to be able to address
* @x: postion of @r in @dest
* @y: postion of @r in @dest
*
* Like im_prepare(): fill @reg with data, ready to be read from by our caller.
* Unlike im_prepare(), rather than allocating memory local to @reg for the
* result, we guarantee that we will fill the pixels in @dest at offset @x, @y.
* In other words, we generate an extra copy operation if necessary.
*
* Also unlike im_prepare(), @dest is not set up for writing for you with
* im_region_buffer(). You can
* point @dest at anything, and pixels really will be written there.
* This makes im_prepare_to() useful for making the ends of pipelines, since
* it (effectively) makes a break in the pipe.
*
* See also: im_prepare(), vips_sink_disc().
*
* Returns: 0 on success, or -1 on error
*/
int
im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
IMAGE *im = reg->im;
Rect image;
Rect wanted;
Rect clipped;
Rect clipped2;
Rect final;
if( im__test_kill( im ) )
return( -1 );
/* Sanity check.
*/
if( !dest->data ||
dest->im->BandFmt != reg->im->BandFmt ||
dest->im->Bands != reg->im->Bands ) {
vips_error( "im_prepare_to",
"%s", _( "inappropriate region type" ) );
return( -1 );
}
/* clip r first against the size of reg->im, then again against the
* memory we have available to write to on dest. Just like
* im_region_region()
*/
image.top = 0;
image.left = 0;
image.width = reg->im->Xsize;
image.height = reg->im->Ysize;
im_rect_intersectrect( r, &image, &clipped );
g_assert( clipped.left == r->left );
g_assert( clipped.top == r->top );
wanted.left = x + (clipped.left - r->left);
wanted.top = y + (clipped.top - r->top);
wanted.width = clipped.width;
wanted.height = clipped.height;
/* Test that dest->valid is large enough.
*/
if( !im_rect_includesrect( &dest->valid, &wanted ) ) {
vips_error( "im_prepare_to", "%s", _( "dest too small" ) );
return( -1 );
}
im_rect_intersectrect( &wanted, &dest->valid, &clipped2 );
/* Translate back to reg's coordinate space and set as valid.
*/
final.left = r->left + (clipped2.left - wanted.left);
final.top = r->top + (clipped2.top - wanted.top);
final.width = clipped2.width;
final.height = clipped2.height;
x = clipped2.left;
y = clipped2.top;
if( im_rect_isempty( &final ) ) {
vips_error( "im_prepare_to",
"%s", _( "valid clipped to nothing" ) );
return( -1 );
}
#ifdef DEBUG
printf( "im_prepare_to: left = %d, top = %d, width = %d, height = %d\n",
final.left, final.top, final.width, final.height );
#endif /*DEBUG*/
/* Input or output image type?
*/
switch( im->dtype ) {
case VIPS_IMAGE_OPENOUT:
case VIPS_IMAGE_PARTIAL:
/* We are generating with a sequence.
*/
if( im_prepare_to_generate( reg, dest, &final, x, y ) )
return( -1 );
break;
case VIPS_IMAGE_MMAPIN:
case VIPS_IMAGE_MMAPINRW:
case VIPS_IMAGE_OPENIN:
/* Attach to existing buffer and copy to dest.
*/
if( im_region_image( reg, &final ) )
return( -1 );
im_region_copy( reg, dest, &final, x, y );
break;
case VIPS_IMAGE_SETBUF:
case VIPS_IMAGE_SETBUF_FOREIGN:
/* Could be either input or output. If there is a generate
* function, we are outputting.
*/
if( im->generate ) {
if( im_prepare_to_generate( reg, dest, &final, x, y ) )
return( -1 );
}
else {
if( im_region_image( reg, &final ) )
return( -1 );
im_region_copy( reg, dest, &final, x, y );
}
break;
default:
vips_error( "im_prepare_to", _( "unable to input from a "
"%s image" ), im_dtype2char( im->dtype ) );
return( -1 );
}
/* We've written fresh pixels to dest, it's no longer invalid (if it
* was).
*
* We need this extra thing here because, unlike im_prepare(), we
* don't im_region_buffer() dest before writing it.
*/
dest->invalid = FALSE;
return( 0 );
}
int
im_prepare_many( REGION **reg, Rect *r )
{
for( ; *reg; ++reg )
if( im_prepare( *reg, r ) )
return( -1 );
return( 0 );
}

View File

@ -62,12 +62,12 @@ typedef struct {
*/
#define MAX_INPUT_IMAGES (64)
/* Convert a REGION.
/* Convert a VipsRegion.
*/
static int
process_region( REGION *or, void *seq, void *a, void *b )
process_region( VipsRegion *or, void *seq, void *a, void *b )
{
REGION **ir = (REGION **) seq;
VipsRegion **ir = (VipsRegion **) seq;
Bundle *bun = (Bundle *) b;
PEL *p[MAX_INPUT_IMAGES], *q;
@ -76,13 +76,13 @@ process_region( REGION *or, void *seq, void *a, void *b )
/* Prepare all input regions and make buffer pointers.
*/
for( i = 0; ir[i]; i++ ) {
if( im_prepare( ir[i], &or->valid ) )
if( vips_region_prepare( ir[i], &or->valid ) )
return( -1 );
p[i] = (PEL *) IM_REGION_ADDR( ir[i],
p[i] = (PEL *) VIPS_REGION_ADDR( ir[i],
or->valid.left, or->valid.top );
}
p[i] = NULL;
q = (PEL *) IM_REGION_ADDR( or, or->valid.left, or->valid.top );
q = (PEL *) VIPS_REGION_ADDR( or, or->valid.left, or->valid.top );
/* Convert linewise.
*/
@ -103,8 +103,8 @@ process_region( REGION *or, void *seq, void *a, void *b )
/* Move pointers on.
*/
for( i = 0; ir[i]; i++ )
p[i] += IM_REGION_LSKIP( ir[i] );
q += IM_REGION_LSKIP( or );
p[i] += VIPS_REGION_LSKIP( ir[i] );
q += VIPS_REGION_LSKIP( or );
}
return( 0 );

View File

@ -448,6 +448,8 @@ vips_image_print( VipsObject *object, VipsBuf *buf )
vips_image_get_bands( image ),
VIPS_ENUM_NICK( VIPS_TYPE_INTERPRETATION,
vips_image_get_interpretation( image ) ) );
VIPS_OBJECT_CLASS( vips_image_parent_class )->print( object, buf );
}
static gboolean
@ -623,26 +625,26 @@ open_lazy_start( VipsImage *out, void *a, void *dummy )
}
}
return( im_region_create( lazy->real ) );
return( vips_region_new( lazy->real ) );
}
/* Just copy.
*/
static int
open_lazy_generate( REGION *or, void *seq, void *a, void *b )
open_lazy_generate( VipsRegion *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
VipsRegion *ir = (VipsRegion *) seq;
Rect *r = &or->valid;
/* Ask for input we need.
*/
if( im_prepare( ir, r ) )
if( vips_region_prepare( ir, r ) )
return( -1 );
/* Attach output region to that.
*/
if( im_region_region( or, ir, r, r->left, r->top ) )
if( vips_region_region( or, ir, r, r->left, r->top ) )
return( -1 );
return( 0 );
@ -948,7 +950,7 @@ vips_image_build( VipsObject *object )
}
static void *
vips_region_invalidate( REGION *reg )
vips_region_invalidate( VipsRegion *reg )
{
reg->invalid = TRUE;

View File

@ -977,9 +977,9 @@ build_args( im_function *fn, im_object *vargv, int argc, char **argv )
/* Free a region, but return 0 so we can be used as a close callback.
*/
static void
region_local_image_cb( VipsImage *main, REGION *reg )
region_local_image_cb( VipsImage *main, VipsRegion *reg )
{
im_region_free( reg );
g_object_unref( reg );
}
/* Make a region on sub, closed by callback on main.
@ -987,9 +987,9 @@ region_local_image_cb( VipsImage *main, REGION *reg )
static int
region_local_image( IMAGE *main, IMAGE *sub )
{
REGION *reg;
VipsRegion *reg;
if( !(reg = im_region_create( sub )) )
if( !(reg = vips_region_new( sub )) )
return( -1 );
g_signal_connect( main, "close",
G_CALLBACK( region_local_image_cb ), reg );

View File

@ -91,12 +91,12 @@ im_rect_includesrect( Rect *r1, Rect *r2 )
void
im_rect_intersectrect( Rect *r1, Rect *r2, Rect *r3 )
{
int left = IM_MAX( r1->left, r2->left );
int top = IM_MAX( r1->top, r2->top );
int right = IM_MIN( IM_RECT_RIGHT( r1 ), IM_RECT_RIGHT( r2 ) );
int bottom = IM_MIN( IM_RECT_BOTTOM( r1 ), IM_RECT_BOTTOM( r2 ) );
int width = IM_MAX( 0, right - left );
int height = IM_MAX( 0, bottom - top );
int left = VIPS_MAX( r1->left, r2->left );
int top = VIPS_MAX( r1->top, r2->top );
int right = VIPS_MIN( IM_RECT_RIGHT( r1 ), IM_RECT_RIGHT( r2 ) );
int bottom = VIPS_MIN( IM_RECT_BOTTOM( r1 ), IM_RECT_BOTTOM( r2 ) );
int width = VIPS_MAX( 0, right - left );
int height = VIPS_MAX( 0, bottom - top );
r3->left = left;
r3->top = top;
@ -124,11 +124,11 @@ im_rect_unionrect( Rect *r1, Rect *r2, Rect *r3 )
else if( im_rect_isempty( r2 ) )
*r3 = *r1;
else {
int left = IM_MIN( r1->left, r2->left );
int top = IM_MIN( r1->top, r2->top );
int width = IM_MAX( IM_RECT_RIGHT( r1 ),
int left = VIPS_MIN( r1->left, r2->left );
int top = VIPS_MIN( r1->top, r2->top );
int width = VIPS_MAX( IM_RECT_RIGHT( r1 ),
IM_RECT_RIGHT( r2 ) ) - left;
int height = IM_MAX( IM_RECT_BOTTOM( r1 ),
int height = VIPS_MAX( IM_RECT_BOTTOM( r1 ),
IM_RECT_BOTTOM( r2 ) )- top;
r3->left = left;
@ -152,7 +152,7 @@ im_rect_equalsrect( Rect *r1, Rect *r2 )
Rect *
im_rect_dup( Rect *r )
{
Rect *out = IM_NEW( NULL, Rect );
Rect *out = VIPS_NEW( NULL, Rect );
if( !out )
return( NULL );

File diff suppressed because it is too large Load Diff

View File

@ -93,7 +93,7 @@ typedef struct _SinkThreadState {
/* The region we walk over sink.t copy. We can't use
* parent_object.reg, it's defined on the outer image.
*/
REGION *reg;
VipsRegion *reg;
} SinkThreadState;
typedef struct _SinkThreadStateClass {
@ -131,7 +131,7 @@ sink_thread_state_dispose( GObject *gobject )
Sink *sink = (Sink *) ((VipsThreadState *) state)->a;
sink_call_stop( sink, state );
VIPS_FREEF( im_region_free, state->reg );
VIPS_FREEF( g_object_unref, state->reg );
G_OBJECT_CLASS( sink_thread_state_parent_class )->dispose( gobject );
}
@ -163,7 +163,7 @@ sink_thread_state_build( VipsObject *object )
SinkThreadState *state = (SinkThreadState *) object;
Sink *sink = (Sink *) ((VipsThreadState *) state)->a;
if( !(state->reg = im_region_create( sink->t )) ||
if( !(state->reg = vips_region_new( sink->t )) ||
sink_call_start( sink, state ) )
return( -1 );
@ -278,7 +278,7 @@ sink_work( VipsThreadState *state, void *a )
SinkThreadState *sstate = (SinkThreadState *) state;
Sink *sink = (Sink *) a;
if( im_prepare( sstate->reg, &state->pos ) ||
if( vips_region_prepare( sstate->reg, &state->pos ) ||
sink->generate( sstate->reg, sstate->seq, sink->a, sink->b ) )
return( -1 );

View File

@ -70,7 +70,7 @@
typedef struct _WriteBuffer {
struct _Write *write;
REGION *region; /* Pixels */
VipsRegion *region; /* Pixels */
Rect area; /* Part of image this region covers */
im_semaphore_t go; /* Start bg thread loop */
im_semaphore_t nwrite; /* Number of threads writing to region */
@ -168,7 +168,7 @@ wbuffer_free( WriteBuffer *wbuffer )
wbuffer->thread = NULL;
}
VIPS_FREEF( im_region_free, wbuffer->region );
VIPS_FREEF( g_object_unref, wbuffer->region );
im_semaphore_destroy( &wbuffer->go );
im_semaphore_destroy( &wbuffer->nwrite );
im_semaphore_destroy( &wbuffer->done );
@ -234,14 +234,14 @@ wbuffer_new( Write *write )
wbuffer->thread = NULL;
wbuffer->kill = FALSE;
if( !(wbuffer->region = im_region_create( write->im )) ) {
if( !(wbuffer->region = vips_region_new( write->im )) ) {
wbuffer_free( wbuffer );
return( NULL );
}
/* The worker threads need to be able to move the buffers around.
*/
im__region_no_ownership( wbuffer->region );
vips__region_no_ownership( wbuffer->region );
#ifdef HAVE_THREADS
/* Make this last (picks up parts of wbuffer on startup).
@ -315,11 +315,11 @@ wbuffer_position( WriteBuffer *wbuffer, int top, int height )
/* The workers take turns to move the buffers.
*/
im__region_take_ownership( wbuffer->region );
vips__region_take_ownership( wbuffer->region );
result = im_region_buffer( wbuffer->region, &wbuffer->area );
result = vips_region_buffer( wbuffer->region, &wbuffer->area );
im__region_no_ownership( wbuffer->region );
vips__region_no_ownership( wbuffer->region );
/* This should be an exclusive buffer, hopefully.
*/

View File

@ -58,7 +58,7 @@ typedef struct _Sink {
/* A big region for the image memory. All the threads write to this.
*/
REGION *all;
VipsRegion *all;
/* The position we're at in the image.
*/
@ -75,7 +75,7 @@ typedef struct _Sink {
static void
sink_free( Sink *sink )
{
VIPS_FREEF( im_region_free, sink->all );
VIPS_FREEF( g_object_unref, sink->all );
}
static int
@ -92,8 +92,8 @@ sink_init( Sink *sink, VipsImage *im )
all.width = im->Xsize;
all.height = im->Ysize;
if( !(sink->all = im_region_create( im )) ||
im_region_image( sink->all, &all ) ) {
if( !(sink->all = vips_region_new( im )) ||
vips_region_image( sink->all, &all ) ) {
sink_free( sink );
return( -1 );
}
@ -148,7 +148,7 @@ sink_work( VipsThreadState *state, void *a )
{
Sink *sink = (Sink *) a;
if( im_prepare_to( state->reg, sink->all,
if( vips_region_prepare_to( state->reg, sink->all,
&state->pos, state->pos.left, state->pos.top ) )
return( -1 );

View File

@ -88,7 +88,7 @@ typedef struct {
struct _Render *render;
Rect area; /* Place here (unclipped) */
REGION *region; /* REGION with the pixels */
VipsRegion *region; /* VipsRegion with the pixels */
/* The tile contains calculated pixels. Though the region may have been
* invalidated behind our backs: we have to check that too.
@ -208,7 +208,7 @@ tile_free( Tile *tile )
{
VIPS_DEBUG_MSG_AMBER( "tile_free\n" );
VIPS_FREEF( im_region_free, tile->region );
VIPS_FREEF( g_object_unref, tile->region );
im_free( tile );
return( NULL );
@ -426,9 +426,10 @@ render_work( VipsThreadState *state, void *a )
VIPS_DEBUG_MSG( "calculating tile %p %dx%d\n",
tile, tile->area.left, tile->area.top );
if( im_prepare_to( state->reg, tile->region,
if( vips_region_prepare_to( state->reg, tile->region,
&tile->area, tile->area.left, tile->area.top ) ) {
VIPS_DEBUG_MSG_RED( "render_work: im_prepare_to() failed\n" );
VIPS_DEBUG_MSG_RED( "render_work: "
"vips_region_prepare_to() failed\n" );
return( -1 );
}
tile->painted = TRUE;
@ -665,7 +666,7 @@ tile_new( Render *render )
tile->dirty = FALSE;
tile->ticks = render->ticks;
if( !(tile->region = im_region_create( render->in )) ) {
if( !(tile->region = vips_region_new( render->in )) ) {
(void) tile_free( tile );
return( NULL );
}
@ -699,7 +700,7 @@ render_tile_add( Tile *tile, Rect *area )
/* Ignore buffer allocate errors, there's not much we could do with
* them.
*/
if( im_region_buffer( tile->region, &tile->area ) )
if( vips_region_buffer( tile->region, &tile->area ) )
VIPS_DEBUG_MSG_RED( "render_tile_add: "
"buffer allocate failed\n" );
@ -739,7 +740,7 @@ tile_touch( Tile *tile )
/* Queue a tile for calculation.
*/
static void
tile_queue( Tile *tile, REGION *reg )
tile_queue( Tile *tile, VipsRegion *reg )
{
Render *render = tile->render;
@ -772,7 +773,7 @@ tile_queue( Tile *tile, REGION *reg )
*/
g_mutex_unlock( render->lock );
if( im_prepare_to( reg, tile->region,
if( vips_region_prepare_to( reg, tile->region,
&tile->area, tile->area.left, tile->area.top ) )
VIPS_DEBUG_MSG_RED( "tile_queue: prepare failed\n" );
@ -813,7 +814,7 @@ render_tile_get_painted( Render *render )
* or if we've no threads or no notify, calculate immediately.
*/
static Tile *
render_tile_request( Render *render, REGION *reg, Rect *area )
render_tile_request( Render *render, VipsRegion *reg, Rect *area )
{
Tile *tile;
@ -863,7 +864,7 @@ render_tile_request( Render *render, REGION *reg, Rect *area )
/* Copy what we can from the tile into the region.
*/
static void
tile_copy( Tile *tile, REGION *to )
tile_copy( Tile *tile, VipsRegion *to )
{
Rect ovlap;
int y;
@ -884,9 +885,9 @@ tile_copy( Tile *tile, REGION *to )
tile, tile->area.left, tile->area.top );
for( y = ovlap.top; y < IM_RECT_BOTTOM( &ovlap ); y++ ) {
PEL *p = (PEL *) IM_REGION_ADDR( tile->region,
PEL *p = (PEL *) VIPS_REGION_ADDR( tile->region,
ovlap.left, y );
PEL *q = (PEL *) IM_REGION_ADDR( to, ovlap.left, y );
PEL *q = (PEL *) VIPS_REGION_ADDR( to, ovlap.left, y );
memcpy( q, p, len );
}
@ -894,7 +895,7 @@ tile_copy( Tile *tile, REGION *to )
else {
VIPS_DEBUG_MSG( "tile_copy: zero filling for %p %dx%d\n",
tile, tile->area.left, tile->area.top );
im_region_paint( to, &ovlap, 0 );
vips_region_paint( to, &ovlap, 0 );
}
}
@ -903,16 +904,16 @@ image_start( IMAGE *out, void *a, void *b )
{
Render *render = (Render *) a;
return( im_region_create( render->in ) );
return( vips_region_new( render->in ) );
}
/* Loop over the output region, filling with data from cache.
*/
static int
image_fill( REGION *out, void *seq, void *a, void *b )
image_fill( VipsRegion *out, void *seq, void *a, void *b )
{
Render *render = (Render *) a;
REGION *reg = (REGION *) seq;
VipsRegion *reg = (VipsRegion *) seq;
Rect *r = &out->valid;
int x, y;
@ -959,9 +960,9 @@ image_fill( REGION *out, void *seq, void *a, void *b )
static int
image_stop( void *seq, void *a, void *b )
{
REGION *reg = (REGION *) seq;
VipsRegion *reg = (VipsRegion *) seq;
im_region_free( reg );
g_object_unref( reg );
return( 0 );
}
@ -969,7 +970,7 @@ image_stop( void *seq, void *a, void *b )
/* The mask image is 255 / 0 for the state of painted for each tile.
*/
static int
mask_fill( REGION *out, void *seq, void *a, void *b )
mask_fill( VipsRegion *out, void *seq, void *a, void *b )
{
#ifdef HAVE_THREADS
Render *render = (Render *) a;
@ -1005,12 +1006,12 @@ mask_fill( REGION *out, void *seq, void *a, void *b )
/* Only mark painted tiles containing valid pixels.
*/
im_region_paint( out, &area, value );
vips_region_paint( out, &area, value );
}
g_mutex_unlock( render->lock );
#else /*!HAVE_THREADS*/
im_region_paint( out, &out->valid, 255 );
vips_region_paint( out, &out->valid, 255 );
#endif /*HAVE_THREADS*/
return( 0 );
@ -1044,7 +1045,8 @@ mask_fill( REGION *out, void *seq, void *a, void *b )
* priority, negative numbers are low priority, positive numbers high
* priority.
*
* Calls to im_prepare() on @out return immediately and hold whatever is
* Calls to vips_region_prepare() on @out return immediately and hold
* whatever is
* currently in cache for that #Rect (check @mask to see which parts of the
* #Rect are valid). Any pixels in the #Rect which are not in cache are added
* to a queue, and the @notify callback will trigger when those pixels are
@ -1056,10 +1058,11 @@ mask_fill( REGION *out, void *seq, void *a, void *b )
* ready. In a glib-based application, this is easily done with g_idle_add().
*
* If @notify is %NULL then im_render_priority() runs synchronously.
* im_prepare() on @out will always block until the pixels have been
* vips_region_prepare() on @out will always block until the pixels have been
* calculated.
*
* See also: im_cache(), im_tile_cache(), im_prepare(), vips_sink_disc(),
* See also: im_cache(), im_tile_cache(), vips_region_prepare(),
* vips_sink_disc(),
* vips_sink().
*
* Returns: 0 on sucess, -1 on error.