clean up sink

common up some stuff in the sinks
This commit is contained in:
John Cupitt 2011-03-28 14:08:42 +01:00
parent 59f88260d6
commit b13872f111
6 changed files with 156 additions and 213 deletions

27
TODO
View File

@ -1,32 +1,5 @@
- add MATLAB write
- sink.c, sinkdisc.c, sinkmemory.c all define this function:
static int
sink_progress( void *a )
{
Sink *sink = (Sink *) a;
VIPS_DEBUG_MSG( "sink_progress: %d x %d\n",
sink->tile_width, sink->tile_height );
/* Trigger any eval callbacks on our source image and
* check for errors.
*/
vips_image_eval( sink->im,
sink->tile_width, sink->tile_height );
if( vips_image_get_kill( im ) )
return( -1 );
return( 0 );
}
how dumb, common this up somehow
sink.c is the replacement for im_iterate()
- need a way to make the vips.1 etc. man pages
gtk has things like docs/reference/gtk/gtk-update-icon-cache.xml and man

View File

@ -11,10 +11,11 @@ libiofuncs_la_SOURCES = \
vips.c \
generate.c \
mapfile.c \
sinkmemory.c \
sinkscreen.c \
sinkdisc.c \
sink.h \
sink.c \
sinkmemory.c \
sinkdisc.c \
sinkscreen.c \
memory.c \
package.c \
header.c \

View File

@ -47,6 +47,8 @@
#include <vips/internal.h>
#include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
@ -54,24 +56,13 @@
/* Per-call state.
*/
typedef struct _Sink {
VipsImage *im;
SinkBase sink_base;
/* We need a temp "p" image between the source image and us to
* make sure we can't damage the original.
*/
VipsImage *t;
/* The position we're at in the image.
*/
int x;
int y;
/* The tilesize we've picked.
*/
int tile_width;
int tile_height;
int nlines;
/* Call params.
*/
VipsStartFn start;
@ -112,9 +103,11 @@ sink_call_stop( Sink *sink, SinkThreadState *state )
VIPS_DEBUG_MSG( "sink_call_stop: state = %p\n", state );
if( sink->stop( state->seq, sink->a, sink->b ) ) {
SinkBase *sink_base = (SinkBase *) sink;
vips_error( "vips_sink",
_( "stop function failed for image \"%s\"" ),
sink->im->filename );
sink_base->im->filename );
return( -1 );
}
@ -147,9 +140,11 @@ sink_call_start( Sink *sink, SinkThreadState *state )
state->seq = sink->start( sink->t, sink->a, sink->b );
if( !state->seq ) {
SinkBase *sink_base = (SinkBase *) sink;
vips_error( "vips_sink",
_( "start function failed for image \"%s\"" ),
sink->im->filename );
sink_base->im->filename );
return( -1 );
}
}
@ -205,16 +200,27 @@ sink_free( Sink *sink )
VIPS_FREEF( g_object_unref, sink->t );
}
void
vips_sink_base_init( SinkBase *sink_base, VipsImage *image )
{
sink_base->im = image;
sink_base->x = 0;
sink_base->y = 0;
vips_get_tile_size( image,
&sink_base->tile_width, &sink_base->tile_height,
&sink_base->nlines );
}
static int
sink_init( Sink *sink,
VipsImage *im,
VipsImage *image,
VipsStartFn start, VipsGenerateFn generate, VipsStopFn stop,
void *a, void *b )
{
sink->im = im;
vips_sink_base_init( &sink->sink_base, image );
sink->t = NULL;
sink->x = 0;
sink->y = 0;
sink->start = start;
sink->generate = generate;
sink->stop = stop;
@ -222,31 +228,28 @@ sink_init( Sink *sink,
sink->b = b;
if( !(sink->t = vips_image_new( "p" )) ||
im_copy( sink->im, sink->t ) ) {
im_copy( sink->sink_base.im, sink->t ) ) {
sink_free( sink );
return( -1 );
}
vips_get_tile_size( im,
&sink->tile_width, &sink->tile_height, &sink->nlines );
return( 0 );
}
static int
sink_allocate( VipsThreadState *state, void *a, gboolean *stop )
int
vips_sink_base_allocate( VipsThreadState *state, void *a, gboolean *stop )
{
Sink *sink = (Sink *) a;
SinkBase *sink_base = (SinkBase *) a;
VipsRect image, tile;
/* Is the state x/y OK? New line or maybe all done.
*/
if( sink->x >= sink->im->Xsize ) {
sink->x = 0;
sink->y += sink->tile_height;
if( sink_base->x >= sink_base->im->Xsize ) {
sink_base->x = 0;
sink_base->y += sink_base->tile_height;
if( sink->y >= sink->im->Ysize ) {
if( sink_base->y >= sink_base->im->Ysize ) {
*stop = TRUE;
return( 0 );
@ -257,17 +260,17 @@ sink_allocate( VipsThreadState *state, void *a, gboolean *stop )
*/
image.left = 0;
image.top = 0;
image.width = sink->im->Xsize;
image.height = sink->im->Ysize;
tile.left = sink->x;
tile.top = sink->y;
tile.width = sink->tile_width;
tile.height = sink->tile_height;
image.width = sink_base->im->Xsize;
image.height = sink_base->im->Ysize;
tile.left = sink_base->x;
tile.top = sink_base->y;
tile.width = sink_base->tile_width;
tile.height = sink_base->tile_height;
vips_rect_intersectrect( &image, &tile, &state->pos );
/* Move state on.
*/
sink->x += sink->tile_width;
sink_base->x += sink_base->tile_width;
return( 0 );
}
@ -285,19 +288,20 @@ sink_work( VipsThreadState *state, void *a )
return( 0 );
}
static int
sink_progress( void *a )
int
vips_sink_base_progress( void *a )
{
Sink *sink = (Sink *) a;
SinkBase *sink_base = (SinkBase *) a;
VIPS_DEBUG_MSG( "sink_progress: %d x %d\n",
sink->tile_width, sink->tile_height );
VIPS_DEBUG_MSG( "vips_sink_base_progress: %d x %d\n",
sink_base->tile_width, sink_base->tile_height );
/* Trigger any eval callbacks on our source image and
* check for errors.
*/
vips_image_eval( sink->im, sink->tile_width, sink->tile_height );
if( vips_image_get_kill( sink->im ) )
vips_image_eval( sink_base->im,
sink_base->tile_width, sink_base->tile_height );
if( vips_image_get_kill( sink_base->im ) )
return( -1 );
return( 0 );
@ -349,17 +353,17 @@ vips_sink_tile( VipsImage *im,
return( -1 );
if( tile_width > 0 ) {
sink.tile_width = tile_width;
sink.tile_height = tile_height;
sink.sink_base.tile_width = tile_width;
sink.sink_base.tile_height = tile_height;
}
vips_image_preeval( sink.t );
result = vips_threadpool_run( im,
sink_thread_state_new,
sink_allocate,
vips_sink_base_allocate,
sink_work,
sink_progress,
vips_sink_base_progress,
&sink );
vips_image_posteval( sink.t );

68
libvips/iofuncs/sink.h Normal file
View File

@ -0,0 +1,68 @@
/* A sink that's not attached to anything, eg. find image average,
*
* 28/3/10
* - from im_iterate(), reworked for threadpool
*/
/*
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
*/
#ifndef VIPS_SINK_H
#define VIPS_SINK_H
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
/* Base for sink.c / sinkdisc.c / sinkmemory.c
*/
typedef struct _SinkBase {
VipsImage *im;
/* The position we're at in buf.
*/
int x;
int y;
/* The tilesize we've picked.
*/
int tile_width;
int tile_height;
int nlines;
} SinkBase;
/* Some function we can share.
*/
void vips_sink_base_init( SinkBase *sink_base, VipsImage *image );
int vips_sink_base_allocate( VipsThreadState *state, void *a, gboolean *stop );
int vips_sink_base_progress( void *a );
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*VIPS_SINK_H*/

View File

@ -61,6 +61,8 @@
#include <vips/threadpool.h>
#include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
@ -83,7 +85,7 @@ typedef struct _WriteBuffer {
/* Per-call state.
*/
typedef struct _Write {
VipsImage *im;
SinkBase sink_base;
/* We are current writing tiles to buf, buf_back is in the hands of
* the bg write thread.
@ -91,17 +93,6 @@ typedef struct _Write {
WriteBuffer *buf;
WriteBuffer *buf_back;
/* The position we're at in buf.
*/
int x;
int y;
/* The tilesize we've picked.
*/
int tile_width;
int tile_height;
int nlines;
/* The file format write operation.
*/
VipsRegionWrite write_fn;
@ -234,7 +225,7 @@ wbuffer_new( Write *write )
wbuffer->thread = NULL;
wbuffer->kill = FALSE;
if( !(wbuffer->region = vips_region_new( write->im )) ) {
if( !(wbuffer->region = vips_region_new( write->sink_base.im )) ) {
wbuffer_free( wbuffer );
return( NULL );
}
@ -303,12 +294,12 @@ wbuffer_position( WriteBuffer *wbuffer, int top, int height )
image.left = 0;
image.top = 0;
image.width = wbuffer->write->im->Xsize;
image.height = wbuffer->write->im->Ysize;
image.width = wbuffer->write->sink_base.im->Xsize;
image.height = wbuffer->write->sink_base.im->Ysize;
area.left = 0;
area.top = top;
area.width = wbuffer->write->im->Xsize;
area.width = wbuffer->write->sink_base.im->Xsize;
area.height = height;
vips_rect_intersectrect( &area, &image, &wbuffer->area );
@ -338,6 +329,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
{
WriteThreadState *wstate = (WriteThreadState *) state;
Write *write = (Write *) a;
SinkBase *sink_base = (SinkBase *) write;
VipsRect image;
VipsRect tile;
@ -347,11 +339,11 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* Is the state x/y OK? New line or maybe new buffer or maybe even
* all done.
*/
if( write->x >= write->buf->area.width ) {
write->x = 0;
write->y += write->tile_height;
if( sink_base->x >= write->buf->area.width ) {
sink_base->x = 0;
sink_base->y += sink_base->tile_height;
if( write->y >= VIPS_RECT_BOTTOM( &write->buf->area ) ) {
if( sink_base->y >= VIPS_RECT_BOTTOM( &write->buf->area ) ) {
/* Block until the last write is done, then set write
* of the front buffer going.
*/
@ -360,7 +352,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* End of image?
*/
if( write->y >= write->im->Ysize ) {
if( sink_base->y >= sink_base->im->Ysize ) {
*stop = TRUE;
return( 0 );
}
@ -378,7 +370,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* Position buf at the new y.
*/
if( wbuffer_position( write->buf,
write->y, write->nlines ) )
sink_base->y, sink_base->nlines ) )
return( -1 );
}
}
@ -387,12 +379,12 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
*/
image.left = 0;
image.top = 0;
image.width = write->im->Xsize;
image.height = write->im->Ysize;
tile.left = write->x;
tile.top = write->y;
tile.width = write->tile_width;
tile.height = write->tile_height;
image.width = sink_base->im->Xsize;
image.height = sink_base->im->Ysize;
tile.left = sink_base->x;
tile.top = sink_base->y;
tile.width = sink_base->tile_width;
tile.height = sink_base->tile_height;
vips_rect_intersectrect( &image, &tile, &state->pos );
wstate->buf = write->buf;
@ -402,7 +394,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* Move state on.
*/
write->x += write->tile_width;
sink_base->x += sink_base->tile_width;
return( 0 );
}
@ -427,40 +419,16 @@ wbuffer_work_fn( VipsThreadState *state, void *a )
return( 0 );
}
/* Our VipsThreadpoolProgress function ... send some eval progress feedback.
*/
static int
wbuffer_progress_fn( void *a )
{
Write *write = (Write *) a;
VIPS_DEBUG_MSG( "wbuffer_progress_fn: %d x %d\n",
write->tile_width, write->tile_height );
/* Trigger any eval callbacks on our source image and
* check for errors.
*/
vips_image_eval( write->im, write->tile_width, write->tile_height );
if( vips_image_get_kill( write->im ) )
return( -1 );
return( 0 );
}
static void
write_init( Write *write,
VipsImage *im, VipsRegionWrite write_fn, void *a )
VipsImage *image, VipsRegionWrite write_fn, void *a )
{
write->im = im;
vips_sink_base_init( &write->sink_base, image );
write->buf = wbuffer_new( write );
write->buf_back = wbuffer_new( write );
write->x = 0;
write->y = 0;
write->write_fn = write_fn;
write->a = a;
vips_get_tile_size( im,
&write->tile_width, &write->tile_height, &write->nlines );
}
static void
@ -479,7 +447,7 @@ write_free( Write *write )
* The function should write the pixels in @area from @region. @a is the
* value passed into vips_discsink().
*
* See also: vips_discsink().
* See also: vips_sink_disc().
*
* Returns: 0 on success, -1 on error.
*/
@ -517,12 +485,12 @@ vips_sink_disc( VipsImage *im, VipsRegionWrite write_fn, void *a )
result = 0;
if( !write.buf ||
!write.buf_back ||
wbuffer_position( write.buf, 0, write.nlines ) ||
wbuffer_position( write.buf, 0, write.sink_base.nlines ) ||
vips_threadpool_run( im,
write_thread_state_new,
wbuffer_allocate_fn,
wbuffer_work_fn,
wbuffer_progress_fn,
vips_sink_base_progress,
&write ) )
result = -1;

View File

@ -47,6 +47,8 @@
#include <vips/internal.h>
#include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
@ -54,22 +56,11 @@
/* Per-call state.
*/
typedef struct _Sink {
VipsImage *im;
SinkBase sink_base;
/* A big region for the image memory. All the threads write to this.
*/
VipsRegion *all;
/* The position we're at in the image.
*/
int x;
int y;
/* The tilesize we've picked.
*/
int tile_width;
int tile_height;
int nlines;
} Sink;
static void
@ -83,9 +74,7 @@ sink_init( Sink *sink, VipsImage *im )
{
VipsRect all;
sink->im = im;
sink->x = 0;
sink->y = 0;
vips_sink_base_init( &sink->sink_base, im );
all.left = 0;
all.top = 0;
@ -98,48 +87,6 @@ sink_init( Sink *sink, VipsImage *im )
return( -1 );
}
vips_get_tile_size( im,
&sink->tile_width, &sink->tile_height, &sink->nlines );
return( 0 );
}
static int
sink_allocate( VipsThreadState *state, void *a, gboolean *stop )
{
Sink *sink = (Sink *) a;
VipsRect image, tile;
/* Is the state x/y OK? New line or maybe all done.
*/
if( sink->x >= sink->im->Xsize ) {
sink->x = 0;
sink->y += sink->tile_height;
if( sink->y >= sink->im->Ysize ) {
*stop = TRUE;
return( 0 );
}
}
/* x, y and buf are good: save params for thread.
*/
image.left = 0;
image.top = 0;
image.width = sink->im->Xsize;
image.height = sink->im->Ysize;
tile.left = sink->x;
tile.top = sink->y;
tile.width = sink->tile_width;
tile.height = sink->tile_height;
vips_rect_intersectrect( &image, &tile, &state->pos );
/* Move state on.
*/
sink->x += sink->tile_width;
return( 0 );
}
@ -155,24 +102,6 @@ sink_work( VipsThreadState *state, void *a )
return( 0 );
}
static int
sink_progress( void *a )
{
Sink *sink = (Sink *) a;
VIPS_DEBUG_MSG( "sink_progress: %d x %d\n",
sink->tile_width, sink->tile_height );
/* Trigger any eval callbacks on our source image and
* check for errors.
*/
vips_image_eval( sink->im, sink->tile_width, sink->tile_height );
if( vips_image_get_kill( sink->im ) )
return( -1 );
return( 0 );
}
/**
* vips_sink_memory:
* @im: generate this image to memory
@ -204,9 +133,9 @@ vips_sink_memory( VipsImage *im )
result = vips_threadpool_run( im,
vips_thread_state_new,
sink_allocate,
vips_sink_base_allocate,
sink_work,
sink_progress,
vips_sink_base_progress,
&sink );
vips_image_posteval( im );