예제 #1
0
/* 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 );
}
예제 #2
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 );
}
예제 #3
0
/**
 * 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 );
}
예제 #4
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 );
}