added sinkmemory, started removing threadgroup
This commit is contained in:
parent
54730feadc
commit
f1ebc12fb1
4
TODO
4
TODO
@ -5,6 +5,10 @@
|
||||
|
||||
- get rid of threadgroup too (deprecate?)
|
||||
|
||||
- can eval_to_region() go? I guess
|
||||
|
||||
- need an eval_to_memory for generate to use to write to "t" images
|
||||
|
||||
|
||||
- expose more of the tone funcs in nip2
|
||||
|
||||
|
@ -508,14 +508,14 @@ write_vips( REGION *region, Rect *area, void *a, void *b )
|
||||
* For images opened with "p", im_generate() just attaches the
|
||||
* start/generate/stop callbacks and returns.
|
||||
*
|
||||
* For "t" images, memory is allocated for the image and im_prepare_thread()
|
||||
* used to fill it with pixels.
|
||||
* For "t" images, memory is allocated for the whole image and it is entirely
|
||||
* generated using vips_sink().
|
||||
*
|
||||
* For "w" images, memory for a few scanlines is allocated and
|
||||
* im_prepare_thread() used to generate the image in small chunks. As each
|
||||
* vips_sink_disc() used to generate the image in small chunks. As each
|
||||
* chunk is generated, it is written to disc.
|
||||
*
|
||||
* See also: im_iterate(), im_open(), im_prepare(), im_wrapone().
|
||||
* See also: vips_sink(), im_open(), im_prepare(), im_wrapone().
|
||||
*
|
||||
* Returns: 0 on success, or -1 on error.
|
||||
*/
|
||||
@ -525,8 +525,6 @@ im_generate( IMAGE *im,
|
||||
void *a, void *b )
|
||||
{
|
||||
int res;
|
||||
REGION *or;
|
||||
im_threadgroup_t *tg;
|
||||
|
||||
g_assert( !im_image_sanity( im ) );
|
||||
|
||||
@ -596,24 +594,13 @@ im_generate( IMAGE *im,
|
||||
im->client1 = a;
|
||||
im->client2 = b;
|
||||
|
||||
/* Evaluate. Two output styles: to memory area (im_setbuf()
|
||||
* or im_mmapinrw()) or to file (im_openout()).
|
||||
*/
|
||||
if( !(or = im_region_create( im )) )
|
||||
return( -1 );
|
||||
if( !(tg = im_threadgroup_create( im )) ) {
|
||||
im_region_free( or );
|
||||
return( -1 );
|
||||
}
|
||||
if( im->dtype == IM_OPENOUT )
|
||||
res = im_wbuffer( tg, write_vips, NULL, NULL );
|
||||
res = vips_sink_disc( im,
|
||||
(VipsRegionWrite) write_vips, NULL );
|
||||
/*
|
||||
else
|
||||
res = eval_to_memory( tg, or );
|
||||
|
||||
/* Clean up.
|
||||
*/
|
||||
im_threadgroup_free( tg );
|
||||
im_region_free( or );
|
||||
*/
|
||||
|
||||
/* Error?
|
||||
*/
|
||||
@ -638,58 +625,3 @@ im_generate( IMAGE *im,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_prepare_thread:
|
||||
* @tg: group of threads to evaluate with
|
||||
* @reg: region to prepare
|
||||
* @r: #Rect of pixels you need to be able to address
|
||||
*
|
||||
* im_prepare_thread() fills @reg with pixels. After calling, you can address
|
||||
* at
|
||||
* least the area @r with IM_REGION_ADDR() and get valid pixels.
|
||||
*
|
||||
* im_prepare_thread() uses @tg, a group of threads, to calculate pixels.
|
||||
* Computation blocks until the pixels are ready.
|
||||
*
|
||||
* Use im_prepare() to calculate an area of pixels in-line.
|
||||
* Use im_render_priority() to calculate an area of pixels in the background.
|
||||
*
|
||||
* See also: im_prepare(), im_render_priority(), im_prepare_to().
|
||||
*
|
||||
* Returns: 0 on success, or -1 on error
|
||||
*/
|
||||
int
|
||||
im_prepare_thread( im_threadgroup_t *tg, REGION *or, Rect *r )
|
||||
{
|
||||
IMAGE *im = or->im;
|
||||
|
||||
g_assert( !im_image_sanity( im ) );
|
||||
|
||||
switch( im->dtype ) {
|
||||
case IM_PARTIAL:
|
||||
if( im_region_fill( or, r,
|
||||
(im_region_fill_fn) eval_to_region, tg ) )
|
||||
return( -1 );
|
||||
|
||||
break;
|
||||
|
||||
case IM_OPENIN:
|
||||
case IM_SETBUF:
|
||||
case IM_SETBUF_FOREIGN:
|
||||
case IM_MMAPIN:
|
||||
case IM_MMAPINRW:
|
||||
/* Attach to existing buffer.
|
||||
*/
|
||||
if( im_region_image( or, r ) )
|
||||
return( -1 );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
im_error( "im_prepare_thread", _( "unable to input from a %s "
|
||||
"image" ), im_dtype2char( im->dtype ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
189
libvips/iofuncs/sinkmemory.c
Normal file
189
libvips/iofuncs/sinkmemory.c
Normal file
@ -0,0 +1,189 @@
|
||||
/* Write an image to a memory buffer.
|
||||
*
|
||||
* 16/4/10
|
||||
* - from vips_sink()
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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 VIPS_DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/thread.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#ifdef WITH_DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif /*WITH_DMALLOC*/
|
||||
|
||||
/* Per-call state.
|
||||
*/
|
||||
typedef struct _Sink {
|
||||
VipsImage *im;
|
||||
|
||||
/* 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 int
|
||||
sink_init( Sink *sink, VipsImage *im )
|
||||
{
|
||||
sink->im = im;
|
||||
sink->x = 0;
|
||||
sink->y = 0;
|
||||
|
||||
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;
|
||||
|
||||
Rect 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;
|
||||
im_rect_intersectrect( &image, &tile, &state->pos );
|
||||
|
||||
/* Move state on.
|
||||
*/
|
||||
sink->x += sink->tile_width;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
sink_work( VipsThreadState *state, void *a )
|
||||
{
|
||||
Sink *sink = (Sink *) a;
|
||||
|
||||
if( im_prepare_to( state->reg, &state->pos ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
sink_progress( void *a )
|
||||
{
|
||||
Sink *sink = (Sink *) a;
|
||||
|
||||
/* Trigger any eval callbacks on our source image and
|
||||
* check for errors.
|
||||
*/
|
||||
if( im__handle_eval( sink->im,
|
||||
sink->tile_width, sink->tile_height ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_sink_memory:
|
||||
* @im: generate this image to memory
|
||||
*
|
||||
* Loops over an image, generating it to a memory buffer attached to the
|
||||
* image.
|
||||
*
|
||||
* See also: vips_sink(), vips_get_tile_size().
|
||||
*
|
||||
* Returns: 0 on success, or -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_sink_memory( VipsImage *im )
|
||||
{
|
||||
Sink sink;
|
||||
int result;
|
||||
|
||||
g_assert( !im_image_sanity( im ) );
|
||||
|
||||
/* We don't use this, but make sure it's set in case any old binaries
|
||||
* are expecting it.
|
||||
*/
|
||||
im->Bbits = im_bits_of_fmt( im->BandFmt );
|
||||
|
||||
if( sink_init( &sink ) )
|
||||
return( -1 );
|
||||
|
||||
if( im__start_eval( im ) )
|
||||
return( -1 );
|
||||
|
||||
result = vips_threadpool_run( im,
|
||||
vips_thread_state_new,
|
||||
sink_allocate,
|
||||
sink_work,
|
||||
sink_progress,
|
||||
&sink );
|
||||
|
||||
im__end_eval( im );
|
||||
|
||||
return( result );
|
||||
}
|
Loading…
Reference in New Issue
Block a user