Exemple #1
0
static int
vips_foreign_save_tiff_build( VipsObject *object )
{
	VipsForeignSave *save = (VipsForeignSave *) object;
	VipsForeignSaveTiff *tiff = (VipsForeignSaveTiff *) object;

	const char *p;

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

	/* Default xres/yres to the values from the image.
	 */
	if( !vips_object_argument_isset( object, "xres" ) )
		tiff->xres = save->ready->Xres * 10.0;
	if( !vips_object_argument_isset( object, "yres" ) )
		tiff->yres = save->ready->Yres * 10.0;

	/* resunit param overrides resunit metadata.
	 */
	if( !vips_object_argument_isset( object, "resunit" ) &&
		vips_image_get_typeof( save->ready, 
			VIPS_META_RESOLUTION_UNIT ) &&
		!vips_image_get_string( save->ready, 
			VIPS_META_RESOLUTION_UNIT, &p ) &&
		vips_isprefix( "in", p ) ) 
		tiff->resunit = VIPS_FOREIGN_TIFF_RESUNIT_INCH;

	if( tiff->resunit == VIPS_FOREIGN_TIFF_RESUNIT_INCH ) {
		tiff->xres *= 2.54;
		tiff->yres *= 2.54;
	}

	if( vips__tiff_write( save->ready, tiff->filename,
		tiff->compression, tiff->Q, tiff->predictor,
		tiff->profile,
		tiff->tile, tiff->tile_width, tiff->tile_height,
		tiff->pyramid,
		tiff->squash,
		tiff->miniswhite,
		tiff->resunit, tiff->xres, tiff->yres,
		tiff->bigtiff,
		tiff->rgbjpeg,
		tiff->properties ) )
		return( -1 );

	return( 0 );
}
Exemple #2
0
static int
vips_foreign_load_pdf_build( VipsObject *object )
{
	VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;

	if( !vips_object_argument_isset( object, "scale" ) )
		pdf->scale = pdf->dpi / 72.0;

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

	return( 0 );
}
Exemple #3
0
static int
vips_foreign_load_svg_build( VipsObject *object )
{
	VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) object;

	if( !vips_object_argument_isset( object, "scale" ) )
		svg->scale = svg->dpi / 72.0;

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

	return( 0 );
}
Exemple #4
0
static void *
vips_object_equal_arg( VipsObject *object,
	GParamSpec *pspec,
	VipsArgumentClass *argument_class,
	VipsArgumentInstance *argument_instance,
	void *a, void *b )
{
	VipsObject *other = (VipsObject *) a;

	const char *name = g_param_spec_get_name( pspec );
	GType type = G_PARAM_SPEC_VALUE_TYPE( pspec );
	GValue v1 = { 0, };
	GValue v2 = { 0, };

	gboolean equal;

	/* Only test assigned input constructor args.
	 */
	if( !(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) ||
		!(argument_class->flags & VIPS_ARGUMENT_INPUT) ||
		!argument_instance->assigned ) 
		return( NULL );

	/* If this is an optional arg, we need to check that this was
	 * assigned on @other as well.
	 */
	if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) &&
		!vips_object_argument_isset( other, name ) )
		/* Optional and was not set on other ... we've found a
		 * difference!
		 */
		return( object ); 

	g_value_init( &v1, type );
	g_value_init( &v2, type );
	g_object_get_property( G_OBJECT( object ), name, &v1 ); 
	g_object_get_property( G_OBJECT( other ), name, &v2 ); 
	equal = vips_value_equal( pspec, &v1, &v2 );
	g_value_unset( &v1 );
	g_value_unset( &v2 );

	/* Stop (return non-NULL) if we've found a difference.
	 */
	return( !equal ? object : NULL ); 
}
static int
vips_colourspace_build( VipsObject *object )
{
	VipsColourspace *colourspace = (VipsColourspace *) object; 

	int i, j;
	VipsImage *x;
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( object, 1 );
	VipsImage **pipe = (VipsImage **) 
		vips_object_local_array( object, MAX_STEPS );

	VipsInterpretation interpretation;

	/* Verify that all input args have been set.
	 */
	if( VIPS_OBJECT_CLASS( vips_colourspace_parent_class )->
		build( object ) )
		return( -1 );

	x = colourspace->in;

	/* Unpack radiance-coded images. We can't use interpretation for this,
	 * since rad images can be scRGB or XYZ.
	 */
	if( x->Coding == VIPS_CODING_RAD ) {
		if( vips_rad2float( x, &t[0], NULL ) )
			return( -1 );
		x = t[0]; 
	}

	if( vips_object_argument_isset( object, "source_space" ) )
		interpretation = colourspace->source_space;
	else
		interpretation = vips_image_guess_interpretation( x );

	/* Treat RGB as sRGB. If you want some other treatment,
	 * you'll need to use the icc funcs.
	 */
	if( interpretation == VIPS_INTERPRETATION_RGB )
		interpretation = VIPS_INTERPRETATION_sRGB;

	/* No conversion necessary.
	 */
	if( interpretation == colourspace->space ) {
		g_object_set( colourspace, "out", vips_image_new(), NULL ); 

		return( vips_image_write( colourspace->in, colourspace->out ) );
	}

	for( i = 0; i < VIPS_NUMBER( vips_colour_routes ); i++ )
		if( vips_colour_routes[i].from == interpretation &&
			vips_colour_routes[i].to == colourspace->space )
			break;
	if( i == VIPS_NUMBER( vips_colour_routes ) ) {
		vips_error( "vips_colourspace", 
			_( "no known route between '%s' and '%s'" ),
			vips_enum_nick( VIPS_TYPE_INTERPRETATION, 
				interpretation ),
			vips_enum_nick( VIPS_TYPE_INTERPRETATION, 
				colourspace->space ) );
		return( -1 );
	}

	for( j = 0; vips_colour_routes[i].route[j]; j++ ) {
		if( vips_colour_routes[i].route[j]( x, &pipe[j], NULL ) ) 
			return( -1 );
		x = pipe[j];
	}

	g_object_set( colourspace, "out", vips_image_new(), NULL ); 
	if( vips_image_write( x, colourspace->out ) )
		return( -1 );

	return( 0 );
}
Exemple #6
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 );
}