Esempio n. 1
0
static int
vips_similarity_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );
	VipsSimilarity *similarity = (VipsSimilarity *) object;

	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 4 );

	double a, b, c, d; 

	if( VIPS_OBJECT_CLASS( vips_similarity_parent_class )->build( object ) )
		return( -1 );

	a = similarity->scale * cos( VIPS_RAD( similarity->angle ) ); 
	b = sin( VIPS_RAD( similarity->angle ) );
	c = -b;
	d = a;

	if( vips_affine( resample->in, &t[0], a, b, c, d, 
		"interpolate", similarity->interpolate,
		"odx", similarity->odx,
		"ody", similarity->ody,
		"idx", similarity->idx,
		"idy", similarity->idy,
		NULL ) ||
		vips_image_write( t[0], resample->out ) )
		return( -1 ); 

	return( 0 );
}
Esempio n. 2
0
/* Generate an area of @or. @ir is large enough.
 */
static void
vips_shrink2_gen2( VipsShrink2 *shrink, VipsShrink2Sequence *seq,
                   VipsRegion *or, VipsRegion *ir,
                   int left, int top, int width, int height )
{
    VipsResample *resample = VIPS_RESAMPLE( shrink );
    const int bands = resample->in->Bands;
    const int sizeof_pixel = VIPS_IMAGE_SIZEOF_PEL( resample->in );
    const int ls = VIPS_REGION_LSKIP( ir ) /
                   VIPS_IMAGE_SIZEOF_ELEMENT( resample->in );

    int x, y, i;
    int x1, y1, b;

    for( y = 0; y < height; y++ ) {
        VipsPel *out = VIPS_REGION_ADDR( or, left, top + y );

        for( x = 0; x < width; x++ ) {
            int ix = (left + x) * shrink->xshrink;
            int iy = (top + y) * shrink->yshrink;
            VipsPel *in = VIPS_REGION_ADDR( ir, ix, iy );

            switch( resample->in->BandFmt ) {
            case VIPS_FORMAT_UCHAR:
                ISHRINK( unsigned char );
                break;
            case VIPS_FORMAT_CHAR:
                ISHRINK( char );
                break;
            case VIPS_FORMAT_USHORT:
                ISHRINK( unsigned short );
                break;
            case VIPS_FORMAT_SHORT:
                ISHRINK( short );
                break;
            case VIPS_FORMAT_UINT:
                ISHRINK( unsigned int );
                break;
            case VIPS_FORMAT_INT:
                ISHRINK( int );
                break;
            case VIPS_FORMAT_FLOAT:
                FSHRINK( float );
                break;
            case VIPS_FORMAT_DOUBLE:
                FSHRINK( double );
                break;

            default:
                g_assert( 0 );
            }

            out += sizeof_pixel;
        }
    }
}
Esempio n. 3
0
static int
vips_similarity_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );
	VipsSimilarity *similarity = (VipsSimilarity *) object;

	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 4 );

	if( VIPS_OBJECT_CLASS( vips_similarity_parent_class )->build( object ) )
		return( -1 );

	/* Use vips_reduce(), if we can.
	 */
	if( similarity->interpolate && 
		strcmp( VIPS_OBJECT_GET_CLASS( similarity->interpolate )->
			nickname, "bicubic" ) == 0 &&
		similarity->angle == 0.0 &&
		similarity->idx == 0.0 &&
		similarity->idy == 0.0 &&
		similarity->odx == 0.0 &&
		similarity->ody == 0.0 ) {
		if( vips_reduce( resample->in, &t[0], 
			1.0 / similarity->scale, 
			1.0 / similarity->scale, NULL ) )  
			return( -1 );
	}
	else {
		double a = similarity->scale * 
			cos( VIPS_RAD( similarity->angle ) ); 
		double b = similarity->scale * 
			-sin( VIPS_RAD( similarity->angle ) );
		double c = -b;
		double d = a;

		if( vips_affine( resample->in, &t[0], a, b, c, d, 
			"interpolate", similarity->interpolate,
			"odx", similarity->odx,
			"ody", similarity->ody,
			"idx", similarity->idx,
			"idy", similarity->idy,
			NULL ) )
			return( -1 );
	}

	if( vips_image_write( t[0], resample->out ) )
		return( -1 ); 

	return( 0 );
}
Esempio n. 4
0
static int
vips_shrink_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );
	VipsShrink *shrink = (VipsShrink *) object;
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 3 );

	int xshrink_int;
	int yshrink_int;

	if( VIPS_OBJECT_CLASS( vips_shrink_parent_class )->build( object ) )
		return( -1 );

	xshrink_int = (int) shrink->xshrink;
	yshrink_int = (int) shrink->yshrink;

	if( xshrink_int != shrink->xshrink || 
		yshrink_int != shrink->yshrink ) {
		/* Shrink by int factors, affine to final size.
		 */
		int target_width = resample->in->Xsize / shrink->xshrink;
		int target_height = resample->in->Ysize / shrink->yshrink;

		double xresidual;
		double yresidual;

		if( vips_shrinkv( resample->in, &t[0], yshrink_int, NULL ) ||
			vips_shrinkh( t[0], &t[1], xshrink_int, NULL ) )
			return( -1 ); 

		xresidual = (double) target_width / t[1]->Xsize;
		yresidual = (double) target_height / t[1]->Ysize;

		if( vips_affine( t[1], &t[2], 
			xresidual, 0.0, 0.0, yresidual, NULL ) ||
			vips_image_write( t[2], resample->out ) )
			return( -1 );
	}
	else {
		if( vips_shrinkv( resample->in, &t[0], shrink->yshrink, NULL ) ||
			vips_shrinkh( t[0], &t[1], shrink->xshrink, NULL ) ||
			vips_image_write( t[1], resample->out ) )
			return( -1 );
	}

	return( 0 );
}
Esempio n. 5
0
static int
vips_resample_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );

#ifdef DEBUG
	printf( "vips_resample_build: " );
	vips_object_print_name( object );
	printf( "\n" );
#endif /*DEBUG*/

	g_object_set( resample, "out", vips_image_new(), NULL ); 

	if( VIPS_OBJECT_CLASS( vips_resample_parent_class )->build( object ) )
		return( -1 );

	return( 0 );
}
Esempio n. 6
0
/* Generate an area of @or. @ir is large enough.
 */
static void
vips_shrinkh_gen2( VipsShrinkh *shrink, VipsShrinkhSequence *seq,
	VipsRegion *or, VipsRegion *ir,
	int left, int top, int width )
{
	VipsResample *resample = VIPS_RESAMPLE( shrink );
	const int bands = resample->in->Bands * 
		(vips_band_format_iscomplex( resample->in->BandFmt ) ? 
		 	2 : 1);
	const int ne = shrink->xshrink * bands; 
	VipsPel *out = VIPS_REGION_ADDR( or, left, top ); 
	VipsPel *in = VIPS_REGION_ADDR( ir, left * shrink->xshrink, top ); 

	int x;
	int x1, b;

	switch( resample->in->BandFmt ) {
	case VIPS_FORMAT_UCHAR: 	
		ISHRINK( unsigned char ); break;
	case VIPS_FORMAT_CHAR: 	
		ISHRINK( char ); break; 
	case VIPS_FORMAT_USHORT: 
		ISHRINK( unsigned short ); break;
	case VIPS_FORMAT_SHORT: 	
		ISHRINK( short ); break; 
	case VIPS_FORMAT_UINT: 	
		ISHRINK( unsigned int ); break; 
	case VIPS_FORMAT_INT: 	
		ISHRINK( int );  break; 
	case VIPS_FORMAT_FLOAT: 	
		FSHRINK( float ); break; 
	case VIPS_FORMAT_DOUBLE:	
		FSHRINK( double ); break;
	case VIPS_FORMAT_COMPLEX: 	
		FSHRINK( float ); break; 
	case VIPS_FORMAT_DPCOMPLEX:	
		FSHRINK( double ); break;

	default:
		g_assert( 0 ); 
	}
}
Esempio n. 7
0
        vips_shrink2_gen2( shrink, seq,
                           or, ir,
                           r->left, r->top + y, r->width, height );

        VIPS_GATE_STOP( "vips_shrink2_gen: work" );
    }

    return( 0 );
}

static int
vips_shrink2_build( VipsObject *object )
{
    VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
    VipsResample *resample = VIPS_RESAMPLE( object );
    VipsShrink2 *shrink = (VipsShrink2 *) object;
    VipsImage **t = (VipsImage **)
                    vips_object_local_array( object, 1 );

    VipsImage *in;

    if( VIPS_OBJECT_CLASS( vips_shrink2_parent_class )->build( object ) )
        return( -1 );

    shrink->mw = ceil( shrink->xshrink );
    shrink->mh = ceil( shrink->yshrink );
    shrink->np = shrink->mw * shrink->mh;

    in = resample->in;
Esempio n. 8
0
static int
vips_mapim_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRect *r = &or->valid;
	VipsRegion **ir = (VipsRegion **) seq;
	const VipsImage **in_array = (const VipsImage **) a;
	const VipsMapim *mapim = (VipsMapim *) b; 
	const VipsResample *resample = VIPS_RESAMPLE( mapim );
	const VipsImage *in = in_array[0];
	const int window_size = 
		vips_interpolate_get_window_size( mapim->interpolate );
	const int window_offset = 
		vips_interpolate_get_window_offset( mapim->interpolate );
	const VipsInterpolateMethod interpolate = 
		vips_interpolate_get_method( mapim->interpolate );
	const int ps = VIPS_IMAGE_SIZEOF_PEL( in );
	const int clip_width = resample->in->Xsize;
	const int clip_height = resample->in->Ysize;

	VipsRect bounds, image, clipped;
	int x, y, z;
	
#ifdef DEBUG_VERBOSE
	printf( "vips_mapim_gen: "
		"generating left=%d, top=%d, width=%d, height=%d\n", 
		r->left,
		r->top,
		r->width,
		r->height );
#endif /*DEBUG_VERBOSE*/

	/* Fetch the chunk of the mapim image we need, and find the max/min in
	 * x and y.
	 */
	if( vips_region_prepare( ir[1], r ) )
		return( -1 );

	VIPS_GATE_START( "vips_mapim_gen: work" ); 

	vips_mapim_region_minmax( ir[1], r, &bounds ); 

	VIPS_GATE_STOP( "vips_mapim_gen: work" ); 

	/* The bounding box of that area is what we will need from @in. Add
	 * enough for the interpolation stencil as well.
	 * 
	 */
	bounds.width += window_size - 1;
	bounds.height += window_size - 1;

	/* Clip against the expanded image.
	 */
	image.left = 0;
	image.top = 0;
	image.width = in->Xsize;
	image.height = in->Ysize;
	vips_rect_intersectrect( &bounds, &image, &clipped );

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

	if( vips_rect_isempty( &clipped ) ) {
		vips_region_black( or );
		return( 0 );
	}
	if( vips_region_prepare( ir[0], &clipped ) )
		return( -1 );

	VIPS_GATE_START( "vips_mapim_gen: work" ); 

	/* Resample! x/y loop over pixels in the output image (5).
	 */
	for( y = 0; y < r->height; y++ ) {
		VipsPel * restrict p = 
			VIPS_REGION_ADDR( ir[1], r->left, y + r->top );
		VipsPel * restrict q = 
			VIPS_REGION_ADDR( or, r->left, y + r->top );

		switch( ir[1]->im->BandFmt ) {
		case VIPS_FORMAT_UCHAR: 	
			ULOOKUP( unsigned char ); break; 
		case VIPS_FORMAT_CHAR: 	
			LOOKUP( signed char ); break; 
		case VIPS_FORMAT_USHORT: 
			ULOOKUP( unsigned short ); break; 
		case VIPS_FORMAT_SHORT: 	
			LOOKUP( signed short ); break; 
		case VIPS_FORMAT_UINT: 	
			ULOOKUP( unsigned int ); break; 
		case VIPS_FORMAT_INT: 	
			LOOKUP( signed int ); break; 

		case VIPS_FORMAT_FLOAT: 		
		case VIPS_FORMAT_COMPLEX: 
			LOOKUP( float ); break; 
			break;

		case VIPS_FORMAT_DOUBLE:	
		case VIPS_FORMAT_DPCOMPLEX: 
			LOOKUP( double ); break;

		default:
			g_assert_not_reached();
		}
	}

	VIPS_GATE_STOP( "vips_mapim_gen: work" ); 

	return( 0 );
}
Esempio n. 9
0
static int
vips_quadratic_gen( VipsRegion *or, void *vseq, 
	void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) vseq;
	VipsQuadratic *quadratic = (VipsQuadratic *) b;
	VipsResample *resample = VIPS_RESAMPLE( quadratic );
	VipsInterpolateMethod interpolate_fn = 
		vips_interpolate_get_method( quadratic->interpolate );

	/* @in is the enlarged image (borders on, after vips_embed()). Use
	 * @resample->in for the original, not-expanded image. 
	 */
	const VipsImage *in = (VipsImage *) a;

	const int ps = VIPS_IMAGE_SIZEOF_PEL( in );

	double *vec = (double *) VIPS_IMAGE_ADDR( quadratic->mat, 0, 0 );

	int clip_width = resample->in->Xsize;
	int clip_height = resample->in->Ysize;

	int xlow = or->valid.left;
	int ylow = or->valid.top;
	int xhigh = VIPS_RECT_RIGHT( &or->valid );
	int yhigh = VIPS_RECT_BOTTOM( &or->valid );

	VipsPel *q;

	int xo, yo;		/* output coordinates, dstimage */
	int z;
	double fxi, fyi; 	/* input coordinates */
	double dx, dy;        	/* xo derivative of input coord. */
	double ddx, ddy;      	/* 2nd xo derivative of input coord. */

	VipsRect image;

	image.left = 0;
	image.top = 0;
	image.width = in->Xsize;
	image.height = in->Ysize;
	if( vips_region_image( ir, &image ) )
		return( -1 );

	for( yo = ylow; yo < yhigh; yo++ ) {
		fxi = xlow + vec[0];                /* order 0 */
		fyi = yo + vec[1];    
		dx = 1.0;
		dy = 0.0;

		switch( quadratic->order ) {
		case 3: 
			fxi += vec[10] * yo * yo + vec[8] * xlow * xlow;
			fyi += vec[11] * yo * yo + vec[9] * xlow * xlow;
			dx += vec[8];
			ddx = vec[8] * 2.0;
			dy += vec[9];
			ddy = vec[9] * 2.0;

		case 2: 
			fxi += vec[6] * xlow * yo;
			fyi += vec[7] * xlow * yo;
			dx += vec[6] * yo;
			dy += vec[7] * yo;

		case 1: 
			fxi += vec[4] * yo + vec[2] * xlow;
			fyi += vec[5] * yo + vec[3] * xlow;
			dx += vec[2];
			dy += vec[3];

		case 0: 
			/* See above for order 0.
			 */
			break;

		default:
		    	g_assert( 0 );
		    	return(-7);
		}

		q = VIPS_REGION_ADDR( or, xlow, yo );

		for( xo = xlow; xo < xhigh; xo++ ) {
			int xi, yi; 	

			xi = fxi;
			yi = fyi;

			/* Clipping! 
			 */
			if( xi < 0 || 
				yi < 0 || 
				xi >= clip_width || 
				yi >= clip_height ) {
				for( z = 0; z < ps; z++ ) 
					q[z] = 0;
			}
			else 
				interpolate_fn( quadratic->interpolate, 
					q, ir, fxi, fyi );

			q += ps;

			fxi += dx;
			fyi += dy;

			if( quadratic->order > 2 ) {
				dx += ddx;
				dy += ddy;
			}
		}
	}

	return( 0 );
}
Esempio n. 10
0
static int
vips_resize_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );
	VipsResize *resize = (VipsResize *) object;

	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 7 );

	VipsImage *in;
	int window_size;
	int int_shrink;
	int int_shrink_width;
	double residual;
	double sigma;

	if( VIPS_OBJECT_CLASS( vips_resize_parent_class )->build( object ) )
		return( -1 );

	if( !vips_object_argument_isset( object, "interpolate" ) ) {
		VipsInterpolate *interpolate;
		char *nick;

		if( vips_type_find( "VipsInterpolate", "bicubic" ) )
			nick = "bicubic";
		else
			nick = "bilinear";
		interpolate = vips_interpolate_new( nick );
		g_object_set( object, "interpolate", interpolate, NULL ); 
		VIPS_UNREF( interpolate ); 
	}

	in = resample->in;

	window_size = resize->interpolate ? 
		vips_interpolate_get_window_size( resize->interpolate ) : 2;

	/* If the factor is > 1.0, we need to zoom rather than shrink.
	 * Just set the int part to 1 in this case.
	 */
	int_shrink = resize->scale > 1.0 ? 1 : floor( 1.0 / resize->scale );

	/* We want to shrink by less for interpolators with larger windows.
	 */
	int_shrink = VIPS_MAX( 1,
		int_shrink / VIPS_MAX( 1, window_size / 2 ) );

	/* Size after int shrink.
	 */
	int_shrink_width = in->Xsize / int_shrink;

	/* Therefore residual scale factor is.
	 */
	residual = (in->Xsize * resize->scale) / int_shrink_width;

	/* A copy for enlarge resize.
	 */
	if( vips_shrink( in, &t[0], int_shrink, int_shrink, NULL ) )
		return( -1 );
	in = t[0];

	/* We want to make sure we read the image sequentially.
	 * However, the convolution we may be doing later will force us 
	 * into SMALLTILE or maybe FATSTRIP mode and that will break
	 * sequentiality.
	 *
	 * So ... read into a cache where tiles are scanlines, and make sure
	 * we keep enough scanlines to be able to serve a line of tiles.
	 *
	 * We use a threaded tilecache to avoid a deadlock: suppose thread1,
	 * evaluating the top block of the output, is delayed, and thread2, 
	 * evaluating the second block, gets here first (this can happen on 
	 * a heavily-loaded system). 
	 *
	 * With an unthreaded tilecache (as we had before), thread2 will get
	 * the cache lock and start evaling the second block of the shrink. 
	 * When it reaches the png reader it will stall until the first block 
	 * has been used ... but it never will, since thread1 will block on 
	 * this cache lock. 
	 */
	if( int_shrink > 1 ) { 
		int tile_width;
		int tile_height;
		int nlines;

		vips_get_tile_size( in, 
			&tile_width, &tile_height, &nlines );
		if( vips_tilecache( in, &t[6], 
			"tile_width", in->Xsize,
			"tile_height", 10,
			"max_tiles", 1 + (nlines * 2) / 10,
			"access", VIPS_ACCESS_SEQUENTIAL,
			"threaded", TRUE, 
			NULL ) )
			return( -1 );
		in = t[6];
	}

	/* If the final affine will be doing a large downsample, we can get 
	 * nasty aliasing on hard edges. Blur before affine to smooth this out.
	 *
	 * Don't blur for very small shrinks, blur with radius 1 for x1.5
	 * shrinks, blur radius 2 for x2.5 shrinks and above, etc.
	 */
	sigma = ((1.0 / residual) - 0.5) / 1.5;
	if( residual < 1.0 &&
		sigma > 0.1 ) { 
		if( vips_gaussblur( in, &t[2], sigma, NULL ) )
			return( -1 );
		in = t[2];
	}

	if( vips_affine( in, &t[3], residual, 0, 0, residual, 
		"interpolate", resize->interpolate,
		"idx", resize->idx,
		"idy", resize->idy,
		NULL ) )  
		return( -1 );
	in = t[3];

	/* If we are upsampling, don't sharpen.
	 */
	if( int_shrink > 1 ) { 
		t[5] = vips_image_new_matrixv( 3, 3,
			-1.0, -1.0, -1.0,
			-1.0, 32.0, -1.0,
			-1.0, -1.0, -1.0 );
		vips_image_set_double( t[5], "scale", 24 );

		if( vips_conv( in, &t[4], t[5], NULL ) ) 
			return( -1 );
		in = t[4];
	}

	if( vips_image_write( in, resample->out ) )
		return( -1 ); 

	return( 0 );
}
Esempio n. 11
0
static int
vips_similarity_build( VipsObject *object )
{
	VipsResample *resample = VIPS_RESAMPLE( object );
	VipsSimilarity *similarity = (VipsSimilarity *) object;
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 4 );

	gboolean handled;

	if( VIPS_OBJECT_CLASS( vips_similarity_parent_class )->build( object ) )
		return( -1 );

	handled = FALSE;

	/* Use vips_reduce(), if we can.
	 */
	if( similarity->interpolate &&
		similarity->angle == 0.0 &&
		similarity->idx == 0.0 &&
		similarity->idy == 0.0 &&
		similarity->odx == 0.0 &&
		similarity->ody == 0.0 ) {
		const char *nickname = VIPS_OBJECT_GET_CLASS( 
			similarity->interpolate )->nickname;

		int i; 

		for( i = 0; i < VIPS_NUMBER( vips_similarity_kernel ); i++ ) {
			VipsInterpolateKernel *ik = &vips_similarity_kernel[i];

			if( strcmp( nickname, ik->nickname ) == 0 ) {
				if( vips_reduce( resample->in, &t[0], 
					1.0 / similarity->scale, 
					1.0 / similarity->scale, 
					"kernel", ik->kernel,
					NULL ) )
					return( -1 );

				handled = TRUE;
				break;
			}
		}
	}

	if( !handled ) { 
		double a = similarity->scale * 
			cos( VIPS_RAD( similarity->angle ) ); 
		double b = similarity->scale * 
			-sin( VIPS_RAD( similarity->angle ) );
		double c = -b;
		double d = a;

		if( vips_affine( resample->in, &t[0], a, b, c, d, 
			"interpolate", similarity->interpolate,
			"odx", similarity->odx,
			"ody", similarity->ody,
			"idx", similarity->idx,
			"idy", similarity->idy,
			NULL ) )
			return( -1 );
	}

	if( vips_image_write( t[0], resample->out ) )
		return( -1 ); 

	return( 0 );
}