/* Generate a region of pixels ... with threads! Very like im_prepare(), but * threaded and does sub-division. */ 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 ); }
/** * im_region_create: * @im: image to create this region on * * Create a region. #REGION s start out empty, you need to call im_prepare() to * fill them with pixels. * * See also: im_prepare(), im_region_free(). */ REGION * im_region_create( IMAGE *im ) { REGION *reg; g_assert( !im_image_sanity( im ) ); if( !(reg = IM_NEW( NULL, REGION )) ) return( NULL ); reg->im = im; reg->valid.left = 0; reg->valid.top = 0; reg->valid.width = 0; reg->valid.height = 0; reg->type = IM_REGION_NONE; reg->data = NULL; reg->bpl = 0; reg->seq = NULL; reg->thread = NULL; reg->window = NULL; reg->buffer = NULL; reg->invalid = FALSE; im__region_take_ownership( reg ); /* We're usually inside the ss lock anyway. But be safe ... */ g_mutex_lock( im->sslock ); im->regions = g_slist_prepend( im->regions, reg ); g_mutex_unlock( im->sslock ); #ifdef DEBUG g_mutex_lock( im__global_lock ); im__regions_all = g_slist_prepend( im__regions_all, reg ); printf( "%d regions in vips\n", g_slist_length( im__regions_all ) ); g_mutex_unlock( im__global_lock ); #endif /*DEBUG*/ return( reg ); }
/** * im_generate: * @im: generate this image * @start: start sequences with this function * @generate: generate pixels with this function * @stop: stop sequences with this function * @a: user data * @b: user data * * Generates an image. The action depends on the image type. * * For images opened with "p", im_generate() just attaches the * start/generate/stop callbacks and returns. * * 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 * vips_sink_disc() used to generate the image in small chunks. As each * chunk is generated, it is written to disc. * * See also: vips_sink(), im_open(), im_prepare(), im_wrapone(). * * Returns: 0 on success, or -1 on error. */ int im_generate( IMAGE *im, im_start_fn start, im_generate_fn generate, im_stop_fn stop, void *a, void *b ) { int res; g_assert( !im_image_sanity( im ) ); if( !im->hint_set ) { im_error( "im_generate", "%s", _( "im_demand_hint() not set" ) ); return( -1 ); } if( im->Xsize <= 0 || im->Ysize <= 0 || im->Bands <= 0 ) { im_error( "im_generate", "%s", _( "bad dimensions" ) ); return( -1 ); } /* We don't use this, but make sure it's set in case any old binaries * are expectiing it. */ im->Bbits = im_bits_of_fmt( im->BandFmt ); /* Look at output type to decide our action. */ switch( im->dtype ) { case IM_PARTIAL: /* Output to partial image. Just attach functions and return. */ if( im->generate || im->start || im->stop ) { im_error( "im_generate", "%s", _( "func already attached" ) ); return( -1 ); } im->start = start; im->generate = generate; im->stop = stop; im->client1 = a; im->client2 = b; #ifdef DEBUG_IO printf( "im_generate: attaching partial callbacks\n" ); #endif /*DEBUG_IO*/ break; case IM_SETBUF: case IM_SETBUF_FOREIGN: case IM_MMAPINRW: case IM_OPENOUT: /* Eval now .. sanity check. */ if( im->generate || im->start || im->stop ) { im_error( "im_generate", "%s", _( "func already attached" ) ); return( -1 ); } /* Get output ready. */ if( im_setupout( im ) ) return( -1 ); /* Attach callbacks. */ im->start = start; im->generate = generate; im->stop = stop; im->client1 = a; im->client2 = b; if( im->dtype == IM_OPENOUT ) res = vips_sink_disc( im, (VipsRegionWrite) write_vips, NULL ); else res = vips_sink_memory( im ); /* Error? */ if( res ) return( -1 ); break; default: /* Not a known output style. */ im_error( "im_generate", _( "unable to output to a %s image" ), im_dtype2char( im->dtype ) ); return( -1 ); } /* Successful write: trigger "written". */ if( im__trigger_callbacks( im->writtenfns ) ) return( -1 ); return( 0 ); }
/* Attach a generate function to an image. */ int im_generate( IMAGE *im, im_start_fn start, im_generate_fn generate, im_stop_fn stop, void *a, void *b ) { int res; REGION *or; im_threadgroup_t *tg; g_assert( !im_image_sanity( im ) ); if( im->Xsize <= 0 || im->Ysize <= 0 || im->Bands <= 0 ) { im_error( "im_generate", _( "bad dimensions" ) ); return( -1 ); } /* Look at output type to decide our action. */ switch( im->dtype ) { case IM_PARTIAL: /* Output to partial image. Just attach functions and return. */ if( im->generate || im->start || im->stop ) { im_error( "im_generate", _( "func already attached" ) ); return( -1 ); } im->start = start; im->generate = generate; im->stop = stop; im->client1 = a; im->client2 = b; #ifdef DEBUG_IO printf( "im_generate: attaching partial callbacks\n" ); #endif /*DEBUG_IO*/ break; case IM_SETBUF: case IM_SETBUF_FOREIGN: case IM_MMAPINRW: case IM_OPENOUT: /* Eval now .. sanity check. */ if( im->generate || im->start || im->stop ) { im_error( "im_generate", _( "func already attached" ) ); return( -1 ); } /* Get output ready. */ if( im_setupout( im ) ) return( -1 ); /* Attach callbacks. */ im->start = start; im->generate = generate; im->stop = stop; 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 ); else res = eval_to_memory( tg, or ); /* Clean up. */ im_threadgroup_free( tg ); im_region_free( or ); /* Error? */ if( res ) return( -1 ); break; default: /* Not a known output style. */ im_error( "im_generate", _( "unable to output to a %s image" ), im_dtype2char( im->dtype ) ); return( -1 ); } return( 0 ); }