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
/* Like im_prepare(): fill reg with data, ready to be read from by our caller.
 * Unlike im_prepare(), rather than allocating memory local to reg for the
 * result, we guarantee that we will fill the pixels in dest at offset x, y.
 * In other words, we generate an extra copy operation if necessary. 
 */
int
im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
	IMAGE *im = reg->im;
	Rect image;
	Rect wanted;
	Rect clipped;
	Rect clipped2;
	Rect final;

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

	/* Sanity check.
	 */
	if( !dest->data || dest->im->BandFmt != reg->im->BandFmt ||
		dest->im->Bands != reg->im->Bands ) {
		im_error( "im_prepare_to", _( "inappropriate region type" ) );
		return( -1 );
	}

	/* clip r first against the size of reg->im, then again against the 
	 * memory we have available to write to on dest. Just like 
	 * im_region_region()
	 */
	image.top = 0;
	image.left = 0;
	image.width = reg->im->Xsize;
	image.height = reg->im->Ysize;
	im_rect_intersectrect( r, &image, &clipped );

	assert( clipped.left == r->left );
	assert( clipped.top == r->top );

	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_prepare_to", _( "dest too small" ) );
		return( -1 );
	}

	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. 3
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. 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
/* Loop over the output region, filling with data from cache.
 */
static int
tile_cache_fill( REGION *out, void *seq, void *a, void *b )
{
	REGION *in = (REGION *) seq;
	Read *read = (Read *) b;
	const int tw = read->tile_width;
	const int th = read->tile_height;
	Rect *r = &out->valid;

	/* Find top left of tiles we need.
	 */
	int xs = (r->left / tw) * tw;
	int ys = (r->top / th) * th;

	int x, y;

	g_mutex_lock( read->lock );

	for( y = ys; y < IM_RECT_BOTTOM( r ); y += th )
		for( x = xs; x < IM_RECT_RIGHT( r ); x += tw ) {
			Tile *tile;
			Rect tarea;
			Rect hit;

			if( !(tile = tile_find( read, in, x, y )) ) {
				g_mutex_unlock( read->lock );
				return( -1 );
			}

			/* The area of the tile.
			 */
			tarea.left = x;
			tarea.top = y;
			tarea.width = tw;
			tarea.height = th;

			/* The part of the tile that we need.
			 */
			im_rect_intersectrect( &tarea, r, &hit );

			copy_region( tile->region, out, &hit );
		}

	g_mutex_unlock( read->lock );

	return( 0 );
}
Esempio n. 6
0
static int 
im_pvmerge( Rect *tarea, Rect *barea, Rect *outarea )
{       

	Rect overlap;

	
	/* Compute overlap.
	 */
	im_rect_intersectrect( tarea, barea, &overlap );

	outarea->width = overlap.width;
	outarea->height = barea->top + barea->height ;
	outarea->left = overlap.left;
	outarea->top = tarea->top;

	return( 0 );
}
Esempio n. 7
0
static int 
im_phmerge( Rect *larea, Rect *rarea, Rect *outarea )
{	

	Rect overlap;


	/* Compute overlap.
	 */
	im_rect_intersectrect( larea, rarea, &overlap );

	outarea->width = rarea->left + rarea->width;
	outarea->height = overlap.height;
	outarea->top = overlap.top;
	outarea->left = larea->left;

	return( 0 );
}
Esempio n. 8
0
/* Find max and min of visible area of image.
 */
static gboolean
conversionview_findmaxmin( Imagemodel *imagemodel, double *min, double *max )
{
	Conversion *conv = imagemodel->conv;
	Rect a, b;

	conversion_disp_to_im_rect( conv, &imagemodel->visible, &a );
	im_rect_intersectrect( &a, &conv->image, &b );
	if( findmaxmin( imageinfo_get( FALSE, conv->ii ), 
		b.left, b.top, b.width, b.height, min, max ) ) {
		error_top( _( "Unable to find image range." ) );
		error_sub( _( "Find image range failed." ) );
		error_vips();
		return( FALSE );
	}

	return( TRUE );
}
Esempio n. 9
0
static Mask *
mask_new( VipsImage *im, int x, int y, PEL *ink, VipsImage *mask_im )
{
	Mask *mask;
	Rect area, image;

	if( im_check_coding_noneorlabq( "im_draw_mask", im ) ||
		im_incheck( mask_im ) ||
		im_check_mono( "im_draw_mask", mask_im ) ||
		im_check_uncoded( "im_draw_mask", mask_im ) ||
		im_check_format( "im_draw_mask", mask_im, IM_BANDFMT_UCHAR ) ||
		!(mask = IM_NEW( NULL, Mask )) )
		return( NULL );
	if( !im__draw_init( DRAW( mask ), im, ink ) ) {
		mask_free( mask );
		return( NULL );
	}

	mask->x = x;
	mask->y = y;
	mask->mask_im = mask_im;

	/* Find the area we draw on the image.
	 */
	area.left = x;
	area.top = y;
	area.width = mask_im->Xsize;
	area.height = mask_im->Ysize;
	image.left = 0;
	image.top = 0;
	image.width = im->Xsize;
	image.height = im->Ysize;
	im_rect_intersectrect( &area, &image, &mask->image_clip );

	/* And the area of the mask image we use.
	 */
	mask->mask_clip = mask->image_clip;
	mask->mask_clip.left -= x;
	mask->mask_clip.top -= y;

	return( mask );
}
Esempio n. 10
0
/**
 * im_draw_image:
 * @image: image to draw on
 * @sub: image to draw
 * @x: position to insert
 * @y: position to insert
 *
 * Draw @sub on top of @image at position @x, @y. The two images must have the
 * same
 * Coding. If @sub has 1 band, the bands will be duplicated to match the
 * number of bands in @image. @sub will be converted to @image's format, see
 * im_clip2fmt().
 *
 * See also: im_insert().
 *
 * Returns: 0 on success, or -1 on error.
 */
int
im_draw_image( VipsImage *image, VipsImage *sub, int x, int y )
{
    Rect br, sr, clip;
    PEL *p, *q;
    int z;

    /* Make rects for main and sub and clip.
     */
    br.left = 0;
    br.top = 0;
    br.width = image->Xsize;
    br.height = image->Ysize;
    sr.left = x;
    sr.top = y;
    sr.width = sub->Xsize;
    sr.height = sub->Ysize;
    im_rect_intersectrect( &br, &sr, &clip );
    if( im_rect_isempty( &clip ) )
        return( 0 );

    if( !(sub = im__inplace_base( "im_draw_image", image, sub, image )) ||
            im_rwcheck( image ) ||
            im_incheck( sub ) )
        return( -1 );

    /* Loop, memcpying sub to main.
     */
    p = (PEL *) IM_IMAGE_ADDR( sub, clip.left - x, clip.top - y );
    q = (PEL *) IM_IMAGE_ADDR( image, clip.left, clip.top );
    for( z = 0; z < clip.height; z++ ) {
        memcpy( (char *) q, (char *) p,
                clip.width * IM_IMAGE_SIZEOF_PEL( sub ) );
        p += IM_IMAGE_SIZEOF_LINE( sub );
        q += IM_IMAGE_SIZEOF_LINE( image );
    }

    return( 0 );
}
Esempio n. 11
0
/**
 * im_draw_smudge:
 * @image: image to smudge
 * @left: area to smudge
 * @top: area to smudge
 * @width: area to smudge
 * @height: area to smudge
 *
 * Smudge a section of @image. Each pixel in the area @left, @top, @width,
 * @height is replaced by the average of the surrounding 3x3 pixels. 
 *
 * This an inplace operation, so @image is changed. It does not thread and will
 * not work well as part of a pipeline. On 32-bit machines it will be limited
 * to 2GB images.
 *
 * See also: im_draw_line().
 *
 * Returns: 0 on success, or -1 on error.
 */
int
im_draw_smudge( VipsImage *im, int left, int top, int width, int height )
{
	Rect area, image, clipped;
	IMAGE *t[2];

	area.left = left;
	area.top = top;
	area.width = width;
	area.height = height;
	image.left = 0;
	image.top = 0;
	image.width = im->Xsize;
	image.height = im->Ysize;
	im_rect_intersectrect( &area, &image, &clipped );
	if( im_rect_isempty( &clipped ) )
		return( 0 );

	if( !blur ) {
		blur = im_create_imaskv( "im_draw_smudge", 3, 1, 1, 4, 1 );
		blur->scale = 6;
	}

	if( !(t[0] = im_open( "im_draw_smudge", "p" )) )
		return( -1 );
	if( !(t[1] = im_open_local( t[0], "im_draw_smudge", "p" )) ||
		im_convsep( im, t[0], blur ) ||
		im_extract_area( t[0], t[1], 
			clipped.left, clipped.top, 
			clipped.width, clipped.height ) ||
		im_draw_image( im, t[1], clipped.left, clipped.top ) ) {
		im_close( t[0] );
		return( -1 );
	}
	im_close( t[0] );

	return( 0 );
}
Esempio n. 12
0
static int
affinei_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	const IMAGE *in = (IMAGE *) a;
	const Affine *affine = (Affine *) b;
	const int window_offset = 
		vips_interpolate_get_window_offset( affine->interpolate );
	const VipsInterpolateMethod interpolate = 
		vips_interpolate_get_method( affine->interpolate );

	/* Area we generate in the output image.
	 */
	const Rect *r = &or->valid;
	const int le = r->left;
	const int ri = IM_RECT_RIGHT( r );
	const int to = r->top;
	const int bo = IM_RECT_BOTTOM( r );

	const Rect *iarea = &affine->trn.iarea;
	const Rect *oarea = &affine->trn.oarea;

	int ps = IM_IMAGE_SIZEOF_PEL( in );
	int x, y, z;
	
	Rect image, want, need, clipped;

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

	/* We are generating this chunk of the transformed image.
	 */
	want = *r;
	want.left += oarea->left;
	want.top += oarea->top;

	/* Find the area of the input image we need.
	 */
	im__transform_invert_rect( &affine->trn, &want, &need );

	/* Now go to space (2) above.
	 */
	need.left += iarea->left;
	need.top += iarea->top;

	/* Add a border for interpolation. Plus one for rounding errors.
	 */
	im_rect_marginadjust( &need, window_offset + 1 );

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

	/* Outside input image? All black.
	 */
	if( im_rect_isempty( &clipped ) ) {
		im_region_black( or );
		return( 0 );
	}

	/* We do need some pixels from the input image to make our output -
	 * ask for them.
	 */
	if( im_prepare( ir, &clipped ) )
		return( -1 );

#ifdef DEBUG
	printf( "affine: preparing left=%d, top=%d, width=%d, height=%d\n", 
		clipped.left,
		clipped.top,
		clipped.width,
		clipped.height );
#endif /*DEBUG*/

	/* Resample! x/y loop over pixels in the output image (5).
	 */
	for( y = to; y < bo; y++ ) {
		/* Input clipping rectangle. 
		 */
		const int ile = iarea->left;
		const int ito = iarea->top;
		const int iri = iarea->left + iarea->width;
		const int ibo = iarea->top + iarea->height;

		/* Derivative of matrix.
		 */
		const double ddx = affine->trn.ia;
		const double ddy = affine->trn.ic;

		/* Continuous cods in transformed space.
		 */
		const double ox = le + oarea->left - affine->trn.dx;
		const double oy = y + oarea->top - affine->trn.dy;

		/* Continuous cods in input space.
		 */
		double ix, iy;

		PEL *q;

		/* To (3).
		 */
		ix = affine->trn.ia * ox + affine->trn.ib * oy;
		iy = affine->trn.ic * ox + affine->trn.id * oy;

		/* Now move to (2).
		 */
		ix += iarea->left;
		iy += iarea->top;

		q = (PEL *) IM_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			int fx, fy; 	

			fx = FLOOR( ix );
			fy = FLOOR( iy );

			/* Clipping! 
			 */
			if( fx < ile || fx >= iri || fy < ito || fy >= ibo ) {
				for( z = 0; z < ps; z++ ) 
					q[z] = 0;
			}
			else {
				interpolate( affine->interpolate, 
					q, ir, ix, iy );
			}

			ix += ddx;
			iy += ddy;
			q += ps;
		}
	}

	return( 0 );
}
Esempio n. 13
0
/**
 * im_draw_rect:
 * @image: image to draw on
 * @left: area to paint
 * @top: area to paint
 * @width: area to paint
 * @height: area to paint
 * @fill: fill the rect
 * @ink: paint with this colour
 *
 * Paint pixels within @left, @top, @width, @height in @image with @ink. If
 * @fill is zero, just paint a 1-pixel-wide outline.
 *
 * See also: im_draw_circle().
 *
 * Returns: 0 on success, or -1 on error.
 */
int
im_draw_rect( IMAGE *image, 
	int left, int top, int width, int height, int fill, VipsPel *ink )
{
	Rect im, rect, clipped;
	Draw draw;

	if( !fill ) 
		return( im_draw_rect( image, left, top, width, 1, 1, ink ) ||
			im_draw_rect( image, 
				left + width - 1, top, 1, height, 1, ink ) ||
			im_draw_rect( image, 
				left, top + height - 1, width, 1, 1, ink ) ||
			im_draw_rect( image, left, top, 1, height, 1, ink ) );

	int x, y;
	VipsPel *to;
	VipsPel *q;

	/* Find area we plot.
	 */
	im.left = 0;
	im.top = 0;
	im.width = image->Xsize;
	im.height = image->Ysize;
	rect.left = left;
	rect.top = top;
	rect.width = width;
	rect.height = height;
	im_rect_intersectrect( &rect, &im, &clipped );

	/* Any points left to plot?
	 */
	if( im_rect_isempty( &clipped ) )
		return( 0 );

	if( im_check_coding_known( "im_draw_rect", image ) ||
		!im__draw_init( &draw, image, ink ) )
		return( -1 );

	/* We plot the first line pointwise, then memcpy() it for the
	 * subsequent lines.
	 */
	to = IM_IMAGE_ADDR( image, clipped.left, clipped.top );

	q = to;
	for( x = 0; x < clipped.width; x++ ) {
		im__draw_pel( &draw, q );
		q += draw.psize;
	}

	q = to + draw.lsize;
	for( y = 1; y < clipped.height; y++ ) {
		memcpy( q, to, clipped.width * draw.psize );
		q += draw.lsize;
	}

	im__draw_free( &draw );

	return( 0 );
}
Esempio n. 14
0
int 
im__find_tboverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
	int bandno_in, 
	int xref, int yref, int xsec, int ysec, 
	int halfcorrelation, int halfarea,
	int *dx0, int *dy0,
	double *scale1, double *angle1, double *dx1, double *dy1 )
{
	IMAGE *ref, *sec;
	TIE_POINTS points, *p_points;		/* defined in mosaic.h */
	TIE_POINTS newpoints, *p_newpoints;
	int i;
	int dx, dy;

	Rect top, bottom, overlap;

	/* Check ref and sec are compatible.
	 */
	if( ref_in->Bands != sec_in->Bands || 
		ref_in->BandFmt != sec_in->BandFmt ||
		ref_in->Coding != sec_in->Coding ) {
		im_errormsg( "im_tbmosaic: input images incompatible" );
		return( -1 );
	}

	/* Test cor and area.
	 */
	if( halfcorrelation < 0 || halfarea < 0 || 
		halfarea < halfcorrelation ) {
		im_errormsg( "im_tbmosaic: bad area parameters" );
		return( -1 );
	}

	/* Set positions of top and bottom.
	 */
	top.left = 0;
	top.top = 0;
	top.width = ref_in->Xsize;
	top.height = ref_in->Ysize;
	bottom.left = xref - xsec;
	bottom.top = yref - ysec;
	bottom.width = sec_in->Xsize;
	bottom.height = sec_in->Ysize;

	/* Find overlap.
	 */
	im_rect_intersectrect( &top, &bottom, &overlap );
	if( overlap.width < 2*halfarea + 1 ||
		overlap.height < 2*halfarea + 1 ) {
		im_errormsg( "im_tbmosaic: overlap too small for search" );
		return( -1 );
	}

	/* Extract overlaps.
	 */
	ref = im_open_local( out, "temp_one", "t" );
	sec = im_open_local( out, "temp_two", "t" );
	if( !ref || !sec )
		return( -1 );
	if( ref_in->Coding == IM_CODING_LABQ ) {
		IMAGE *t1 = im_open_local( out, "temp:3", "p" );
		IMAGE *t2 = im_open_local( out, "temp:4", "p" );
		IMAGE *t3 = im_open_local( out, "temp:5", "p" );
		IMAGE *t4 = im_open_local( out, "temp:6", "p" );
		IMAGE *t5 = im_open_local( out, "temp:7", "p" );
		IMAGE *t6 = im_open_local( out, "temp:8", "p" );

		if( !t1 || !t2 || !t3 || !t4 || !t5 || !t6 )
			return( -1 );
		if( im_extract_area( ref_in, t1, 
			overlap.left, overlap.top, 
			overlap.width, overlap.height ) )
			return( -1 );
		if( im_extract_area( sec_in, t2, 
			overlap.left - bottom.left, overlap.top - bottom.top, 
			overlap.width, overlap.height ) )
			return( -1 );
		if( im_LabQ2Lab( t1, t3 ) || im_LabQ2Lab( t2, t4 ) ||
	    		im_Lab2disp( t3, t5, im_col_displays( 1 ) ) || 
			im_Lab2disp( t4, t6, im_col_displays( 1 ) ) )
			return( -1 );
		
		/* Extract the green.
		 */
		if( im_extract_band( t5, ref, 1 ) ||
			im_extract_band( t6, sec, 1 ) )
			return( -1 );
	}
	else if( ref_in->Coding == IM_CODING_NONE ) {
		IMAGE *t1 = im_open_local( out, "temp:9", "p" );
		IMAGE *t2 = im_open_local( out, "temp:10", "p" );
		IMAGE *t3 = im_open_local( out, "temp:11", "p" );
		IMAGE *t4 = im_open_local( out, "temp:12", "p" );

		if( !t1 || !t2 || !t3 || !t4 )
			return( -1 );
		if( im_extract_area( ref_in, t1, 
			overlap.left, overlap.top, 
			overlap.width, overlap.height ) )
			return( -1 );
		if( im_extract_area( sec_in, t2, 
			overlap.left - bottom.left, overlap.top - bottom.top, 
			overlap.width, overlap.height ) )
			return( -1 );
		if( im_extract_band( t1, t3, bandno_in ) ||
			im_extract_band( t2, t4, bandno_in ) )
			return( -1 );
		if( im_scale( t3, ref ) ||
			im_scale( t4, sec ) )
			return( -1 );
	}
	else {
		im_errormsg( "im_tbmosaic: unknown Coding type" );
		return( -1 );
	}

	/* Initialise and fill TIE_POINTS 
	 */
	p_points = &points;
	p_newpoints = &newpoints;
	p_points->reference = ref_in->filename;
	p_points->secondary = sec_in->filename;
	p_points->nopoints = IM_MAXPOINTS;
	p_points->deltax = 0;
	p_points->deltay = 0;
	p_points->halfcorsize = halfcorrelation; 	
	p_points->halfareasize = halfarea;

	/* Initialise the structure 
	 */
	for( i = 0; i < IM_MAXPOINTS; i++ ) {
		p_points->x_reference[i] = 0;
		p_points->y_reference[i] = 0;
		p_points->x_secondary[i] = 0;
		p_points->y_secondary[i] = 0;
		p_points->contrast[i] = 0;
		p_points->correlation[i] = 0.0;
		p_points->dx[i] = 0.0;
		p_points->dy[i] = 0.0;
		p_points->deviation[i] = 0.0;
	}

	/* Search ref for possible tie-points. Sets: p_points->contrast, 
	 * p_points->x,y_reference.
 	 */
	if( im__tbcalcon( ref, p_points ) )
		return( -1 ); 

	/* For each candidate point, correlate against corresponding part of
	 * sec. Sets x,y_secondary and fills correlation and dx, dy.
 	 */
	if( im__chkpair( ref, sec, p_points ) )
		return( -1 );

	/* First call to im_clinear().
	 */
  	if( im__initialize( p_points ) )
		return( -1 );

	/* Improve the selection of tiepoints until all abs(deviations) are 
	 * < 1.0 by deleting all wrong points.
 	 */
	if( im__improve( p_points, p_newpoints ) )
		return( -1 );

	/* Average remaining offsets.
	 */
	if( im__avgdxdy( p_newpoints, &dx, &dy ) )
		return( -1 );

	/* Offset with overlap position.
	 */
	*dx0 = -bottom.left + dx;
	*dy0 = -bottom.top + dy;

	/* Write 1st order parameters too.
	 */
	*scale1 = newpoints.l_scale;
	*angle1 = newpoints.l_angle;
	*dx1 = newpoints.l_deltax;
	*dy1 = newpoints.l_deltay;

	return( 0 );
}
Esempio n. 15
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. 16
0
/* Smear a section of an IMAGE. As above, but shift it left a bit.
 */
int
im_smear( IMAGE *im, int ix, int iy, Rect *r )
{	
	int x, y, a, b, c;
	int ba = im->Bands;
	int el = ba * im->Xsize;
	Rect area, image, clipped;
	double total[ 256 ];

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

	/* Don't do the margins.
	 */
	area = *r;
	area.left += ix;
	area.top += iy;
	image.left = 0;
	image.top = 0;
	image.width = im->Xsize;
	image.height = im->Ysize;
	im_rect_marginadjust( &image, -1 );
	image.left--;
	im_rect_intersectrect( &area, &image, &clipped );

	/* Any left?
	 */
	if( im_rect_isempty( &clipped ) )
		return( 0 );

/* What we do for each type.
 */
#define SMEAR(TYPE) \
	for( y = clipped.top; y < clipped.top + clipped.height; y++ ) \
		for( x = clipped.left;  \
			x < clipped.left + clipped.width; x++ ) { \
			TYPE *to = (TYPE *) im->data + x * ba + y * el; \
			TYPE *from = to - el; \
			TYPE *f; \
 			\
			for( a = 0; a < ba; a++ ) \
				total[a] = 0.0; \
			\
			for( a = 0; a < 3; a++ ) { \
				f = from; \
				for( b = 0; b < 3; b++ ) \
					for( c = 0; c < ba; c++ ) \
						total[c] += *f++; \
				from += el; \
			} \
 			\
			for( a = 0; a < ba; a++ ) \
				to[a] = (40 * (double) to[a+ba] + total[a]) \
					/ 49.0; \
		}

	/* Loop through the remaining pixels.
	 */
	switch( im->BandFmt ) {
	case IM_BANDFMT_UCHAR: 
		SMEAR(unsigned char); 
		break; 

	case IM_BANDFMT_CHAR: 
		SMEAR(char); 
		break; 

	case IM_BANDFMT_USHORT: 
		SMEAR(unsigned short); 
		break; 

	case IM_BANDFMT_SHORT: 
		SMEAR(short); 
		break; 

	case IM_BANDFMT_UINT: 
		SMEAR(unsigned int); 
		break; 

	case IM_BANDFMT_INT: 
		SMEAR(int); 
		break; 

	case IM_BANDFMT_FLOAT: 
		SMEAR(float); 
		break; 

	case IM_BANDFMT_DOUBLE: 
		SMEAR(double); 
		break; 

	/* Do complex types too. Just treat as float and double, but with
	 * twice the number of bands.
	 */
	case IM_BANDFMT_COMPLEX:
		/* Twice number of bands: double size and bands.
		 */
		ba *= 2;
		el *= 2;

		SMEAR(float);

		break;

	case IM_BANDFMT_DPCOMPLEX:
		/* Twice number of bands: double size and bands.
		 */
		ba *= 2;
		el *= 2;

		SMEAR(double);

		break;

	default:
		im_error( "im_smear", "%s", _( "unknown band format" ) );
		return( -1 );
	}

	return( 0 );
}
Esempio n. 17
0
static int
replicate_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	Rect *r = &or->valid;
	int twidth = in->Xsize;
	int theight = in->Ysize;
	int x, y;
	Rect tile;

	/* Find top left of tiles we need.
	 */
	int xs = (r->left / twidth) * twidth;
	int ys = (r->top / theight) * theight;

	/* The tile enclosing the top-left corner of the requested area.
	 */
	tile.left = xs;
	tile.top = ys;
	tile.width = twidth;
	tile.height = theight;

	/* If the request fits inside a single tile, we can just pointer-copy.
	 */
	if( im_rect_includesrect( &tile, r ) ) {
		Rect irect;

		/* Translate request to input space.
		 */
		irect = *r;
		irect.left -= xs;
		irect.top -= ys;
		if( im_prepare( ir, &irect ) )
			return( -1 );

		if( im_region_region( or, ir, r, irect.left, irect.top ) )
			return( -1 );

		return( 0 );
	}

	for( y = ys; y < IM_RECT_BOTTOM( r ); y += theight )
		for( x = xs; x < IM_RECT_RIGHT( r ); x += twidth ) {
			Rect paint;

			/* Whole tile at x, y
			 */
			tile.left = x;
			tile.top = y;
			tile.width = twidth;
			tile.height = theight;

			/* Which parts touch the area of the output we are
			 * building.
			 */
			im_rect_intersectrect( &tile, r, &paint );

			/* Translate back to ir coordinates.
			 */
			paint.left -= x;
			paint.top -= y;

			g_assert( !im_rect_isempty( &paint ) );

			/* Render into or.
			 */
			if( im_prepare_to( ir, or, &paint,
				paint.left + x,
				paint.top + y ) )
				return( -1 );
		}

	return( 0 );
}
Esempio n. 18
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 );
}
Esempio n. 19
0
/**
 * im_correl:
 * @ref: reference image
 * @sec: secondary image
 * @xref: position in reference image
 * @yref: position in reference image
 * @xsec: position in secondary image
 * @ysec: position in secondary image
 * @hwindowsize: half window size
 * @hsearchsize: half search size 
 * @correlation: return detected correlation
 * @x: return found position
 * @y: return found position
 *
 * This operation finds the position of @sec within @ref. 
 *
 * The area around
 * (@xsec, @ysec) is searched for the best match to the area around (@xref,
 * @yref). It  searches an area of size @hsearchsize for a
 * match of size @hwindowsize.  The position of the best match is
 * returned, together with the correlation at that point.
 *
 * Only  the  first  band  of each image is correlated. @ref and @sec may be
 * very large --- the function  extracts  and  generates  just  the
 * parts needed.  Correlation is done with im_spcor(); the position of
 * the maximum is found with im_maxpos().
 * 
 * See also: im_match_linear(), im_match_linear_search(), im_lrmosaic().
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_correl( IMAGE *ref, IMAGE *sec, 
	int xref, int yref, int xsec, int ysec,
	int hwindowsize, int hsearchsize,
	double *correlation, int *x, int *y )
{
	IMAGE *surface = im_open( "surface", "t" );
	IMAGE *t1, *t2, *t3, *t4;

	Rect refr, secr;
	Rect winr, srhr;
	Rect wincr, srhcr;

	if( !surface || 
		!(t1 = im_open_local( surface, "correlate:1", "p" )) ||
		!(t2 = im_open_local( surface, "correlate:1", "p" )) ||
		!(t3 = im_open_local( surface, "correlate:1", "p" )) ||
		!(t4 = im_open_local( surface, "correlate:1", "p" )) )
		return( -1 );
	
	/* Find position of window and search area, and clip against image
	 * size.
	 */
	refr.left = 0;
	refr.top = 0;
	refr.width = ref->Xsize;
	refr.height = ref->Ysize;
	winr.left = xref - hwindowsize;
	winr.top = yref - hwindowsize;
	winr.width = hwindowsize*2 + 1;
	winr.height = hwindowsize*2 + 1;
	im_rect_intersectrect( &refr, &winr, &wincr );

	secr.left = 0;
	secr.top = 0;
	secr.width = sec->Xsize;
	secr.height = sec->Ysize;
	srhr.left = xsec - hsearchsize;
	srhr.top = ysec - hsearchsize;
	srhr.width = hsearchsize*2 + 1;
	srhr.height = hsearchsize*2 + 1;
	im_rect_intersectrect( &secr, &srhr, &srhcr );

	/* Extract window and search area.
	 */
	if( im_extract_area( ref, t1, 
			wincr.left, wincr.top, wincr.width, wincr.height ) ||
		im_extract_area( sec, t2, 
			srhcr.left, srhcr.top, srhcr.width, srhcr.height ) ) {
		im_close( surface );
		return( -1 );
	}

	/* Make sure we have just one band. From im_*mosaic() we will, but
	 * from im_match_linear_search() etc. we may not.
	 */
	if( t1->Bands != 1 ) {
		if( im_extract_band( t1, t3, 0 ) ) {
			im_close( surface );
			return( -1 );
		}
		t1 = t3;
	}
	if( t2->Bands != 1 ) {
		if( im_extract_band( t2, t4, 0 ) ) {
			im_close( surface );
			return( -1 );
		}
		t2 = t4;
	}

	/* Search!
	 */
	if( im_spcor( t2, t1, surface ) ) {
		im_close( surface );
		return( -1 );
	}

	/* Find maximum of correlation surface.
	 */
	if( im_maxpos( surface, x, y, correlation ) ) {
		im_close( surface );
		return( -1 );
	}
	im_close( surface );

	/* Translate back to position within sec.
	 */
	*x += srhcr.left;
	*y += srhcr.top;

	return( 0 );
}
Esempio n. 20
0
int 
im__find_lroverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
	int bandno_in, 
	int xref, int yref, int xsec, int ysec, 
	int halfcorrelation, int halfarea,
	int *dx0, int *dy0,
	double *scale1, double *angle1, double *dx1, double *dy1 )
{
	Rect left, right, overlap;
	IMAGE *ref, *sec;
	IMAGE *t[6];
	TIE_POINTS points, *p_points;
	TIE_POINTS newpoints, *p_newpoints;
	int dx, dy;
	int i;

	/* Test cor and area.
	 */
	if( halfcorrelation < 0 || halfarea < 0 || 
		halfarea < halfcorrelation ) {
		im_error( "im_lrmosaic", "%s", _( "bad area parameters" ) );
		return( -1 );
	}

	/* Set positions of left and right.
	 */
	left.left = 0;
	left.top = 0;
	left.width = ref_in->Xsize;
	left.height = ref_in->Ysize;
	right.left = xref - xsec;
	right.top = yref - ysec;
	right.width = sec_in->Xsize;
	right.height = sec_in->Ysize;

	/* Find overlap.
	 */
	im_rect_intersectrect( &left, &right, &overlap );
	if( overlap.width < 2 * halfarea + 1 ||
		overlap.height < 2 * halfarea + 1 ) {
		im_error( "im_lrmosaic", 
			"%s", _( "overlap too small for search" ) );
		return( -1 );
	}

	/* Extract overlaps as 8-bit, 1 band.
	 */
	if( !(ref = im_open_local( out, "temp_one", "t" )) ||
		!(sec = im_open_local( out, "temp_two", "t" )) ||
		im_open_local_array( out, t, 6, "im_lrmosaic", "p" ) ||
		im_extract_area( ref_in, t[0], 
			overlap.left, overlap.top, 
			overlap.width, overlap.height ) ||
		im_extract_area( sec_in, t[1], 
			overlap.left - right.left, overlap.top - right.top, 
			overlap.width, overlap.height ) )
		return( -1 );
	if( ref_in->Coding == IM_CODING_LABQ ) {
		if( im_LabQ2Lab( t[0], t[2] ) || 
			im_LabQ2Lab( t[1], t[3] ) ||
	    		im_Lab2disp( t[2], t[4], im_col_displays( 1 ) ) || 
			im_Lab2disp( t[3], t[5], im_col_displays( 1 ) ) ||
			im_extract_band( t[4], ref, 1 ) ||
			im_extract_band( t[5], sec, 1 ) )
			return( -1 );
	}
	else if( ref_in->Coding == IM_CODING_NONE ) {
		if( im_extract_band( t[0], t[2], bandno_in ) ||
			im_extract_band( t[1], t[3], bandno_in ) ||
			im_scale( t[2], ref ) ||
			im_scale( t[3], sec ) )
			return( -1 );
	}
	else {
		im_error( "im_lrmosaic", "%s", _( "unknown Coding type" ) );
		return( -1 );
	}

	/* Initialise and fill TIE_POINTS 
	 */
	p_points = &points;
	p_newpoints = &newpoints;
	p_points->reference = ref_in->filename;
	p_points->secondary = sec_in->filename;
	p_points->nopoints = IM_MAXPOINTS;
	p_points->deltax = 0;
	p_points->deltay = 0;
	p_points->halfcorsize = halfcorrelation; 	
	p_points->halfareasize = halfarea;

	/* Initialise the structure 
	 */
	for( i = 0; i < IM_MAXPOINTS; i++ ) {
		p_points->x_reference[i] = 0;
		p_points->y_reference[i] = 0;
		p_points->x_secondary[i] = 0;
		p_points->y_secondary[i] = 0;
		p_points->contrast[i] = 0;
		p_points->correlation[i] = 0.0;
		p_points->dx[i] = 0.0;
		p_points->dy[i] = 0.0;
		p_points->deviation[i] = 0.0;
	}

	/* Search ref for possible tie-points. Sets: p_points->contrast, 
	 * p_points->x,y_reference.
 	 */
	if( im__lrcalcon( ref, p_points ) )
		return( -1 ); 

	/* For each candidate point, correlate against corresponding part of
	 * sec. Sets x,y_secondary and fills correlation and dx, dy.
 	 */
	if( im__chkpair( ref, sec, p_points ) )
		return( -1 );

	/* First call to im_clinear().
	 */
  	if( im__initialize( p_points ) )
		return( -1 );

	/* Improve the selection of tiepoints until all abs(deviations) are 
	 * < 1.0 by deleting all wrong points.
 	 */
	if( im__improve( p_points, p_newpoints ) )
		return( -1 );

	/* Average remaining offsets.
	 */
	if( im__avgdxdy( p_newpoints, &dx, &dy ) )
		return( -1 );

	/* Offset with overlap position.
	 */
	*dx0 = -right.left + dx;
	*dy0 = -right.top + dy;

	/* Write 1st order parameters too.
	 */
	*scale1 = newpoints.l_scale;
	*angle1 = newpoints.l_angle;
	*dx1 = newpoints.l_deltax;
	*dy1 = newpoints.l_deltay;

	return( 0 );
}
Esempio n. 21
0
/* Loop over a big region, filling it in many small pieces with threads.
 */
static int
eval_to_region( REGION *or, im_threadgroup_t *tg )
{
	Rect *r = &or->valid;
	Rect image;

	int x, y;

	image.left = 0;
	image.top = 0;
	image.width = or->im->Xsize;
	image.height = or->im->Ysize;

	/* Note we'll be working to fill a contigious area.
	 */
	tg->inplace = 1;

	/* Loop over or, attaching to all sub-parts in turn.
	 */
	for( y = r->top; y < IM_RECT_BOTTOM( r ); y += tg->ph )
		for( x = r->left; x < IM_RECT_RIGHT( r ); x += tg->pw ) {
			im_thread_t *thr;
			Rect pos;
			Rect clipped;

			/* thrs appear on idle when the child thread does
			 * threadgroup_idle_add and hits the 'go' semaphore.
			 */
                        thr = im_threadgroup_get( tg );

			/* Set the position we want to generate with this
			 * thread. Clip against the size of the image and the
			 * space available in or.
			 */
			pos.left = x;
			pos.top = y;
			pos.width = tg->pw;
			pos.height = tg->ph;
			im_rect_intersectrect( &pos, &image, &clipped );
			im_rect_intersectrect( &clipped, r, &clipped );

			/* Note params and start work.
			 */
			thr->oreg = or; 
			thr->pos = clipped; 
			thr->x = clipped.left;
			thr->y = clipped.top;
			im_threadgroup_trigger( thr );

			/* Check for errors.
			 */
			if( im_threadgroup_iserror( tg ) ) {
				/* Don't kill threads yet ... we may want to
				 * get some error stuff out of them.
				 */
				im_threadgroup_wait( tg );
				return( -1 );
			}
		}

	/* Wait for all threads to hit 'go' again.
	 */
	im_threadgroup_wait( tg );

	if( im_threadgroup_iserror( tg ) )
		return( -1 );

	return( 0 );
}