Esempio n. 1
0
/**
 * im_region_region:
 * @reg: region to operate upon
 * @dest: region to connect to
 * @r: #Rect of pixels you need to be able to address
 * @x: postion of @r in @dest
 * @y: postion of @r in @dest
 *
 * Make IM_REGION_ADDR() on @reg go to @dest instead.
 *
 * @r is the part of @reg which you want to be able to address (this
 * effectively becomes the valid field), (@x, @y) is the top LH corner of the
 * corresponding area in @dest.
 *
 * Performs all clipping necessary to ensure that @reg->valid is indeed
 * valid.
 *
 * If the region we attach to is modified, we can be left with dangling
 * pointers! If the region we attach to is on another image, the two images
 * must have
 * the same sizeof( pel ).
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_region( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
    Rect image;
    Rect wanted;
    Rect clipped;
    Rect clipped2;
    Rect final;

    /* Sanity check.
     */
    if( !dest->data ||
            IM_IMAGE_SIZEOF_PEL( dest->im ) !=
            IM_IMAGE_SIZEOF_PEL( reg->im ) ) {
        im_error( "im_region_region",
                  "%s", _( "inappropriate region type" ) );
        return( -1 );
    }
    im__region_check_ownership( reg );

    /* We can't test

    	g_assert( dest->thread == g_thread_self() );

     * since we can have several threads writing to the same region in
     * threadgroup.
     */

    /* Clip r against size of the image.
     */
    image.top = 0;
    image.left = 0;
    image.width = reg->im->Xsize;
    image.height = reg->im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Translate to dest's coordinate space and clip against the available
     * pixels.
     */
    wanted.left = x + (clipped.left - r->left);
    wanted.top = y + (clipped.top - r->top);
    wanted.width = clipped.width;
    wanted.height = clipped.height;

    /* Test that dest->valid is large enough.
     */
    if( !im_rect_includesrect( &dest->valid, &wanted ) ) {
        im_error( "im_region_region",
                  "%s", _( "dest too small" ) );
        return( -1 );
    }

    /* Clip against the available pixels.
     */
    im_rect_intersectrect( &wanted, &dest->valid, &clipped2 );

    /* Translate back to reg's coordinate space and set as valid.
     */
    final.left = r->left + (clipped2.left - wanted.left);
Esempio n. 2
0
/**
 * im_region_buffer:
 * @reg: region to operate upon
 * @r: #Rect of pixels you need to be able to address
 *
 * The region is transformed so that at least @r pixels are available as a
 * memory buffer.
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_buffer( REGION *reg, Rect *r )
{
    IMAGE *im = reg->im;

    Rect image;
    Rect clipped;

    im__region_check_ownership( reg );

    /* Clip against image.
     */
    image.top = 0;
    image.left = 0;
    image.width = im->Xsize;
    image.height = im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Test for empty.
     */
    if( im_rect_isempty( &clipped ) ) {
        im_error( "im_region_buffer",
                  "%s", _( "valid clipped to nothing" ) );
        return( -1 );
    }

    /* Have we been asked to drop caches? We want to throw everything
     * away.
     *
     * If not, try to reuse the current buffer.
     */
    if( reg->invalid ) {
        im_region_reset( reg );
        if( !(reg->buffer = im_buffer_new( im, &clipped )) )
            return( -1 );
    }
    else {
        /* Don't call im_region_reset() ... we combine buffer unref
         * and new buffer ref in one call to reduce malloc/free
         * cycling.
         */
        IM_FREEF( im_window_unref, reg->window );
        if( !(reg->buffer =
                    im_buffer_unref_ref( reg->buffer, im, &clipped )) )
            return( -1 );
    }

    /* Init new stuff.
     */
    reg->valid = reg->buffer->area;
    reg->bpl = IM_IMAGE_SIZEOF_PEL( im ) * reg->buffer->area.width;
    reg->type = IM_REGION_BUFFER;
    reg->data = reg->buffer->buf;

    return( 0 );
}
Esempio n. 3
0
/* Call this from the relinquishing thread. Removes the buffer (if any) from
 * this thread's buffer cache.
 */
void
im__region_no_ownership( REGION *reg )
{
    g_mutex_lock( reg->im->sslock );

    im__region_check_ownership( reg );

    reg->thread = NULL;
    if( reg->buffer )
        im_buffer_undone( reg->buffer );

    g_mutex_unlock( reg->im->sslock );
}
Esempio n. 4
0
/* Region should be a pixel buffer. On return, check
 * reg->buffer->done to see if there are pixels there already. Otherwise, you
 * need to calculate.
 */
int
im_region_buffer( REGION *reg, Rect *r )
{
	IMAGE *im = reg->im;

	Rect image;
	Rect clipped;

	im__region_check_ownership( reg );

	/* Clip against image.
	 */
	image.top = 0;
	image.left = 0;
	image.width = im->Xsize;
	image.height = im->Ysize;
	im_rect_intersectrect( r, &image, &clipped );

	/* Test for empty.
	 */
	if( im_rect_isempty( &clipped ) ) {
		im_error( "im_region_buffer", _( "valid clipped to nothing" ) );
		return( -1 );
	}

	/* Already have stuff?
	 */
	if( reg->type == IM_REGION_BUFFER &&
		im_rect_includesrect( &reg->valid, &clipped ) &&
		reg->buffer &&
		!reg->buffer->invalid ) 
		return( 0 );

	/* Don't call im_region_reset() ... we combine buffer unref and new
	 * buffer ref in one call to reduce malloc/free cycling.
	 */
	IM_FREEF( im_window_unref, reg->window );
	if( !(reg->buffer = im_buffer_unref_ref( reg->buffer, im, &clipped )) )
		return( -1 );

	/* Init new stuff.
	 */
	reg->valid = reg->buffer->area;
	reg->bpl = IM_IMAGE_SIZEOF_PEL( im ) * reg->buffer->area.width;
	reg->type = IM_REGION_BUFFER;
	reg->data = reg->buffer->buf;

	return( 0 );
}
Esempio n. 5
0
/**
 * im_region_image:
 * @reg: region to operate upon
 * @r: #Rect of pixels you need to be able to address
 *
 * The region is transformed so that at least @r pixels are available directly
 * from the image. The image needs to be a memory buffer or represent a file
 * on disc that has been mapped or can be mapped.
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_image( REGION *reg, Rect *r )
{
    Rect image;
    Rect clipped;

    /* Sanity check.
     */
    im__region_check_ownership( reg );

    /* Clip against image.
     */
    image.top = 0;
    image.left = 0;
    image.width = reg->im->Xsize;
    image.height = reg->im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Test for empty.
     */
    if( im_rect_isempty( &clipped ) ) {
        im_error( "im_region_image",
                  "%s", _( "valid clipped to nothing" ) );
        return( -1 );
    }

    if( reg->im->data ) {
        /* We have the whole image available ... easy!
         */
        im_region_reset( reg );

        /* We can't just set valid = clipped, since this may be an
         * incompletely calculated memory buffer. Just set valid to r.
         */
        reg->valid = clipped;
        reg->bpl = IM_IMAGE_SIZEOF_LINE( reg->im );
        reg->data = reg->im->data +
                    (gint64) clipped.top * IM_IMAGE_SIZEOF_LINE( reg->im ) +
                    clipped.left * IM_IMAGE_SIZEOF_PEL( reg->im );
        reg->type = IM_REGION_OTHER_IMAGE;
    }
    else if( reg->im->dtype == IM_OPENIN ) {
        /* No complete image data ... but we can use a rolling window.
         */
        if( reg->type != IM_REGION_WINDOW || !reg->window ||
                reg->window->top > clipped.top ||
                reg->window->top + reg->window->height <
                clipped.top + clipped.height ) {
            im_region_reset( reg );

            if( !(reg->window = im_window_ref( reg->im,
                                               clipped.top, clipped.height )) )
                return( -1 );

            reg->type = IM_REGION_WINDOW;
        }

        /* Note the area the window actually represents.
         */
        reg->valid.left = 0;
        reg->valid.top = reg->window->top;
        reg->valid.width = reg->im->Xsize;
        reg->valid.height = reg->window->height;
        reg->bpl = IM_IMAGE_SIZEOF_LINE( reg->im );
        reg->data = reg->window->data;
    }
    else {
        im_error( "im_region_image",
                  "%s", _( "bad image type" ) );
        return( -1 );
    }

    return( 0 );
}
Esempio n. 6
0
/* Make REGION reg ready for input of area r. For most image types, we can
 * just im_attach, for PARTIAL though we may need to generate. 
 */
int
im_prepare( REGION *reg, Rect *r )
{	
	IMAGE *im = reg->im;

	Rect save = *r;

	im__region_check_ownership( reg );

	if( im__test_kill( im ) )
		return( -1 );

	/* We use save for sanity checking valid: we test at the end that the
	 * pixels we have generated are indeed all the ones that were asked
	 * for.
	 *
	 * However, r may be clipped by the image size, so we need to clip
	 * save as well to make sure we don't fail the assert due to that.
	 */
{	
	Rect image;

	image.left = 0;
	image.top = 0;
	image.width = reg->im->Xsize;
	image.height = reg->im->Ysize;
	im_rect_intersectrect( &save, &image, &save );
}

#ifdef DEBUG
        printf( "im_prepare: left = %d, top = %d, width = %d, height = %d\n",
		r->left, r->top, r->width, r->height );
#endif /*DEBUG*/

	switch( im->dtype ) {
	case IM_PARTIAL:
		if( im_region_fill( reg, r, 
			(im_region_fill_fn) fill_region, NULL ) )
			return( -1 );

		break;

	case IM_SETBUF:
	case IM_SETBUF_FOREIGN:
	case IM_MMAPIN:
	case IM_MMAPINRW:
	case IM_OPENIN:
		/* Attach to existing buffer.
		 */
		if( im_region_image( reg, r ) )
			return( -1 );

		break;

	default:
		im_error( "im_prepare", _( "unable to input from a %s image" ),
			im_dtype2char( im->dtype ) );
		return( -1 );
	}

	/* valid should now include all the pixels that were asked for.
	 */
	assert( im_rect_includesrect( &reg->valid, &save ) );

	return( 0 );
}