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 - 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 - 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 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 \ vips.c \
generate.c \ generate.c \
mapfile.c \ mapfile.c \
sinkmemory.c \ sink.h \
sinkscreen.c \
sinkdisc.c \
sink.c \ sink.c \
sinkmemory.c \
sinkdisc.c \
sinkscreen.c \
memory.c \ memory.c \
package.c \ package.c \
header.c \ header.c \

View File

@ -47,6 +47,8 @@
#include <vips/internal.h> #include <vips/internal.h>
#include <vips/debug.h> #include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC #ifdef WITH_DMALLOC
#include <dmalloc.h> #include <dmalloc.h>
#endif /*WITH_DMALLOC*/ #endif /*WITH_DMALLOC*/
@ -54,24 +56,13 @@
/* Per-call state. /* Per-call state.
*/ */
typedef struct _Sink { typedef struct _Sink {
VipsImage *im; SinkBase sink_base;
/* We need a temp "p" image between the source image and us to /* We need a temp "p" image between the source image and us to
* make sure we can't damage the original. * make sure we can't damage the original.
*/ */
VipsImage *t; 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. /* Call params.
*/ */
VipsStartFn start; VipsStartFn start;
@ -112,9 +103,11 @@ sink_call_stop( Sink *sink, SinkThreadState *state )
VIPS_DEBUG_MSG( "sink_call_stop: state = %p\n", state ); VIPS_DEBUG_MSG( "sink_call_stop: state = %p\n", state );
if( sink->stop( state->seq, sink->a, sink->b ) ) { if( sink->stop( state->seq, sink->a, sink->b ) ) {
SinkBase *sink_base = (SinkBase *) sink;
vips_error( "vips_sink", vips_error( "vips_sink",
_( "stop function failed for image \"%s\"" ), _( "stop function failed for image \"%s\"" ),
sink->im->filename ); sink_base->im->filename );
return( -1 ); return( -1 );
} }
@ -147,9 +140,11 @@ sink_call_start( Sink *sink, SinkThreadState *state )
state->seq = sink->start( sink->t, sink->a, sink->b ); state->seq = sink->start( sink->t, sink->a, sink->b );
if( !state->seq ) { if( !state->seq ) {
SinkBase *sink_base = (SinkBase *) sink;
vips_error( "vips_sink", vips_error( "vips_sink",
_( "start function failed for image \"%s\"" ), _( "start function failed for image \"%s\"" ),
sink->im->filename ); sink_base->im->filename );
return( -1 ); return( -1 );
} }
} }
@ -205,16 +200,27 @@ sink_free( Sink *sink )
VIPS_FREEF( g_object_unref, sink->t ); 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 static int
sink_init( Sink *sink, sink_init( Sink *sink,
VipsImage *im, VipsImage *image,
VipsStartFn start, VipsGenerateFn generate, VipsStopFn stop, VipsStartFn start, VipsGenerateFn generate, VipsStopFn stop,
void *a, void *b ) void *a, void *b )
{ {
sink->im = im; vips_sink_base_init( &sink->sink_base, image );
sink->t = NULL; sink->t = NULL;
sink->x = 0;
sink->y = 0;
sink->start = start; sink->start = start;
sink->generate = generate; sink->generate = generate;
sink->stop = stop; sink->stop = stop;
@ -222,31 +228,28 @@ sink_init( Sink *sink,
sink->b = b; sink->b = b;
if( !(sink->t = vips_image_new( "p" )) || if( !(sink->t = vips_image_new( "p" )) ||
im_copy( sink->im, sink->t ) ) { im_copy( sink->sink_base.im, sink->t ) ) {
sink_free( sink ); sink_free( sink );
return( -1 ); return( -1 );
} }
vips_get_tile_size( im,
&sink->tile_width, &sink->tile_height, &sink->nlines );
return( 0 ); return( 0 );
} }
static int int
sink_allocate( VipsThreadState *state, void *a, gboolean *stop ) vips_sink_base_allocate( VipsThreadState *state, void *a, gboolean *stop )
{ {
Sink *sink = (Sink *) a; SinkBase *sink_base = (SinkBase *) a;
VipsRect image, tile; VipsRect image, tile;
/* Is the state x/y OK? New line or maybe all done. /* Is the state x/y OK? New line or maybe all done.
*/ */
if( sink->x >= sink->im->Xsize ) { if( sink_base->x >= sink_base->im->Xsize ) {
sink->x = 0; sink_base->x = 0;
sink->y += sink->tile_height; sink_base->y += sink_base->tile_height;
if( sink->y >= sink->im->Ysize ) { if( sink_base->y >= sink_base->im->Ysize ) {
*stop = TRUE; *stop = TRUE;
return( 0 ); return( 0 );
@ -257,17 +260,17 @@ sink_allocate( VipsThreadState *state, void *a, gboolean *stop )
*/ */
image.left = 0; image.left = 0;
image.top = 0; image.top = 0;
image.width = sink->im->Xsize; image.width = sink_base->im->Xsize;
image.height = sink->im->Ysize; image.height = sink_base->im->Ysize;
tile.left = sink->x; tile.left = sink_base->x;
tile.top = sink->y; tile.top = sink_base->y;
tile.width = sink->tile_width; tile.width = sink_base->tile_width;
tile.height = sink->tile_height; tile.height = sink_base->tile_height;
vips_rect_intersectrect( &image, &tile, &state->pos ); vips_rect_intersectrect( &image, &tile, &state->pos );
/* Move state on. /* Move state on.
*/ */
sink->x += sink->tile_width; sink_base->x += sink_base->tile_width;
return( 0 ); return( 0 );
} }
@ -285,19 +288,20 @@ sink_work( VipsThreadState *state, void *a )
return( 0 ); return( 0 );
} }
static int int
sink_progress( void *a ) vips_sink_base_progress( void *a )
{ {
Sink *sink = (Sink *) a; SinkBase *sink_base = (SinkBase *) a;
VIPS_DEBUG_MSG( "sink_progress: %d x %d\n", VIPS_DEBUG_MSG( "vips_sink_base_progress: %d x %d\n",
sink->tile_width, sink->tile_height ); sink_base->tile_width, sink_base->tile_height );
/* Trigger any eval callbacks on our source image and /* Trigger any eval callbacks on our source image and
* check for errors. * check for errors.
*/ */
vips_image_eval( sink->im, sink->tile_width, sink->tile_height ); vips_image_eval( sink_base->im,
if( vips_image_get_kill( sink->im ) ) sink_base->tile_width, sink_base->tile_height );
if( vips_image_get_kill( sink_base->im ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -349,17 +353,17 @@ vips_sink_tile( VipsImage *im,
return( -1 ); return( -1 );
if( tile_width > 0 ) { if( tile_width > 0 ) {
sink.tile_width = tile_width; sink.sink_base.tile_width = tile_width;
sink.tile_height = tile_height; sink.sink_base.tile_height = tile_height;
} }
vips_image_preeval( sink.t ); vips_image_preeval( sink.t );
result = vips_threadpool_run( im, result = vips_threadpool_run( im,
sink_thread_state_new, sink_thread_state_new,
sink_allocate, vips_sink_base_allocate,
sink_work, sink_work,
sink_progress, vips_sink_base_progress,
&sink ); &sink );
vips_image_posteval( sink.t ); 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/threadpool.h>
#include <vips/debug.h> #include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC #ifdef WITH_DMALLOC
#include <dmalloc.h> #include <dmalloc.h>
#endif /*WITH_DMALLOC*/ #endif /*WITH_DMALLOC*/
@ -83,7 +85,7 @@ typedef struct _WriteBuffer {
/* Per-call state. /* Per-call state.
*/ */
typedef struct _Write { typedef struct _Write {
VipsImage *im; SinkBase sink_base;
/* We are current writing tiles to buf, buf_back is in the hands of /* We are current writing tiles to buf, buf_back is in the hands of
* the bg write thread. * the bg write thread.
@ -91,17 +93,6 @@ typedef struct _Write {
WriteBuffer *buf; WriteBuffer *buf;
WriteBuffer *buf_back; 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. /* The file format write operation.
*/ */
VipsRegionWrite write_fn; VipsRegionWrite write_fn;
@ -234,7 +225,7 @@ wbuffer_new( Write *write )
wbuffer->thread = NULL; wbuffer->thread = NULL;
wbuffer->kill = FALSE; wbuffer->kill = FALSE;
if( !(wbuffer->region = vips_region_new( write->im )) ) { if( !(wbuffer->region = vips_region_new( write->sink_base.im )) ) {
wbuffer_free( wbuffer ); wbuffer_free( wbuffer );
return( NULL ); return( NULL );
} }
@ -303,12 +294,12 @@ wbuffer_position( WriteBuffer *wbuffer, int top, int height )
image.left = 0; image.left = 0;
image.top = 0; image.top = 0;
image.width = wbuffer->write->im->Xsize; image.width = wbuffer->write->sink_base.im->Xsize;
image.height = wbuffer->write->im->Ysize; image.height = wbuffer->write->sink_base.im->Ysize;
area.left = 0; area.left = 0;
area.top = top; area.top = top;
area.width = wbuffer->write->im->Xsize; area.width = wbuffer->write->sink_base.im->Xsize;
area.height = height; area.height = height;
vips_rect_intersectrect( &area, &image, &wbuffer->area ); vips_rect_intersectrect( &area, &image, &wbuffer->area );
@ -338,6 +329,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
{ {
WriteThreadState *wstate = (WriteThreadState *) state; WriteThreadState *wstate = (WriteThreadState *) state;
Write *write = (Write *) a; Write *write = (Write *) a;
SinkBase *sink_base = (SinkBase *) write;
VipsRect image; VipsRect image;
VipsRect tile; 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 /* Is the state x/y OK? New line or maybe new buffer or maybe even
* all done. * all done.
*/ */
if( write->x >= write->buf->area.width ) { if( sink_base->x >= write->buf->area.width ) {
write->x = 0; sink_base->x = 0;
write->y += write->tile_height; 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 /* Block until the last write is done, then set write
* of the front buffer going. * of the front buffer going.
*/ */
@ -360,7 +352,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* End of image? /* End of image?
*/ */
if( write->y >= write->im->Ysize ) { if( sink_base->y >= sink_base->im->Ysize ) {
*stop = TRUE; *stop = TRUE;
return( 0 ); return( 0 );
} }
@ -378,7 +370,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* Position buf at the new y. /* Position buf at the new y.
*/ */
if( wbuffer_position( write->buf, if( wbuffer_position( write->buf,
write->y, write->nlines ) ) sink_base->y, sink_base->nlines ) )
return( -1 ); return( -1 );
} }
} }
@ -387,12 +379,12 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
*/ */
image.left = 0; image.left = 0;
image.top = 0; image.top = 0;
image.width = write->im->Xsize; image.width = sink_base->im->Xsize;
image.height = write->im->Ysize; image.height = sink_base->im->Ysize;
tile.left = write->x; tile.left = sink_base->x;
tile.top = write->y; tile.top = sink_base->y;
tile.width = write->tile_width; tile.width = sink_base->tile_width;
tile.height = write->tile_height; tile.height = sink_base->tile_height;
vips_rect_intersectrect( &image, &tile, &state->pos ); vips_rect_intersectrect( &image, &tile, &state->pos );
wstate->buf = write->buf; wstate->buf = write->buf;
@ -402,7 +394,7 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
/* Move state on. /* Move state on.
*/ */
write->x += write->tile_width; sink_base->x += sink_base->tile_width;
return( 0 ); return( 0 );
} }
@ -427,40 +419,16 @@ wbuffer_work_fn( VipsThreadState *state, void *a )
return( 0 ); 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 static void
write_init( Write *write, 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 = wbuffer_new( write );
write->buf_back = wbuffer_new( write ); write->buf_back = wbuffer_new( write );
write->x = 0;
write->y = 0;
write->write_fn = write_fn; write->write_fn = write_fn;
write->a = a; write->a = a;
vips_get_tile_size( im,
&write->tile_width, &write->tile_height, &write->nlines );
} }
static void static void
@ -479,7 +447,7 @@ write_free( Write *write )
* The function should write the pixels in @area from @region. @a is the * The function should write the pixels in @area from @region. @a is the
* value passed into vips_discsink(). * value passed into vips_discsink().
* *
* See also: vips_discsink(). * See also: vips_sink_disc().
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
*/ */
@ -517,12 +485,12 @@ vips_sink_disc( VipsImage *im, VipsRegionWrite write_fn, void *a )
result = 0; result = 0;
if( !write.buf || if( !write.buf ||
!write.buf_back || !write.buf_back ||
wbuffer_position( write.buf, 0, write.nlines ) || wbuffer_position( write.buf, 0, write.sink_base.nlines ) ||
vips_threadpool_run( im, vips_threadpool_run( im,
write_thread_state_new, write_thread_state_new,
wbuffer_allocate_fn, wbuffer_allocate_fn,
wbuffer_work_fn, wbuffer_work_fn,
wbuffer_progress_fn, vips_sink_base_progress,
&write ) ) &write ) )
result = -1; result = -1;

View File

@ -47,6 +47,8 @@
#include <vips/internal.h> #include <vips/internal.h>
#include <vips/debug.h> #include <vips/debug.h>
#include "sink.h"
#ifdef WITH_DMALLOC #ifdef WITH_DMALLOC
#include <dmalloc.h> #include <dmalloc.h>
#endif /*WITH_DMALLOC*/ #endif /*WITH_DMALLOC*/
@ -54,22 +56,11 @@
/* Per-call state. /* Per-call state.
*/ */
typedef struct _Sink { typedef struct _Sink {
VipsImage *im; SinkBase sink_base;
/* A big region for the image memory. All the threads write to this. /* A big region for the image memory. All the threads write to this.
*/ */
VipsRegion *all; 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; } Sink;
static void static void
@ -83,9 +74,7 @@ sink_init( Sink *sink, VipsImage *im )
{ {
VipsRect all; VipsRect all;
sink->im = im; vips_sink_base_init( &sink->sink_base, im );
sink->x = 0;
sink->y = 0;
all.left = 0; all.left = 0;
all.top = 0; all.top = 0;
@ -98,48 +87,6 @@ sink_init( Sink *sink, VipsImage *im )
return( -1 ); 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 ); return( 0 );
} }
@ -155,24 +102,6 @@ sink_work( VipsThreadState *state, void *a )
return( 0 ); 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: * vips_sink_memory:
* @im: generate this image to memory * @im: generate this image to memory
@ -204,9 +133,9 @@ vips_sink_memory( VipsImage *im )
result = vips_threadpool_run( im, result = vips_threadpool_run( im,
vips_thread_state_new, vips_thread_state_new,
sink_allocate, vips_sink_base_allocate,
sink_work, sink_work,
sink_progress, vips_sink_base_progress,
&sink ); &sink );
vips_image_posteval( im ); vips_image_posteval( im );