Esempio n. 1
0
/* Set output area of trn so that it just holds all of our input pels.
 */
void
im__transform_set_area( Transformation *trn )
{
	double xA, xB, xC, xD;
	double yA, yB, yC, yD;	
	int xmin, xmax, ymin, ymax;

	im__transform_forward( trn, 
		trn->iarea.left, trn->iarea.top, 
		&xA, &yA );
	im__transform_forward( trn, 
		IM_RECT_RIGHT( &trn->iarea ) - 1, trn->iarea.top, 
		&xB, &yB );
	im__transform_forward( trn, 
		trn->iarea.left, IM_RECT_BOTTOM( &trn->iarea ) - 1, 
		&xC, &yC );
	im__transform_forward( trn, 
		IM_RECT_RIGHT( &trn->iarea ) - 1, 
			IM_RECT_BOTTOM( &trn->iarea ) - 1, 
		&xD, &yD );

	xmin = IM_MIN( xA, IM_MIN( xB, IM_MIN( xC, xD ) ) );
	ymin = IM_MIN( yA, IM_MIN( yB, IM_MIN( yC, yD ) ) );
	xmax = IM_MAX( xA, IM_MAX( xB, IM_MAX( xC, xD ) ) );
	ymax = IM_MAX( yA, IM_MAX( yB, IM_MAX( yC, yD ) ) );

	trn->oarea.left = xmin;
	trn->oarea.top = ymin;
	trn->oarea.width = xmax - xmin + 1;
	trn->oarea.height = ymax - ymin + 1;
}
Esempio n. 2
0
/* Transform a rect using a point transformer.
 */
static void
transform_rect( const Transformation *trn, transform_fn transform,
                const Rect *in,		/* In input space */
                Rect *out )		/* In output space */
{
    double x1, y1;		/* Map corners */
    double x2, y2;
    double x3, y3;
    double x4, y4;
    double left, right, top, bottom;

    /* Map input Rect.
     */
    transform( trn, in->left, in->top, &x1, &y1 );
    transform( trn, in->left, IM_RECT_BOTTOM( in ), &x3, &y3 );
    transform( trn, IM_RECT_RIGHT( in ), in->top, &x2, &y2 );
    transform( trn, IM_RECT_RIGHT( in ), IM_RECT_BOTTOM( in ), &x4, &y4 );

    /* Find bounding box for these four corners. Round-to-nearest to try
     * to stop rounding errors growing images.
     */
    left = IM_MIN( x1, IM_MIN( x2, IM_MIN( x3, x4 ) ) );
    right = IM_MAX( x1, IM_MAX( x2, IM_MAX( x3, x4 ) ) );
    top = IM_MIN( y1, IM_MIN( y2, IM_MIN( y3, y4 ) ) );
    bottom = IM_MAX( y1, IM_MAX( y2, IM_MAX( y3, y4 ) ) );

    out->left = IM_RINT( left );
    out->top = IM_RINT( top );
    out->width = IM_RINT( right - left );
    out->height = IM_RINT( bottom - top );
}
Esempio n. 3
0
/* Build per-call state.
 */
static Overlapping *
build_tbstate( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
   	Overlapping *ovlap;

	if( !(ovlap = im__build_mergestate( "im_tbmerge", 
		ref, sec, out, dx, dy, mwidth )) )
		return( NULL );

	/* Select blender.
	 */
	switch( ovlap->ref->Coding ) {
	case IM_CODING_LABQ:
		ovlap->blend = tb_blend_labpack;
		break;

	case IM_CODING_NONE:
		ovlap->blend = tb_blend;
		break;

	default:
		im_error( "im_tbmerge", "%s", _( "unknown coding type" ) );
		return( NULL );
	}

	/* Find the parts of output which come just from ref and just from sec.
	 */
	ovlap->rpart = ovlap->rarea;
	ovlap->spart = ovlap->sarea;
	ovlap->rpart.height -= ovlap->overlap.height;
	ovlap->spart.top += ovlap->overlap.height;
	ovlap->spart.height -= ovlap->overlap.height;

	/* Is there too much overlap? ie. bottom edge of ref image is greater
	 * than bottom edge of sec image, or top edge of ref > top edge of
	 * sec.
	 */
	if( IM_RECT_BOTTOM( &ovlap->rarea ) > IM_RECT_BOTTOM( &ovlap->sarea ) ||
		ovlap->rarea.top > ovlap->sarea.top ) {
		im_error( "im_tbmerge", "%s", _( "too much overlap" ) );
		return( NULL );
	}

	/* Max number of pixels we may have to blend together.
	 */
	ovlap->blsize = ovlap->overlap.width;

	return( ovlap );
}
Esempio n. 4
0
/* Generate function.
 */
static int
make_vert_gen( REGION *or, void *seq, void *a, void *b )
{
	IMAGE *in = (IMAGE *) a;
	Rect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int ri = IM_RECT_RIGHT( r );
	int bo = IM_RECT_BOTTOM( r );
	int nb = in->Bands;

	int x, y, z;

	for( y = to; y < bo; y++ ) {
		VipsPel *q = IM_REGION_ADDR( or, le, y );
		VipsPel *p = IM_IMAGE_ADDR( in, 0, y );

		switch( in->BandFmt ) {
		case IM_BANDFMT_UCHAR: 	VERT( unsigned char ); break;
		case IM_BANDFMT_CHAR: 	VERT( signed char ); break; 
		case IM_BANDFMT_USHORT: VERT( unsigned short ); break; 
		case IM_BANDFMT_SHORT: 	VERT( signed short ); break; 
		case IM_BANDFMT_UINT: 	VERT( unsigned int ); break; 
		case IM_BANDFMT_INT: 	VERT( signed int );  break; 
		case IM_BANDFMT_FLOAT: 	VERT( float ); break; 
		case IM_BANDFMT_DOUBLE:	VERT( double ); break; 

		default:
			g_assert( 0 ); 
		}
	}

	return( 0 );
}
Esempio n. 5
0
/* Scroll to make an xywh area visible. If the area is larger than the
 * viewport, position the view at the bottom left if the xywh area ... 
 * this is usually right for workspaces.
 */
void
workspaceview_scroll( Workspaceview *wview, int x, int y, int w, int h )
{
	GtkAdjustment *hadj = gtk_scrolled_window_get_hadjustment( 
		GTK_SCROLLED_WINDOW( wview->window ) );
	GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment( 
		GTK_SCROLLED_WINDOW( wview->window ) );
        Rect *vp = &wview->vp;
        int nx, ny;

        nx = hadj->value;
        if( x + w > IM_RECT_RIGHT( vp ) )
                nx = IM_MAX( 0, (x + w) - vp->width );
        if( x < nx )
                nx = x;

        ny = vadj->value;
        if( y + h > IM_RECT_BOTTOM( vp ) )
                ny = IM_MAX( 0, (y + h) - vp->height );
        if( y < ny )
                ny = y;

#ifdef DEBUG
        printf( "workspaceview_scroll: x=%d, y=%d, w=%d, h=%d, "
                "nx = %d, ny = %d\n", x, y, w, h, nx, ny );
#endif /*DEBUG*/

	adjustments_set_value( hadj, vadj, nx, ny );
}
Esempio n. 6
0
/* Rotate a small piece.
 */
static int
rot270_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;

	/* Output area.
	 */
	Rect *r = &or->valid;
	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int x, y, i;

	/* Pixel geometry.
	 */
	int ps, ls;

	/* Find the area of the input image we need.
	 */
	Rect need;

	need.left = in->Xsize - bo;
	need.top = le;
	need.width = r->height;
	need.height = r->width;
	if( im_prepare( ir, &need ) )
		return( -1 );
	
	/* Find PEL size and line skip for ir.
	 */
	ps = IM_IMAGE_SIZEOF_PEL( in );
	ls = IM_REGION_LSKIP( ir );

	/* Rotate the bit we now have.
	 */
	for( y = to; y < bo; y++ ) {
		/* Start of this output line.
		 */
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		/* Corresponding position in ir.
		 */
		PEL *p = (PEL *) IM_REGION_ADDR( ir, 
			need.left + need.width - (y - to) - 1,
			need.top );

		for( x = le; x < ri; x++ ) {
			for( i = 0; i < ps; i++ )
				q[i] = p[i];

			q += ps;
			p += ls;
		}
	}

	return( 0 );
}
Esempio n. 7
0
static int
vips_rot180_gen( VipsRegion *or, void *seq, void *a, void *b,
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsImage *in = (VipsImage *) a;

	/* Output area.
	 */
	VipsRect *r = &or->valid;
	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int x, y;

	/* Pixel geometry.
	 */
	int ps;

	/* Find the area of the input image we need.
	 */
	Rect need;

	need.left = in->Xsize - ri;
	need.top = in->Ysize - bo;
	need.width = r->width;
	need.height = r->height;
	if( vips_region_prepare( ir, &need ) )
		return( -1 );

	/* Find PEL size and line skip for ir.
	 */
	ps = VIPS_IMAGE_SIZEOF_PEL( in );

	/* Rotate the bit we now have.
	 */
	for( y = to; y < bo; y++ ) {
		/* Start of this output line.
		 */
		VipsPel *q = VIPS_REGION_ADDR( or, le, y );

		/* Corresponding position in ir.
		 */
		VipsPel *p = VIPS_REGION_ADDR( ir, 
			need.left + need.width - 1, 
			need.top + need.height - (y - to) - 1 );

		/* Blap across!
		 */
		for( x = le; x < ri; x++ ) {
			memcpy( q, p, ps );
			q += ps;
			p -= ps;
		}
	}

	return( 0 );
}
Esempio n. 8
0
/* Fastcor generate function.
 */
static int
fastcor_gen( REGION *or, void *seq, void *a, void *b )
{
    REGION *ir = (REGION *) seq;
    IMAGE *ref = (IMAGE *) b;
    Rect irect;
    Rect *r = &or->valid;
    int le = r->left;
    int to = r->top;
    int bo = IM_RECT_BOTTOM(r);
    int ri = IM_RECT_RIGHT(r);

    int x, y, i, j;
    int lsk;

    /* What part of ir do we need?
     */
    irect.left = or->valid.left;
    irect.top = or->valid.top;
    irect.width = or->valid.width + ref->Xsize - 1;
    irect.height = or->valid.height + ref->Ysize - 1;

    if( im_prepare( ir, &irect ) )
        return( -1 );
    lsk = IM_REGION_LSKIP( ir );

    /* Loop over or.
     */
    for( y = to; y < bo; y++ ) {
        PEL *a = (PEL *) IM_REGION_ADDR( ir, le, y );
        unsigned int *q = (unsigned int *) IM_REGION_ADDR( or, le, y );

        for( x = le; x < ri; x++ ) {
            int sum = 0;
            PEL *b = (PEL *) ref->data;
            PEL *a1 = a;

            for( j = 0; j < ref->Ysize; j++ ) {
                PEL *a2 = a1;

                for( i = 0; i < ref->Xsize; i++ ) {
                    int t = *b++ - *a2++;

                    sum += t * t;
                }

                a1 += lsk;
            }

            *q++ = sum;
            a += 1;
        }
    }

    return( 0 );
}
Esempio n. 9
0
/* Flip a small area.
 */
static int
flip_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	Rect *r = &or->valid;
	Rect in;
	char *p, *q;
	int x, y, z;

	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_IMAGE_SIZEOF_PEL( ir->im );	/* sizeof pel */

	int hgt = ir->im->Xsize - r->width;

	int lastx;

	/* Transform to input coordinates.
	 */
	in = *r;
	in.left = hgt - r->left;

	/* Find x of final pixel in input area.
	 */
	lastx = IM_RECT_RIGHT( &in ) - 1;

	/* Ask for input we need.
	 */
	if( im_prepare( ir, &in ) )
		return( -1 );

	/* Loop, copying and reversing lines.
	 */
	for( y = to; y < bo; y++ ) {
		p = IM_REGION_ADDR( ir, lastx, y );
		q = IM_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			/* Copy the pel.
			 */
			for( z = 0; z < ps; z++ )
				q[z] = p[z];

			/* Skip forwards in out, back in in.
			 */
			q += ps;
			p -= ps;
		}
	}

	return( 0 );
}
Esempio n. 10
0
static void
workspaceview_child_size_cb( Columnview *cview, 
	GtkAllocation *allocation, Workspaceview *wview )
{
	Workspace *ws = WORKSPACE( VOBJECT( wview )->iobject );
	Workspacegroup *wsg = workspace_get_workspacegroup( ws );

	int right, bottom;

	g_assert( IS_WORKSPACEVIEW( wview ) );

	/* Compute a new bounding box for our children.
	 */
	wview->bounding.left = 0;
	wview->bounding.top = 0;
	wview->bounding.width = 0;
	wview->bounding.height = 0;

	(void) view_map( VIEW( wview ),
		(view_map_fn) workspaceview_child_size_sub, 
		&wview->bounding, NULL );

	wview->bounding.width += 1000;
	wview->bounding.height += 1000;

#ifdef DEBUG
{
	Column *col = COLUMN( VOBJECT( cview )->iobject );

	printf( "workspaceview_child_size_cb: cview %s "
		"bb left=%d, top=%d, width=%d, height=%d\n",
		IOBJECT( col )->name, 
		wview->bounding.left,
		wview->bounding.top,
		wview->bounding.width,
		wview->bounding.height );
}
#endif /*DEBUG*/

	/* Resize our fixed if necessary.
	 */
	right = IM_RECT_RIGHT( &wview->bounding );
	bottom = IM_RECT_BOTTOM( &wview->bounding );
	if( right != wview->width || bottom != wview->height ) {
		gtk_widget_set_size_request( GTK_WIDGET( wview->fixed ), 
			right, bottom ); 

		/* Update the model hints ... it uses bounding to position
		 * loads and saves.
		 */
		ws->area = wview->bounding;
		filemodel_set_offset( FILEMODEL( wsg ), 
			ws->area.left, ws->area.top );
	}
}
Esempio n. 11
0
/* Generate function.
 */
static int
make_horz_gen( REGION *or, void *seq, void *a, void *b )
{
    IMAGE *in = (IMAGE *) a;
    Rect *r = &or->valid;
    int le = r->left;
    int to = r->top;
    int ri = IM_RECT_RIGHT( r );
    int bo = IM_RECT_BOTTOM( r );
    int nb = in->Bands;
    int lsk = IM_REGION_LSKIP( or );
    int ht = or->im->Ysize;

    int x, y, z;

    for( x = le; x < ri; x++ ) {
        VipsPel *q = IM_REGION_ADDR( or, x, to );
        VipsPel *p = IM_IMAGE_ADDR( in, x, 0 );

        switch( in->BandFmt ) {
        case IM_BANDFMT_UCHAR:
            HORZ( unsigned char );
            break;
        case IM_BANDFMT_CHAR:
            HORZ( signed char );
            break;
        case IM_BANDFMT_USHORT:
            HORZ( unsigned short );
            break;
        case IM_BANDFMT_SHORT:
            HORZ( signed short );
            break;
        case IM_BANDFMT_UINT:
            HORZ( unsigned int );
            break;
        case IM_BANDFMT_INT:
            HORZ( signed int );
            break;
        case IM_BANDFMT_FLOAT:
            HORZ( float );
            break;
        case IM_BANDFMT_DOUBLE:
            HORZ( double );
            break;

        default:
            g_assert( 0 );
        }
    }

    return( 0 );
}
Esempio n. 12
0
/* Fetch one pixel at a time ... good for very large shrinks.
 */
static int
point_shrink_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	SubsampleInfo *st = (SubsampleInfo *) b;
	Rect *r = &or->valid;

	int le = r->left;
	int ri = IM_RECT_RIGHT( r );
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_IMAGE_SIZEOF_PEL( in );

	Rect s;
	int x, y;
	int k;

	/* Loop down the region.
	 */
	for( y = to; y < bo; y++ ) {
		char *q = IM_REGION_ADDR( or, le, y );
		char *p;

		/* Loop across the region, in owidth sized pieces.
		 */
		for( x = le; x < ri; x++ ) {
			/* Ask for input.
			 */
			s.left = x * st->xshrink;
			s.top = y * st->yshrink;
			s.width = 1;
			s.height = 1;
			if( im_prepare( ir, &s ) )
				return( -1 );

			/* Append new pels to output.
			 */
			p = IM_REGION_ADDR( ir, s.left, s.top );
			for( k = 0; k < ps; k++ )
				q[k] = p[k];
			q += ps;
		}
	}

	return( 0 );
}
Esempio n. 13
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. 14
0
/* Zerox generate function.
 */
static int
zerox_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	int flag = GPOINTER_TO_INT( b );
	Rect irect;
	Rect *r = &or->valid;

	/* Range of pixels we loop over. 
	 */
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM( r );
	int ba = in->Bands;
	int ne = ba * r->width;

	int i, y;

	/* We need to be able to see one pixel to the right. 
	 */
	irect.top = r->top;
	irect.left = r->left;
	irect.width = r->width + 1;
	irect.height = r->height;
	if( im_prepare( ir, &irect ) )
		return( -1 );
	
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		switch( in->BandFmt ) {
		case IM_BANDFMT_CHAR:           LOOP( signed char ); break;
		case IM_BANDFMT_SHORT:          LOOP( signed short ); break;
		case IM_BANDFMT_INT:            LOOP( signed int ); break;
		case IM_BANDFMT_FLOAT:          LOOP( float ); break;
		case IM_BANDFMT_DOUBLE:         LOOP( double ); break;

		default:
			g_assert( 0 );
		}
	}

	return( 0 );
} 
Esempio n. 15
0
/* Copy rect from from to to.
 */
static void
copy_region( REGION *from, REGION *to, Rect *area )
{
	int y;

	/* Area should be inside both from and to.
	 */
	g_assert( im_rect_includesrect( &from->valid, area ) );
	g_assert( im_rect_includesrect( &to->valid, area ) );

	/* Loop down common area, copying.
	 */
	for( y = area->top; y < IM_RECT_BOTTOM( area ); y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( from, area->left, y );
		PEL *q = (PEL *) IM_REGION_ADDR( to, area->left, y );

		memcpy( q, p, IM_IMAGE_SIZEOF_PEL( from->im ) * area->width );
	}
}
Esempio n. 16
0
/* Bandjoin generate function.
 */
static int
bandjoin_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION **ir = (REGION **) seq;
	Rect *r = &or->valid;
	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int x, y, z;
	int i1s = IM_IMAGE_SIZEOF_PEL( ir[0]->im );
	int i2s = IM_IMAGE_SIZEOF_PEL( ir[1]->im );

	/* Ask for input we need.
	 */
	if( im_prepare( ir[0], r ) )
		return( -1 );
	if( im_prepare( ir[1], r ) ) 
		return( -1 );

	/* Perform join.
	 */
	for( y = to; y < bo; y++ ) {
		PEL *i1 = (PEL *) IM_REGION_ADDR( ir[0], le, y );
		PEL *i2 = (PEL *) IM_REGION_ADDR( ir[1], le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			/* Copy bytes from first file.  
			 */
			for( z = 0; z < i1s; z++ )
				*q++ = *i1++;

			/* Copy bytes from in2.  
			 */
			for( z = 0; z < i2s; z++ )
				*q++ = *i2++;
		}
	}

	return( 0 );
}
Esempio n. 17
0
static int
find_hist( REGION *reg, void *seq, void *a, void *b )
{
	Histogram *hist = (Histogram *) seq;
	Rect *r = &reg->valid;
	IMAGE *im = reg->im;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int nb = im->Bands;
	int max_val = im->BandFmt == IM_BANDFMT_UCHAR ? 256 : 65536;
	int scale = max_val / hist->bins;
	int x, y, z, i;
	int index[3];

	/* Fill these with dimensions, backwards.
	 */
	index[0] = index[1] = index[2] = 0;

	/* Accumulate!
	 */
	for( y = to; y < bo; y++ ) {
		char *line = IM_REGION_ADDR( reg, le, y );

		switch( im->BandFmt ) {
		case IM_BANDFMT_UCHAR:
			LOOP( unsigned char );
			break;

		case IM_BANDFMT_USHORT:
			LOOP( unsigned char );
			break;

		default:
			error_exit( "panic #34847563245" );
		}
	}

	return( 0 );
}
Esempio n. 18
0
/* Do a map.
 */
static int 
maplut_gen( REGION *or, void *vseq, void *a, void *b )
{
	Seq *seq = (Seq *) vseq;
	IMAGE *in = (IMAGE *) a;
	LutInfo *st = (LutInfo *) b;
	REGION *ir = seq->ir;
	Rect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int np = r->width;			/* Pels across region */
	int ne = IM_REGION_N_ELEMENTS( or );	/* Number of elements */
	int x, y, z, i;

	/* Get input ready.
	 */
	if( im_prepare( ir, r ) )
		return( -1 );

	/* Process!
	 */
	if( st->nb == 1 )
		/* One band lut.
		 */
		outer_switch( loop1, loop1c, loop1g, loop1cg ) 
	else 
		/* Many band lut.
		 */
		if( ir->im->Bands == 1 )
			/* ... but 1 band input.
			 */
			outer_switch( loop1m, loop1cm, loop1gm, loop1cgm ) 
		else
			outer_switch( loop, loopc, loopg, loopcg )

	return( 0 );
}
Esempio n. 19
0
/* Generate function.
 */
static int
make_xy_gen( REGION *or, void *seq, void *a, void *b )
{
	Rect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int ri = IM_RECT_RIGHT( r );
	int bo = IM_RECT_BOTTOM( r );

	int x, y;

	for( y = to; y < bo; y++ ) {
		unsigned int *q = (unsigned int *) IM_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			q[0] = x;
			q[1] = y;
			q += 2;
		}
	}

	return( 0 );
}
Esempio n. 20
0
/* Make sure we have first/last for this area.
 */
static int
make_firstlast( MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	Rect rr, sr;
	int y, yr, ys;
	int missing;

	/* We're going to build first/last ... lock it from other generate
	 * threads. In fact it's harmless if we do get two writers, but we may
	 * avoid duplicating work.
	 */
	g_mutex_lock( ovlap->fl_lock );

	/* Do we already have first/last for this area? Bail out if we do.
	 */
	missing = 0;
	for( y = oreg->top; y < IM_RECT_BOTTOM( oreg ); y++ ) {
		const int j = y - ovlap->overlap.top;
		const int first = ovlap->first[j];

		if( first < 0 ) {
			missing = 1;
			break;
		}
	}
	if( !missing ) {
		/* No work to do!
		 */
		g_mutex_unlock( ovlap->fl_lock );
		return( 0 );
	}

	/* Entire width of overlap in ref for scan-lines we want.
	 */
	rr.left = ovlap->overlap.left;
	rr.top = oreg->top;
	rr.width = ovlap->overlap.width;
	rr.height = oreg->height;
	rr.left -= ovlap->rarea.left;
	rr.top -= ovlap->rarea.top;

	/* Entire width of overlap in sec for scan-lines we want.
	 */
	sr.left = ovlap->overlap.left;
	sr.top = oreg->top;
	sr.width = ovlap->overlap.width;
	sr.height = oreg->height;
	sr.left -= ovlap->sarea.left;
	sr.top -= ovlap->sarea.top;

#ifdef DEBUG
	printf( "im__lrmerge: making first/last for areas:\n" );
	printf( "ref: left = %d, top = %d, width = %d, height = %d\n",
		rr.left, rr.top, rr.width, rr.height );
	printf( "sec: left = %d, top = %d, width = %d, height = %d\n",
		sr.left, sr.top, sr.width, sr.height );
#endif

	/* Make pixels.
	 */
	if( im_prepare( rir, &rr ) || im_prepare( sir, &sr ) ) {
		g_mutex_unlock( ovlap->fl_lock );
		return( -1 );
	}

	/* Make first/last cache.
	 */
	for( y = oreg->top, yr = rr.top, ys = sr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) {
		const int j = y - ovlap->overlap.top;
		int *first = &ovlap->first[j];
		int *last = &ovlap->last[j];

		/* Done this line already?
		 */
		if( *first < 0 ) {
			/* Search for start/end of overlap on this scan-line.
			 */
			if( find_first( sir, first, 
				sr.left, ys, sr.width ) ||
				find_last( rir, last, 
					rr.left, yr, rr.width ) ) {
				g_mutex_unlock( ovlap->fl_lock );
				return( -1 );
			}

			/* Translate to output space.
			 */
			*first += ovlap->sarea.left;
			*last += ovlap->rarea.left;

			/* Clip to maximum blend width, if necessary.
			 */
			if( ovlap->mwidth >= 0 && 
				*last - *first > ovlap->mwidth ) {
				int shrinkby = (*last - *first) - ovlap->mwidth;

				*first += shrinkby / 2;
				*last -= shrinkby / 2;
			}
		}
	}

	g_mutex_unlock( ovlap->fl_lock );

	return( 0 );
}
Esempio n. 21
0
/* Dilate!
 */
static int
dilate_gen( REGION *or, void *vseq, void *a, void *b )
{
	SeqInfo *seq = (SeqInfo *) vseq;
	INTMASK *msk = (INTMASK *) b;
	REGION *ir = seq->ir;

	int *soff = seq->soff;
	int *coff = seq->coff;

	Rect *r = &or->valid;
	Rect s;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int sz = IM_REGION_N_ELEMENTS( or );

	int *t;

	int x, y;
	int result, i;

	/* Prepare the section of the input image we need. A little larger
	 * than the section of the output image we are producing.
	 */
	s = *r;
	s.width += msk->xsize - 1;
	s.height += msk->ysize - 1;
	if( im_prepare( ir, &s ) )
		return( -1 );

#ifdef DEBUG
	printf( "erode_gen: preparing %dx%d pixels\n", s.width, s.height );
#endif /*DEBUG*/

	/* Scan mask, building offsets we check when processing. Only do this
	 * if the bpl has changed since the previous im_prepare().
	 */
	if( seq->last_bpl != IM_REGION_LSKIP( ir ) ) {
		seq->last_bpl = IM_REGION_LSKIP( ir );

		seq->ss = 0;
		seq->cs = 0;
		for( t = msk->coeff, y = 0; y < msk->ysize; y++ )
			for( x = 0; x < msk->xsize; x++, t++ )
				switch( *t ) {
				case 255:
					soff[seq->ss++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				case 128:
					break;

				case 0:
					coff[seq->cs++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				default:
					im_error( "im_dilate", 
						_( "bad mask element (%d "
						"should be 0, 128 or 255)" ), 
						*t );
					return( -1 ); 
				}
	}

	/* Dilate!
	 */
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		/* Loop along line.
		 */
		for( x = 0; x < sz; x++, q++, p++ ) {
			/* Search for a hit on the set list.
			 */
			result = 0;
			for( i = 0; i < seq->ss; i++ )
				if( p[soff[i]] ) {
					/* Found a match! 
					 */
					result = 255;
					break;
				}

			/* No set pixels ... search for a hit in the clear
			 * pixels.
			 */
			if( !result )
				for( i = 0; i < seq->cs; i++ )
					if( !p[coff[i]] ) {
						/* Found a match! 
						 */
						result = 255;
						break;
					}

			*q = result;

		}
	}

	return( 0 );
}
Esempio n. 22
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 );
}
Esempio n. 23
0
/* Erode!
 */
static int
erode_gen( REGION *or, void *vseq, void *a, void *b )
{
	MorphSequence *seq = (MorphSequence *) vseq;
	Morph *morph = (Morph *) b;
	INTMASK *mask = morph->mask;
	REGION *ir = seq->ir;

	int *soff = seq->soff;
	int *coff = seq->coff;

	Rect *r = &or->valid;
	Rect s;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int sz = IM_REGION_N_ELEMENTS( or );

	int *t;

	int x, y;
	int result, i;

	/* Prepare the section of the input image we need. A little larger
	 * than the section of the output image we are producing.
	 */
	s = *r;
	s.width += mask->xsize - 1;
	s.height += mask->ysize - 1;
	if( im_prepare( ir, &s ) )
		return( -1 );

#ifdef DEBUG
	printf( "erode_gen: preparing %dx%d@%dx%d pixels\n", 
		s.width, s.height, s.left, s.top );
#endif /*DEBUG*/

	/* Scan mask, building offsets we check when processing. Only do this
	 * if the bpl has changed since the previous im_prepare().
	 */
	if( seq->last_bpl != IM_REGION_LSKIP( ir ) ) {
		seq->last_bpl = IM_REGION_LSKIP( ir );

		seq->ss = 0;
		seq->cs = 0;
		for( t = mask->coeff, y = 0; y < mask->ysize; y++ )
			for( x = 0; x < mask->xsize; x++, t++ )
				switch( *t ) {
				case 255:
					soff[seq->ss++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				case 128:
					break;

				case 0:
					coff[seq->cs++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				default:
					g_assert( 0 );
				}
	}

	/* Erode!
	 */
	for( y = to; y < bo; y++ ) {
		VipsPel *p = IM_REGION_ADDR( ir, le, y );
		VipsPel *q = IM_REGION_ADDR( or, le, y );

		/* Loop along line.
		 */
		for( x = 0; x < sz; x++, q++, p++ ) {
			/* Check all set pixels are set.
			 */
			result = 255;
			for( i = 0; i < seq->ss; i++ )
				if( !p[soff[i]] ) {
					/* Found a mismatch! 
					 */
					result = 0;
					break;
				}

			/* Check all clear pixels are clear.
			 */
			if( result )
				for( i = 0; i < seq->cs; i++ )
					if( p[coff[i]] ) {
						result = 0;
						break;
					}

			*q = result;
		}
	}
	
	return( 0 );
}
Esempio n. 24
0
/* Loop over region, adding information to the appropriate fields of tmp.
 */
static int
scan_fn( REGION *reg, void *seq, void *a, void *b )
{	
	double *tmp = (double *) seq;
	Rect *r = &reg->valid;
	IMAGE *im = reg->im;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int sz = IM_REGION_N_ELEMENTS( reg );
	double s = 0.0;
	double s2 = 0.0;
	int x, y;

/* Sum pels in this section.
 */
#define loop(TYPE) \
	{	TYPE *p; \
 		\
		for( y = to; y < bo; y++ ) { \
			p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
			\
			for( x = 0; x < sz; x++ ) { \
				TYPE v = p[x]; \
				\
				s += v; \
				s2 += (double) v * (double) v; \
			}\
		}\
	}

	/* Now generate code for all types. 
	 */
	switch( im->BandFmt ) {
	case IM_BANDFMT_UCHAR:		loop(unsigned char); break; 
	case IM_BANDFMT_CHAR:		loop(signed char); break; 
	case IM_BANDFMT_USHORT:		loop(unsigned short); break; 
	case IM_BANDFMT_SHORT:		loop(signed short); break; 
	case IM_BANDFMT_UINT:		loop(unsigned int); break; 
	case IM_BANDFMT_INT:		loop(signed int); break; 
	case IM_BANDFMT_FLOAT:		loop(float); break; 

	case IM_BANDFMT_DOUBLE:	
#ifdef HAVE_LIBOIL
		for( y = to; y < bo; y++ ) { 
			double *p = (double *) IM_REGION_ADDR( reg, le, y ); 
			double t;
			double t2;

			oil_sum_f64( &t, p, sizeof( double ), sz );
			oil_squaresum_f64( &t2, p, sz );

			s += t;
			s2 += t2;
		}
#else /*!HAVE_LIBOIL*/
		loop(double); 
#endif /*HAVE_LIBOIL*/
		break; 

	default: 
		assert( 0 );
	}

	/* Add to sum for this sequence.
	 */
	tmp[0] += s;
	tmp[1] += s2;

	return( 0 );
}
Esempio n. 25
0
/* Shrink a REGION.
 */
static int
shrink_gen( REGION *or, void *vseq, void *a, void *b )
{
    SeqInfo *seq = (SeqInfo *) vseq;
    ShrinkInfo *st = (ShrinkInfo *) b;
    REGION *ir = seq->ir;
    Rect *r = &or->valid;
    Rect s;
    int le = r->left;
    int ri = IM_RECT_RIGHT( r );
    int to = r->top;
    int bo = IM_RECT_BOTTOM(r);

    int x, y, z, k;

    /* What part of the input image do we need? Very careful: round left
     * down, round right up.
     */
    s.left = r->left * st->xshrink;
    s.top = r->top * st->yshrink;
    s.width = ceil( IM_RECT_RIGHT( r ) * st->xshrink ) - s.left;
    s.height = ceil( IM_RECT_BOTTOM( r ) * st->yshrink ) - s.top;
    if( im_prepare( ir, &s ) )
        return( -1 );

    /* Init offsets for pel addressing. Note that offsets must be for the
     * type we will address the memory array with.
     */
    for( z = 0, y = 0; y < st->mh; y++ )
        for( x = 0; x < st->mw; x++ )
            seq->off[z++] = (IM_REGION_ADDR( ir, x, y ) -
                             IM_REGION_ADDR( ir, 0, 0 )) /
                            IM_IMAGE_SIZEOF_ELEMENT( ir->im );

    switch( ir->im->BandFmt ) {
    case IM_BANDFMT_UCHAR:
        ishrink(unsigned char);
        break;
    case IM_BANDFMT_CHAR:
        ishrink(char);
        break;
    case IM_BANDFMT_USHORT:
        ishrink(unsigned short);
        break;
    case IM_BANDFMT_SHORT:
        ishrink(short);
        break;
    case IM_BANDFMT_UINT:
        ishrink(unsigned int);
        break;
    case IM_BANDFMT_INT:
        ishrink(int);
        break;
    case IM_BANDFMT_FLOAT:
        fshrink(float);
        break;
    case IM_BANDFMT_DOUBLE:
        fshrink(double);
        break;

    default:
        im_error( "im_shrink", "%s", _( "unsupported input format" ) );
        return( -1 );
    }

    return( 0 );
}
Esempio n. 26
0
/* Subsample a REGION. We fetch in IM_MAX_WIDTH pixel-wide strips, left-to-right
 * across the input.
 */
static int
line_shrink_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	SubsampleInfo *st = (SubsampleInfo *) b;
	Rect *r = &or->valid;

	int le = r->left;
	int ri = IM_RECT_RIGHT( r );
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_IMAGE_SIZEOF_PEL( in );

	int owidth = IM_MAX_WIDTH / st->xshrink;

	Rect s;
	int x, y;
	int z, k;

	/* Loop down the region.
	 */
	for( y = to; y < bo; y++ ) {
		char *q = IM_REGION_ADDR( or, le, y );
		char *p;

		/* Loop across the region, in owidth sized pieces.
		 */
		for( x = le; x < ri; x += owidth ) {
			/* How many pixels do we make this time?
			 */
			int ow = IM_MIN( owidth, ri - x );

			/* Ask for this many from input ... can save a 
			 * little here!
			 */
			int iw = ow * st->xshrink - (st->xshrink - 1);

			/* Ask for input.
			 */
			s.left = x * st->xshrink;
			s.top = y * st->yshrink;
			s.width = iw;
			s.height = 1;
			if( im_prepare( ir, &s ) )
				return( -1 );

			/* Append new pels to output.
			 */
			p = IM_REGION_ADDR( ir, s.left, s.top );
			for( z = 0; z < ow; z++ ) {
				for( k = 0; k < ps; k++ )
					q[k] = p[k];

				q += ps;
				p += ps * st->xshrink;
			}
		}
	}

	return( 0 );
}
Esempio n. 27
0
/* Top-bottom blend function for IM_CODING_LABQ images.
 */
static int
tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	Rect prr, psr;
	int y, yr, ys;

	/* Make sure we have a complete first/last set for this area. This
	 * will just look at the top 8 bits of L, not all 10, but should be OK.
	 */
	if( make_firstlast( inf, ovlap, oreg ) )
		return( -1 );

	/* Part of rr which we will output.
	 */
	prr = *oreg;
	prr.left -= ovlap->rarea.left;
	prr.top -= ovlap->rarea.top;

	/* Part of sr which we will output.
	 */
	psr = *oreg;
	psr.left -= ovlap->sarea.left;
	psr.top -= ovlap->sarea.top;

	/* Make pixels.
	 */
	if( im_prepare( rir, &prr ) )
		return( -1 );
	if( im_prepare( sir, &psr ) )
		return( -1 );

	/* Loop down overlap area.
	 */
	for( y = oreg->top, yr = prr.top, ys = psr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) { 
		VipsPel *pr = IM_REGION_ADDR( rir, prr.left, yr );
		VipsPel *ps = IM_REGION_ADDR( sir, psr.left, ys );
		VipsPel *q = IM_REGION_ADDR( or, oreg->left, y );

		const int j = oreg->left - ovlap->overlap.left;
		const int *first = ovlap->first + j;
		const int *last = ovlap->last + j;

		float *fq = inf->merge;
		float *r = inf->from1;
		float *s = inf->from2;

		/* Unpack two bits we want.
		 */
		vips__LabQ2Lab_vec( r, pr, oreg->width );
		vips__LabQ2Lab_vec( s, ps, oreg->width );

		/* Blend as floats.
		 */
		fblend( float, 3, r, s, fq ); 

		/* Re-pack to output buffer.
		 */
		vips__Lab2LabQ_vec( q, inf->merge, oreg->width );
	}

	return( 0 );
}
Esempio n. 28
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. 29
0
static int 
affinei( IMAGE *in, IMAGE *out, 
	VipsInterpolate *interpolate, Transformation *trn )
{
	Affine *affine;
	double edge;

	/* Make output image.
	 */
	if( im_piocheck( in, out ) ) 
		return( -1 );
	if( im_cp_desc( out, in ) ) 
		return( -1 );

	/* Need a copy of the params for the lifetime of out.
	 */
	if( !(affine = IM_NEW( out, Affine )) )
		return( -1 );
	affine->interpolate = NULL;
	if( im_add_close_callback( out, 
		(im_callback_fn) affine_free, affine, NULL ) )
		return( -1 );
	affine->in = in;
	affine->out = out;
	affine->interpolate = interpolate;
	g_object_ref( interpolate );
	affine->trn = *trn;

	if( im__transform_calc_inverse( &affine->trn ) )
		return( -1 );

	out->Xsize = affine->trn.oarea.width;
	out->Ysize = affine->trn.oarea.height;

	/* Normally SMALLTILE ... except if this is a size up/down affine.
	 */
	if( affine->trn.b == 0.0 && affine->trn.c == 0.0 ) {
		if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) )
			return( -1 );
	}
	else {
		if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) )
			return( -1 );
	}

	/* Check for coordinate overflow ... we want to be able to hold the
	 * output space inside INT_MAX / TRANSFORM_SCALE.
	 */
	edge = INT_MAX / VIPS_TRANSFORM_SCALE;
	if( affine->trn.oarea.left < -edge || affine->trn.oarea.top < -edge ||
		IM_RECT_RIGHT( &affine->trn.oarea ) > edge || 
		IM_RECT_BOTTOM( &affine->trn.oarea ) > edge ) {
		im_error( "im_affinei", 
			"%s", _( "output coordinates out of range" ) );
		return( -1 );
	}

	/* Generate!
	 */
	if( im_generate( out, 
		im_start_one, affinei_gen, im_stop_one, in, affine ) )
		return( -1 );

	return( 0 );
}
Esempio n. 30
0
/* Top-bottom blend function for non-labpack images.
 */
static int
tb_blend( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	IMAGE *im = or->im;

	Rect prr, psr;
	int y, yr, ys;

	/* Make sure we have a complete first/last set for this area.
	 */
	if( make_firstlast( inf, ovlap, oreg ) )
		return( -1 );

	/* Part of rr which we will output.
	 */
	prr = *oreg;
	prr.left -= ovlap->rarea.left;
	prr.top -= ovlap->rarea.top;

	/* Part of sr which we will output.
	 */
	psr = *oreg;
	psr.left -= ovlap->sarea.left;
	psr.top -= ovlap->sarea.top;

	/* Make pixels.
	 */
	if( im_prepare( rir, &prr ) )
		return( -1 );
	if( im_prepare( sir, &psr ) )
		return( -1 );

	/* Loop down overlap area.
	 */
	for( y = oreg->top, yr = prr.top, ys = psr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) { 
		VipsPel *pr = IM_REGION_ADDR( rir, prr.left, yr );
		VipsPel *ps = IM_REGION_ADDR( sir, psr.left, ys );
		VipsPel *q = IM_REGION_ADDR( or, oreg->left, y );

		const int j = oreg->left - ovlap->overlap.left;
		const int *first = ovlap->first + j;
		const int *last = ovlap->last + j;

		switch( im->BandFmt ) {
		case IM_BANDFMT_UCHAR: 	
			iblend( unsigned char, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_CHAR: 	
			iblend( signed char, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_USHORT: 
			iblend( unsigned short, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_SHORT: 	
			iblend( signed short, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_UINT: 	
			iblend( unsigned int, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_INT: 	
			iblend( signed int, im->Bands, pr, ps, q );  break; 
		case IM_BANDFMT_FLOAT: 	
			fblend( float, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_DOUBLE:	
			fblend( double, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_COMPLEX:
			fblend( float, im->Bands*2, pr, ps, q ); break; 
		case IM_BANDFMT_DPCOMPLEX:
			fblend( double, im->Bands*2, pr, ps, q ); break;

		default:
			im_error( "im_tbmerge", "%s", _( "internal error" ) );
			return( -1 );
		}
	}

	return( 0 );
}