Example #1
0
static int
write_dzi( VipsForeignSaveDz *dz )
{
	GsfOutput *out;
	char buf[VIPS_PATH_MAX];
	char *p;

	vips_snprintf( buf, VIPS_PATH_MAX, "%s.dzi", dz->basename );
	out = vips_gsf_path( dz->tree, buf, NULL ); 

	vips_snprintf( buf, VIPS_PATH_MAX, "%s", dz->suffix + 1 );
	if( (p = (char *) vips__find_rightmost_brackets( buf )) )
		*p = '\0';

	gsf_output_printf( out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); 
	gsf_output_printf( out, "<Image "
		"xmlns=\"http://schemas.microsoft.com/deepzoom/2008\"\n" );
	gsf_output_printf( out, "  Format=\"%s\"\n", buf );
	gsf_output_printf( out, "  Overlap=\"%d\"\n", dz->overlap );
	gsf_output_printf( out, "  TileSize=\"%d\"\n", dz->tile_size );
	gsf_output_printf( out, "  >\n" ); 
	gsf_output_printf( out, "  <Size \n" );
	gsf_output_printf( out, "    Height=\"%d\"\n", dz->layer->height );
	gsf_output_printf( out, "    Width=\"%d\"\n", dz->layer->width );
	gsf_output_printf( out, "  />\n" ); 
	gsf_output_printf( out, "</Image>\n" );

	(void) gsf_output_close( out );
	g_object_unref( out );

	return( 0 );
}
Example #2
0
/* Make a temporary file name. The format parameter is something like "%s.jpg" 
 * and will be expanded to something like "/tmp/vips-12-34587.jpg".
 *
 * You need to free the result. 
 */
char *
vips__temp_name( const char *format )
{
	static int serial = 0;

	char file[FILENAME_MAX];
	char file2[FILENAME_MAX];
	char *name;

	vips_snprintf( file, FILENAME_MAX, "vips-%d-%u", 
		serial++, g_random_int() );
	vips_snprintf( file2, FILENAME_MAX, format, file );
	name = g_build_filename( vips__temp_dir(), file2, NULL );

	/* We could use something like g_mkstemp() to guarantee uniqueness
	 * across processes, but the extra FS calls can be difficult for 
	 * selinux.
	 *
	 * g_random_int() should be safe enough -- it's seeded from time(), so
	 * it ought not to collide often -- and on linux at least we never 
	 * actually use these filenames in the filesystem anyway.
	 */

	return( name );
}
Example #3
0
void
vips_vector_constant( VipsVector *vector, char *name, int value, int size )
{
#ifdef HAVE_ORC
	char *sname;

	if( size == 1 )
		sname = "b";
	else if( size == 2 )
		sname = "w";
	else if( size == 4 )
		sname = "l";
	else {
		printf( "vips_vector_constant: bad constant size\n" );

		/* Not really correct, heh.
		 */
		sname = "x";
	}

	if( value > 0 )
		vips_snprintf( name, 256, "c%d%s", value, sname );
	else
		vips_snprintf( name, 256, "cm%d%s", -value, sname );

	if( orc_program_find_var_by_name( vector->program, name ) == -1 ) {
		orc_program_add_constant( vector->program, size, value, name );
		vector->n_constant += 1;
	}
#endif /*HAVE_ORC*/
}
Example #4
0
/* Make a temporary file name. The format parameter is something like "%s.jpg" 
 * and will be expanded to something like "/tmp/vips-12-34587.jpg".
 *
 * You need to free the result. A real file will also be created, though we
 * delete it for you.
 */
char *
vips__temp_name( const char *format )
{
	static int serial = 1;

	char file[FILENAME_MAX];
	char file2[FILENAME_MAX];

	char *name;
	int fd;

	vips_snprintf( file, FILENAME_MAX, "vips-%d-XXXXXX", serial++ );
	vips_snprintf( file2, FILENAME_MAX, format, file );
	name = g_build_filename( vips__temp_dir(), file2, NULL );

	if( (fd = g_mkstemp( name )) == -1 ) {
		vips_error( "tempfile", 
			_( "unable to make temporary file %s" ), name );
		g_free( name );
		return( NULL );
	}
	close( fd );
	g_unlink( name );

	return( name );
}
Example #5
0
/* Guess a value for the install PREFIX.
 */
static const char *
guess_prefix( const char *argv0, const char *name )
{
	char *prefix;

	/* Try to guess from argv0.
	 */
	if( argv0 ) {
		if( g_path_is_absolute( argv0 ) ) {
			/* Must point to our executable.
			 */
			if( (prefix = extract_prefix( argv0, name )) ) {
#ifdef DEBUG
				printf( "vips_guess_prefix: found \"%s\" from "
					"argv0\n", prefix );
#endif /*DEBUG*/
				return( prefix );
			} 
		}

		/* Look along path for name.
		 */
		if( (prefix = find_file( name )) ) {
#ifdef DEBUG
			printf( "vips_guess_prefix: found \"%s\" from "
				"PATH\n", prefix );
#endif /*DEBUG*/
			return( prefix );
		}
        }

#ifdef HAVE_REALPATH
	/* Try to guess from cwd. Only if this is a relative path, though. No
 	 * realpath on winders, but fortunately it seems to always generate
 	 * a full path in argv[0].
	 */
	if( !g_path_is_absolute( argv0 ) ) {
		char full_path[PATH_MAX];
		char resolved[PATH_MAX];

		vips_snprintf( full_path, PATH_MAX, 
			"%s" G_DIR_SEPARATOR_S "%s", get_current_dir(), argv0 );

		if( realpath( full_path, resolved ) ) {
			if( (prefix = extract_prefix( resolved, name )) ) {

#ifdef DEBUG
				printf( "vips_guess_prefix: found \"%s\" "
					"from cwd\n", prefix );
#endif /*DEBUG*/
				return( prefix );
			}
		}
	}
#endif /*HAVE_REALPATH*/

	/* Fall back to the configure-time prefix.
	 */
	return( VIPS_PREFIX );
}
Example #6
0
/* Search a path for a file ... we overwrite the PATH string passed in.
 */
static char *
scan_path( char *path, const char *name )
{
	char *p, *q;
	char *prefix;

	for( p = path; 
		(q = vips_break_token( p, G_SEARCHPATH_SEPARATOR_S )); p = q ) {
		char str[PATH_MAX];

		/* Form complete path.
		 */
		vips_snprintf( str, PATH_MAX, 
			"%s" G_DIR_SEPARATOR_S "%s", p, name );

#ifdef DEBUG
		printf( "scan_path: looking in \"%s\" for \"%s\"\n", 
			p, name );
#endif /*DEBUG*/

		if( vips_existsf( "%s", str ) && 
			(prefix = extract_prefix( str, name )) ) {
			return( prefix );
		}
	}

	return( NULL );
}
Example #7
0
/* Look for a file along PATH. If we find it, look for an enclosing prefix.
 */
static char *
find_file( const char *name )
{
	const char *path = g_getenv( "PATH" );
	char *prefix;
	char full_path[PATH_MAX];

	if( !path )
		return( NULL );

#ifdef DEBUG
	printf( "vips_guess_prefix: g_getenv( \"PATH\" ) == \"%s\"\n", path );
#endif /*DEBUG*/

#ifdef OS_WIN32
	/* Windows always searches '.' first, so prepend cwd to path.
	 */
	vips_snprintf( full_path, PATH_MAX, "%s" G_SEARCHPATH_SEPARATOR_S "%s",
		get_current_dir(), path );
#else /*!OS_WIN32*/
	vips_strncpy( full_path, path, PATH_MAX );
#endif /*OS_WIN32*/

	if( (prefix = scan_path( full_path, name )) ) 
		return( prefix );

	return( NULL );
}
Example #8
0
/* Find the prefix part of a dir ... name is the name of this prog from argv0.
 *
 * dir					name		guess prefix
 *
 * /home/john/vips-7.6.4/bin/vips-7.6	vips-7.6	/home/john/vips-7.6.4
 * /usr/local/bin/ip			ip		/usr/local
 *
 * all other forms ... return NULL.
 */
static char *
extract_prefix( const char *dir, const char *name )
{
	char edir[PATH_MAX];
	char vname[PATH_MAX];
	int i;

#ifdef DEBUG
	printf( "extract_prefix: trying for dir = \"%s\", name = \"%s\"\n", 
		dir, name );
#endif /*DEBUG*/

	/* Is dir relative? Prefix with cwd.
	 */
	if( !g_path_is_absolute( dir ) ) {
		vips_snprintf( edir, PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s",
			get_current_dir(), dir );
	}
	else {
		vips_strncpy( edir, dir, PATH_MAX );
	}

	/* Chop off the trailing prog name, plus the trailing
	 * G_DIR_SEPARATOR_S.
	 */
	if( !vips_ispostfix( edir, name ) ) 
		return( NULL );
	vips_strncpy( vname, edir, PATH_MAX );
	vname[strlen( edir ) - strlen( name ) - 1] = '\0';

	/* Remove any "/./", any trailing "/.", any trailing "/".
	 */
	for( i = 0; i < (int) strlen( vname ); i++ ) 
		if( vips_isprefix( G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S, 
			vname + i ) )
			memcpy( vname + i, vname + i + 2, 
				strlen( vname + i + 2 ) + 1 );
	if( vips_ispostfix( vname, G_DIR_SEPARATOR_S "." ) )
		vname[strlen( vname ) - 2] = '\0';
	if( vips_ispostfix( vname, G_DIR_SEPARATOR_S ) )
		vname[strlen( vname ) - 1] = '\0';

#ifdef DEBUG
	printf( "extract_prefix: canonicalised path = \"%s\"\n", vname );
#endif /*DEBUG*/

	/* Ought to be a "/bin" at the end now.
	 */
	if( !vips_ispostfix( vname, G_DIR_SEPARATOR_S "bin" ) ) 
		return( NULL );
	vname[strlen( vname ) - strlen( G_DIR_SEPARATOR_S "bin" )] = '\0';

#ifdef DEBUG
	printf( "extract_prefix: found \"%s\"\n", vname );
#endif /*DEBUG*/

	return( vips_strdup( NULL, vname ) );
}
Example #9
0
File: type.c Project: alon/libvips
/* Transform an area to a G_TYPE_STRING.
 */
static void
transform_area_g_string( const GValue *src_value, GValue *dest_value )
{
	VipsArea *area;
	char buf[256];

	area = g_value_get_boxed( src_value );
	vips_snprintf( buf, 256, "VIPS_TYPE_AREA, count = %d, data = %p",
		area->count, area->data );
	g_value_set_string( dest_value, buf );
}
Example #10
0
File: type.c Project: alon/libvips
/* Transform a blob to a G_TYPE_STRING.
 */
static void
transform_blob_g_string( const GValue *src_value, GValue *dest_value )
{
	void *blob;
	size_t blob_length;
	char buf[256];

	blob = vips_value_get_blob( src_value, &blob_length );
	vips_snprintf( buf, 256, "VIPS_TYPE_BLOB, data = %p, length = %zd",
		blob, blob_length );
	g_value_set_string( dest_value, buf );
} 
Example #11
0
/* Load all plugins in a directory ... look for '.plg' suffix. Error if we had
 * any probs.
 */
static int
vips_load_plugins( const char *fmt, ... )
{
        va_list ap;
        char dir_name[VIPS_PATH_MAX];
        GDir *dir;
	const char *name;
        int result;

	/* Silently succeed if we can't do modules.
	 */
	if( !g_module_supported() )
		return( 0 );

        va_start( ap, fmt );
        (void) vips_vsnprintf( dir_name, VIPS_PATH_MAX - 1, fmt, ap );
        va_end( ap );

#ifdef DEBUG
	printf( "vips_load_plugins: searching \"%s\"\n", dir_name );
#endif /*DEBUG*/

        if( !(dir = g_dir_open( dir_name, 0, NULL )) ) 
		/* Silent success for dir not there.
		 */
                return( 0 );

        result = 0;
        while( (name = g_dir_read_name( dir )) )
                if( vips_ispostfix( name, ".plg" ) ) { 
			char path[VIPS_PATH_MAX];
			GModule *module;

			vips_snprintf( path, VIPS_PATH_MAX - 1, 
				"%s" G_DIR_SEPARATOR_S "%s", dir_name, name );

#ifdef DEBUG
			printf( "vips_load_plugins: loading \"%s\"\n", path );
#endif /*DEBUG*/

			module = g_module_open( path, G_MODULE_BIND_LAZY );
			if( !module ) {
				vips_warn( "vips_init", 
					_( "unable to load \"%s\" -- %s" ), 
					path, 
					g_module_error() ); 
				result = -1;
			}
                }
        g_dir_close( dir );

	return( result );
}
Example #12
0
static void *
vips_foreign_load_nifti_set( const char *name, GValue *value, glong offset,
	void *a, void *b )
{
	nifti_image *nim = (nifti_image *) a;
	VipsImage *out = VIPS_IMAGE( b );

	char vips_name[256];

	vips_gvalue_read( value, (gpointer) nim + offset );
	vips_snprintf( vips_name, 256, "nifti-%s", name );
	vips_image_set( out, vips_name, value );

	return( NULL );
}
Example #13
0
void
vips_vector_source_scanline( VipsVector *vector, 
	char *name, int line, int size )
{
#ifdef HAVE_ORC
	vips_snprintf( name, 256, "sl%d", line );

	if( orc_program_find_var_by_name( vector->program, name ) == -1 ) {
		int var;

		var = orc_program_add_source( vector->program, size, name );
		vector->sl[vector->n_scanline] = var;
		vector->line[vector->n_scanline] = line;
		vector->n_scanline += 1;
	}
#endif /*HAVE_ORC*/
}
Example #14
0
/* Given (eg.) "/poop/somefile.png", write @im to the thumbnail name,
 * (eg.) "/poop/tn_somefile.jpg".
 */
static int
thumbnail_write( VipsImage *im, const char *filename )
{
	char *file;
	char *p;
	char buf[FILENAME_MAX];
	char *output_name;

	file = g_path_get_basename( filename );

	/* Remove the suffix from the file portion.
	 */
	if( (p = strrchr( file, '.' )) ) 
		*p = '\0';

	/* output_format can be an absolute path, in which case we discard the
	 * path from the incoming file.
	 */
	vips_snprintf( buf, FILENAME_MAX, output_format, file );
	if( g_path_is_absolute( output_format ) ) 
		output_name = g_strdup( buf );
	else {
		char *dir;

		dir = g_path_get_dirname( filename );
		output_name = g_build_filename( dir, buf, NULL );
		g_free( dir );
	}

	vips_info( "vipsthumbnail", 
		"thumbnailing %s as %s", filename, output_name );

	g_free( file );

	if( vips_image_write_to_file( im, output_name, NULL ) ) {
		g_free( output_name );
		return( -1 );
	}
	g_free( output_name );

	return( 0 );
}
Example #15
0
/* Set the png text data as metadata on the vips image.
 */
static int
vips__set_text( VipsImage *out, int i, const char *key, const char *text ) 
{
	char name[256];

	if( strcmp( key, "XML:com.adobe.xmp") == 0 ) 
		/* Save as an XMP tag.
		 */
		strncpy( name, VIPS_META_XMP_NAME, 256 );
	else 
		/* Save as a comment. Some PNGs have EXIF data as
		 * text segments, but the correct way to support this is with
		 * png_get_eXIf_1().
		 */
		vips_snprintf( name, 256, "png-comment-%d-%s", i, key );

	vips_image_set_string( out, name, text );

	return( 0 );
}
Example #16
0
void
vips_vector_source_scanline( VipsVector *vector, 
	char *name, int line, int size )
{
#ifdef HAVE_ORC
	vips_snprintf( name, 256, "sl%d", line );

	if( orc_program_find_var_by_name( vector->program, name ) == -1 ) {
		int var;

		if( !(var = orc_program_add_source( vector->program, 
			size, name )) ) 
			vips_vector_error( vector );
#ifdef DEBUG_TRACE
		printf( "orc_program_add_source( %s, %d, \"%s\" );\n",
			vector->unique_name, size, name );
#endif /*DEBUG_TRACE*/
		vector->sl[vector->n_scanline] = var;
		vector->line[vector->n_scanline] = line;
		vector->n_scanline += 1;
	}
#endif /*HAVE_ORC*/
}
Example #17
0
static int
vips_fits_get_header( VipsFits *fits, VipsImage *out )
{
	int status;
	int bitpix;

	int width, height, bands, format, type;
	int keysexist;
	int i;

	status = 0;

	if( fits_get_img_paramll( fits->fptr, 
		10, &bitpix, &fits->naxis, fits->naxes, &status ) ) {
		vips_fits_error( status );
		return( -1 );
	}

#ifdef VIPS_DEBUG
	VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis );
	for( i = 0; i < fits->naxis; i++ )
		VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] );
#endif /*VIPS_DEBUG*/

	height = 1;
	bands = 1;
	switch( fits->naxis ) {
	/* If you add more dimensions here, adjust data read below. See also
	 * the definition of MAX_DIMENSIONS above.
	 */
	case 10:
	case 9:
	case 8:
	case 7:
	case 6:
	case 5:
	case 4:
		for( i = fits->naxis; i > 3; i-- )
			if( fits->naxes[i - 1] != 1 ) {
				vips_error( "fits", 
					"%s", _( "dimensions above 3 "
					"must be size 1" ) );
				return( -1 );
			}

	case 3:
		bands = fits->naxes[2];

	case 2:
		height = fits->naxes[1];

	case 1:
		width = fits->naxes[0];
		break;

	default:
		vips_error( "fits", _( "bad number of axis %d" ), fits->naxis );
		return( -1 );
	}

	/* Are we in one-band mode?
	 */
	if( fits->band_select != -1 )
		bands = 1;

	/* Get image format. We want the 'raw' format of the image, our caller
	 * can convert using the meta info if they want.
	 */
	for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ )
		if( fits2vips_formats[i][0] == bitpix )
			break;
	if( i == VIPS_NUMBER( fits2vips_formats ) ) {
		vips_error( "fits", _( "unsupported bitpix %d\n" ),
			bitpix );
		return( -1 );
	}
	format = fits2vips_formats[i][1];
	fits->datatype = fits2vips_formats[i][2];

	if( bands == 1 ) {
		if( format == VIPS_FORMAT_USHORT )
			type = VIPS_INTERPRETATION_GREY16;
		else
			type = VIPS_INTERPRETATION_B_W;
	}
	else if( bands == 3 ) {
		if( format == VIPS_FORMAT_USHORT )
			type = VIPS_INTERPRETATION_RGB16;
		else
			type = VIPS_INTERPRETATION_RGB;
	}
	else
		type = VIPS_INTERPRETATION_MULTIBAND;

	vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
	vips_image_init_fields( out,
		 width, height, bands,
		 format,
		 VIPS_CODING_NONE, type, 1.0, 1.0 );

	/* Read all keys into meta.
	 */
	if( fits_get_hdrspace( fits->fptr, &keysexist, NULL, &status ) ) {
		vips_fits_error( status );
		return( -1 );
	}

	for( i = 0; i < keysexist; i++ ) {
		char record[81];
		char vipsname[100];

		if( fits_read_record( fits->fptr, i + 1, record, &status ) ) {
			vips_fits_error( status );
			return( -1 );
		}

		VIPS_DEBUG_MSG( "fits2vips: setting meta on vips image:\n" );
		VIPS_DEBUG_MSG( " record == \"%s\"\n", record );

		/* FITS lets keys repeat. For example, HISTORY appears many
		 * times, each time with a fresh line of history attached. We
		 * have to include the key index in the vips name we assign.
		 */

		vips_snprintf( vipsname, 100, "fits-%d", i );
		vips_image_set_string( out, vipsname, record );
	}

	return( 0 );
}
Example #18
0
static ReadSlide *
readslide_new( const char *filename, VipsImage *out, 
	int level, gboolean autocrop, const char *associated )
{
	ReadSlide *rslide;
	int64_t w, h;
	const char *error;
	const char *background;
	const char * const *properties;
	char *associated_names;

	if( level && 
		associated ) {
		vips_error( "openslide2vips",
			"%s", _( "specify only one of level or associated "
			"image" ) );
		return( NULL );
	}

	rslide = VIPS_NEW( out, ReadSlide );
	memset( rslide, 0, sizeof( *rslide ) );
	g_signal_connect( out, "close", G_CALLBACK( readslide_destroy_cb ),
		rslide );

	rslide->level = level;
	rslide->autocrop = autocrop;
	rslide->associated = g_strdup( associated );

	/* Non-crazy defaults, override below if we can.
	 */
	rslide->tile_width = 256;
	rslide->tile_height = 256;

	rslide->osr = openslide_open( filename );
	if( rslide->osr == NULL ) {
		vips_error( "openslide2vips", 
			"%s", _( "unsupported slide format" ) );
		return( NULL );
	}

	error = openslide_get_error( rslide->osr );
	if( error ) {
		vips_error( "openslide2vips",
			_( "opening slide: %s" ), error );
		return( NULL );
	}

	if( level < 0 || 
		level >= openslide_get_level_count( rslide->osr ) ) {
		vips_error( "openslide2vips",
			"%s", _( "invalid slide level" ) );
		return( NULL );
	}

	if( associated &&
		check_associated_image( rslide->osr, associated ) )
		return( NULL );

	if( associated ) {
		openslide_get_associated_image_dimensions( rslide->osr,
			associated, &w, &h );
		vips_image_set_string( out, "slide-associated-image",
			associated );
		vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
	} 
	else {
		char buf[256];
		const char *value;

		openslide_get_level_dimensions( rslide->osr,
			level, &w, &h );
		rslide->downsample = openslide_get_level_downsample(
			rslide->osr, level );
		vips_image_set_int( out, "slide-level", level );
		vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );

		/* Try to get tile width/height. An undocumented, experimental
		 * feature.
		 */
		vips_snprintf( buf, 256, 
			"openslide.level[%d].tile-width", level );
		if( (value = openslide_get_property_value( rslide->osr, buf )) )
			rslide->tile_width = atoi( value );
		vips_snprintf( buf, 256, 
			"openslide.level[%d].tile-height", level );
		if( (value = openslide_get_property_value( rslide->osr, buf )) )
			rslide->tile_height = atoi( value );
		if( value )
			VIPS_DEBUG_MSG( "readslide_new: found tile-size\n" );

		/* Some images have a bounds in the header. Crop to 
		 * that if autocrop is set. 
		 */
		if( rslide->autocrop ) 
			if( !get_bounds( rslide->osr, &rslide->bounds ) )
				rslide->autocrop = FALSE; 
		if( rslide->autocrop ) {
			VipsRect image;

			rslide->bounds.left /= rslide->downsample;
			rslide->bounds.top /= rslide->downsample;
			rslide->bounds.width /= rslide->downsample;
			rslide->bounds.height /= rslide->downsample;

			/* Clip against image size.
			 */
			image.left = 0;
			image.top = 0;
			image.width = w;
			image.height = h;
			vips_rect_intersectrect( &rslide->bounds, &image, 
				&rslide->bounds );

			/* If we've clipped to nothing, ignore bounds.
			 */
			if( vips_rect_isempty( &rslide->bounds ) )
				rslide->autocrop = FALSE;
		}
		if( rslide->autocrop ) {
			w = rslide->bounds.width;
			h = rslide->bounds.height;
		}
	}

	rslide->bg = 0xffffff;
	if( (background = openslide_get_property_value( rslide->osr,
		OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR )) )
		rslide->bg = strtoul( background, NULL, 16 );

	if( w <= 0 || 
		h <= 0 || 
		rslide->downsample < 0 ) {
		vips_error( "openslide2vips", _( "getting dimensions: %s" ),
			openslide_get_error( rslide->osr ) );
		return( NULL );
	}
	if( w > INT_MAX || 
		h > INT_MAX ) {
		vips_error( "openslide2vips",
			"%s", _( "image dimensions overflow int" ) );
		return( NULL );
	}

	if( !rslide->autocrop ) {
		rslide->bounds.left = 0;
		rslide->bounds.top = 0;
		rslide->bounds.width = w;
		rslide->bounds.height = h;
	}

	vips_image_init_fields( out, w, h, 4, VIPS_FORMAT_UCHAR,
		VIPS_CODING_NONE, VIPS_INTERPRETATION_RGB, 1.0, 1.0 );

	for( properties = openslide_get_property_names( rslide->osr );
		*properties != NULL; properties++ )
		vips_image_set_string( out, *properties,
			openslide_get_property_value( rslide->osr,
			*properties ) );

	associated_names = g_strjoinv( ", ", (char **)
		openslide_get_associated_image_names( rslide->osr ) );
	vips_image_set_string( out, 
		"slide-associated-images", associated_names );
	VIPS_FREE( associated_names );

	return( rslide );
}
Example #19
0
static Read *
read_new( const char *filename, VipsImage *im, 
	gboolean all_frames, const char *density, int page )
{
	Read *read;
	static int inited = 0;

	if( !inited ) {
#ifdef HAVE_MAGICKCOREGENESIS
		MagickCoreGenesis( vips_get_argv0(), MagickFalse );
#else /*!HAVE_MAGICKCOREGENESIS*/
		InitializeMagick( "" );
#endif /*HAVE_MAGICKCOREGENESIS*/
		inited = 1;
	}

	if( !(read = VIPS_NEW( im, Read )) )
		return( NULL );
	read->filename = filename ? g_strdup( filename ) : NULL;
	read->all_frames = all_frames;
	read->page = page;
	read->im = im;
	read->image = NULL;
	read->image_info = CloneImageInfo( NULL );
	GetExceptionInfo( &read->exception );
	read->n_frames = 0;
	read->frames = NULL;
	read->frame_height = 0;
	read->lock = vips_g_mutex_new();

	g_signal_connect( im, "close", G_CALLBACK( read_close ), read );

	if( !read->image_info ) 
		return( NULL );

	if( filename ) 
		vips_strncpy( read->image_info->filename, 
			filename, MaxTextExtent );

	/* Canvas resolution for rendering vector formats like SVG.
	 */
	VIPS_SETSTR( read->image_info->density, density );

#ifdef HAVE_SETIMAGEOPTION
	/* When reading DICOM images, we want to ignore any
	 * window_center/_width setting, since it may put pixels outside the
	 * 0-65535 range and lose data. 
	 *
	 * These window settings are attached as vips metadata, so our caller
	 * can interpret them if it wants.
	 */
  	SetImageOption( read->image_info, "dcm:display-range", "reset" );
#endif /*HAVE_SETIMAGEOPTION*/

	if( !all_frames ) {
#ifdef HAVE_NUMBER_SCENES 
		 /* I can't find docs for these fields, but this seems to work.
		  */
		char page[256];

		read->image_info->scene = read->page;
		read->image_info->number_scenes = 1;

		/* Some IMs must have the string version set as well.
		 */
		vips_snprintf( page, 256, "%d", read->page );
		read->image_info->scenes = strdup( page );
#else /*!HAVE_NUMBER_SCENES*/
		/* This works with GM 1.2.31 and probably others.
		 */
		read->image_info->subimage = read->page;
		read->image_info->subrange = 1;
#endif
	}

#ifdef DEBUG
	printf( "magick2vips: read_new: %s\n", read->filename );
#endif /*DEBUG*/

	return( read );
}
Example #20
0
/* Generate code for a section of the mask. first is the index we start
 * at, we set last to the index of the last one we use before we run 
 * out of intermediates / constants / parameters / sources or mask
 * coefficients.
 *
 * 0 for success, -1 on error.
 */
static int
vips_reducev_compile_section( VipsReducev *reducev, Pass *pass, gboolean first )
{
	VipsVector *v;
	int i;

#ifdef DEBUG_COMPILE
	printf( "starting pass %d\n", pass->first ); 
#endif /*DEBUG_COMPILE*/

	pass->vector = v = vips_vector_new( "reducev", 1 );

	/* We have two destinations: the final output image (8-bit) and the
	 * intermediate buffer if this is not the final pass (16-bit).
	 */
	pass->d2 = vips_vector_destination( v, "d2", 2 );

	/* "r" is the array of sums from the previous pass (if any).
	 */
	pass->r = vips_vector_source_name( v, "r", 2 );

	/* The value we fetch from the image, the accumulated sum.
	 */
	TEMP( "value", 2 );
	TEMP( "sum", 2 );

	/* Init the sum. If this is the first pass, it's a constant. If this
	 * is a later pass, we have to init the sum from the result 
	 * of the previous pass. 
	 */
	if( first ) {
		char c0[256];

		CONST( c0, 0, 2 );
		ASM2( "loadpw", "sum", c0 );
	}
	else 
		ASM2( "loadw", "sum", "r" );

	for( i = pass->first; i < reducev->n_point; i++ ) {
		char source[256];
		char coeff[256];

		SCANLINE( source, i, 1 );

		/* This mask coefficient.
		 */
		vips_snprintf( coeff, 256, "p%d", i );
		pass->p[pass->n_param] = PARAM( coeff, 2 );
		pass->n_param += 1;
		if( pass->n_param >= MAX_PARAM )
			return( -1 );

		/* Mask coefficients are 2.6 bits fixed point. We need to hold
		 * about -0.5 to 1.0, so -2 to +1.999 is as close as we can
		 * get. 
		 *
		 * We need a signed multiply, so the image pixel needs to
		 * become a signed 16-bit value. We know only the bottom 8 bits
		 * of the image and coefficient are interesting, so we can take
		 * the bottom bits of a 16x16->32 multiply. 
		 *
		 * We accumulate the signed 16-bit result in sum.
		 */
		ASM2( "convubw", "value", source );
		ASM3( "mullw", "value", "value", coeff );
		ASM3( "addssw", "sum", "sum", "value" );

		/* We've used this coeff.
		 */
		pass->last = i;

		if( vips_vector_full( v ) )
			break;

		/* orc 0.4.24 and earlier hate more than about five lines at
		 * once :( 
		 */
		if( i - pass->first > 3 )
			break;
	}

	/* If this is the end of the mask, we write the 8-bit result to the
	 * image, otherwise write the 16-bit intermediate to our temp buffer. 
	 */
	if( pass->last >= reducev->n_point - 1 ) {
		char c32[256];
		char c6[256];
		char c0[256];
		char c255[256];

		CONST( c32, 32, 2 );
		ASM3( "addw", "sum", "sum", c32 );
		CONST( c6, 6, 2 );
		ASM3( "shrsw", "sum", "sum", c6 );

		/* You'd think "convsuswb", convert signed 16-bit to unsigned
		 * 8-bit with saturation, would be quicker, but it's a lot
		 * slower.
		 */
		CONST( c0, 0, 2 );
		ASM3( "maxsw", "sum", c0, "sum" ); 
		CONST( c255, 255, 2 );
		ASM3( "minsw", "sum", c255, "sum" ); 

		ASM2( "convwb", "d1", "sum" );
	}
	else 
		ASM2( "copyw", "d2", "sum" );

	if( !vips_vector_compile( v ) ) 
		return( -1 );

#ifdef DEBUG_COMPILE
	printf( "done coeffs %d to %d\n", pass->first, pass->last );
	vips_vector_print( v );
#endif /*DEBUG_COMPILE*/

	return( 0 );
}
Example #21
0
/**
 * vips_init:
 * @argv0: name of application
 *
 * vips_init() starts up the world of VIPS. You should call this on
 * program startup before using any other VIPS operations. If you do not call
 * vips_init(), VIPS will call it for you when you use your first VIPS 
 * operation, but
 * it may not be able to get hold of @argv0 and VIPS may therefore be unable
 * to find its data files. It is much better to call this function yourself.
 *
 * vips_init() does approximately the following:
 *
 * <itemizedlist>
 *   <listitem> 
 *     <para>initialises any libraries that VIPS is using, including GObject
 *     and the threading system, if neccessary</para>
 *   </listitem>
 *   <listitem> 
 *     <para>guesses where the VIPS data files are and sets up
 *     internationalisation --- see vips_guess_prefix()
 *     </para>
 *   </listitem>
 *   <listitem> 
 *     <para>creates the main vips types, including VipsImage and friends
 *     </para>
 *   </listitem>
 *   <listitem> 
 *     <para>loads any plugins from $libdir/vips-x.y, where x and y are the
 *     major and minor version numbers for this VIPS.
 *     </para>
 *   </listitem>
 * </itemizedlist>
 *
 * Example:
 *
 * |[
 * int main( int argc, char **argv )
 * {
 *   if( vips_init( argv[0] ) )
 *     vips_error_exit( "unable to start VIPS" );
 *
 *   vips_shutdown();
 *
 *   return( 0 );
 * }
 * ]|
 *
 * See also: vips_shutdown(), vips_get_option_group(), vips_version(), 
 * vips_guess_prefix(), vips_guess_libdir().
 *
 * Returns: 0 on success, -1 otherwise
 */
int
vips_init( const char *argv0 )
{
	extern GType vips_system_get_type( void );

	static gboolean started = FALSE;
	static gboolean done = FALSE;
	char *prgname;
	const char *prefix;
	const char *libdir;
	char name[256];

	/* Two stage done handling: 'done' means we've completed, 'started'
	 * means we're currently initialising. Use this to prevent recursive
	 * invocation.
	 */
	if( done )
		/* Called more than once, we succeeded, just return OK.
		 */
		return( 0 );
	if( started ) 
		/* Recursive invocation, something has broken horribly.
		 * Hopefully the first init will handle it.
		 */
		return( 0 );
	started = TRUE;

#ifdef NEED_TYPE_INIT
	/* Before glib 2.36 you have to call this on startup.
	 */
	g_type_init();
#endif /*NEED_TYPE_INIT*/

	/* Older glibs need this.
	 */
#ifndef HAVE_THREAD_NEW
	if( !g_thread_supported() ) 
		g_thread_init( NULL );
#endif 

	if( !vips__global_lock )
		vips__global_lock = vips_g_mutex_new();

	VIPS_SETSTR( vips__argv0, argv0 );

	prgname = g_path_get_basename( argv0 );
	g_set_prgname( prgname );
	g_free( prgname );

	/* Try to discover our prefix. 
	 */
	if( !(prefix = vips_guess_prefix( argv0, "VIPSHOME" )) || 
		!(libdir = vips_guess_libdir( argv0, "VIPSHOME" )) ) 
		return( -1 );

	/* Get i18n .mo files from $VIPSHOME/share/locale/.
	 */
	vips_snprintf( name, 256,
		"%s" G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S "locale",
		prefix );
	bindtextdomain( GETTEXT_PACKAGE, name );
	bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );

	/* Default info setting from env.
	 */
	if( g_getenv( "IM_INFO" ) ) 
		vips__info = 1;

	/* Register base vips types.
	 */
	(void) vips_image_get_type();
	(void) vips_region_get_type();
	vips__meta_init_types();
	vips__interpolate_init();
	im__format_init();

	/* Start up operator cache.
	 */
	vips__cache_init();

	/* Start up packages.
	 */
	(void) vips_system_get_type();
	vips_arithmetic_operation_init();
	vips_conversion_operation_init();
	vips_create_operation_init();
	vips_foreign_operation_init();
	vips_resample_operation_init();
	vips_colour_operation_init();
	vips_histogram_operation_init();
	vips_convolution_operation_init();

	/* Load up any plugins in the vips libdir. We don't error on failure,
	 * it's too annoying to have VIPS refuse to start because of a broken
	 * plugin.
	 */
	if( im_load_plugins( "%s/vips-%d.%d", 
		libdir, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION ) ) {
		vips_warn( "vips_init", "%s", vips_error_buffer() );
		vips_error_clear();
	}

	/* Also load from libdir. This is old and slightly broken behaviour
	 * :-( kept for back compat convenience.
	 */
	if( im_load_plugins( "%s", libdir ) ) {
		vips_warn( "vips_init", "%s", vips_error_buffer() );
		vips_error_clear();
	}

	/* Build classes which wrap old vips7 operations.
	 */
	vips__init_wrap7_classes();

	/* Start up the buffer cache.
	 */
	vips__buffer_init();

	/* Get the run-time compiler going.
	 */
	vips_vector_init();

	/* Register vips_shutdown(). This may well not get called and many
	 * platforms don't support it anyway.
	 */
#ifdef HAVE_ATEXIT
	atexit( vips_shutdown );
#endif /*HAVE_ATEXIT*/

	done = TRUE;

	return( 0 );
}
Example #22
0
int
vips_init( const char *argv0 )
{
	extern GType vips_system_get_type( void );

	static gboolean started = FALSE;
	static gboolean done = FALSE;
	char *prgname;
	const char *prefix;
	const char *libdir;
	char name[256];

	/* Two stage done handling: 'done' means we've completed, 'started'
	 * means we're currently initialising. Use this to prevent recursive
	 * invocation.
	 */
	if( done )
		/* Called more than once, we succeeded, just return OK.
		 */
		return( 0 );
	if( started ) 
		/* Recursive invocation, something has broken horribly.
		 * Hopefully the first init will handle it.
		 */
		return( 0 );
	started = TRUE;

#ifdef HAVE_TYPE_INIT
	/* Before glib 2.36 you have to call this on startup.
	 */
	g_type_init();
#endif /*HAVE_TYPE_INIT*/

	/* Older glibs need this.
	 */
#ifndef HAVE_THREAD_NEW
	if( !g_thread_supported() ) 
		g_thread_init( NULL );
#endif 

	/* This does an unsynchronised static hash table init on first call --
	 * we have to make sure we do this single-threaded. See: 
	 * https://github.com/openslide/openslide/issues/161
	 */
	(void) g_get_language_names(); 

	if( !vips__global_lock )
		vips__global_lock = vips_g_mutex_new();

	VIPS_SETSTR( vips__argv0, argv0 );

	prgname = g_path_get_basename( argv0 );
	g_set_prgname( prgname );
	g_free( prgname );

	vips__thread_profile_attach( "main" );

	/* We can't do VIPS_GATE_START() until command-line processing
	 * happens, since vips__thread_profile may not be set yet. Call
	 * directly. 
	 */
	vips__thread_gate_start( "init: main" ); 
	vips__thread_gate_start( "init: startup" ); 

	/* Try to discover our prefix. 
	 */
	if( !(prefix = vips_guess_prefix( argv0, "VIPSHOME" )) || 
		!(libdir = vips_guess_libdir( argv0, "VIPSHOME" )) ) 
		return( -1 );

	/* Get i18n .mo files from $VIPSHOME/share/locale/.
	 */
	vips_snprintf( name, 256,
		"%s" G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S "locale",
		prefix );
	bindtextdomain( GETTEXT_PACKAGE, name );
	bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );

	/* Default various settings from env.
	 */
	if( g_getenv( "VIPS_INFO" ) || 
		g_getenv( "IM_INFO" ) ) 
		vips_info_set( TRUE );
	if( g_getenv( "VIPS_TRACE" ) )
		vips_cache_set_trace( TRUE );

	/* Register base vips types.
	 */
	(void) vips_image_get_type();
	(void) vips_region_get_type();
	vips__meta_init_types();
	vips__interpolate_init();
	im__format_init();

	/* Start up operator cache.
	 */
	vips__cache_init();

	/* Start up packages.
	 */
	(void) vips_system_get_type();
	vips_arithmetic_operation_init();
	vips_conversion_operation_init();
	vips_create_operation_init();
	vips_foreign_operation_init();
	vips_resample_operation_init();
	vips_colour_operation_init();
	vips_histogram_operation_init();
	vips_convolution_operation_init();
	vips_freqfilt_operation_init();
	vips_morphology_operation_init();
	vips_draw_operation_init();
	vips_mosaicing_operation_init();

	/* Load any vips8 plugins from the vips libdir. Keep going, even if
	 * some plugins fail to load. 
	 */
	(void) vips_load_plugins( "%s/vips-plugins-%d.%d", 
		libdir, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION );

	/* Load up any vips7 plugins in the vips libdir. We don't error on 
	 * failure, it's too annoying to have VIPS refuse to start because of 
	 * a broken plugin.
	 */
	if( im_load_plugins( "%s/vips-%d.%d", 
		libdir, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION ) ) {
		vips_warn( "vips_init", "%s", vips_error_buffer() );
		vips_error_clear();
	}

	/* Also load from libdir. This is old and slightly broken behaviour
	 * :-( kept for back compat convenience.
	 */
	if( im_load_plugins( "%s", libdir ) ) {
		vips_warn( "vips_init", "%s", vips_error_buffer() );
		vips_error_clear();
	}

	/* Start up the buffer cache.
	 */
	vips__buffer_init();

	/* Get the run-time compiler going.
	 */
	vips_vector_init();

#ifdef HAVE_GSF
	/* Use this for structured file write.
	 */
	gsf_init();
#endif /*HAVE_GSF*/

	/* Register vips_shutdown(). This may well not get called and many
	 * platforms don't support it anyway.
	 */
#ifdef HAVE_ATEXIT
	atexit( vips_shutdown );
#endif /*HAVE_ATEXIT*/

#ifdef DEBUG_LEAK
	vips__image_pixels_quark = 
		g_quark_from_static_string( "vips-image-pixels" ); 
#endif /*DEBUG_LEAK*/

	done = TRUE;

	vips__thread_gate_stop( "init: startup" ); 

	return( 0 );
}