VipsImage * im_open( const char *filename, const char *mode ) { VipsImage *image; /* Pass in a nonsense name for argv0 ... this init path is only here * for old programs which are missing an vips_init() call. We need * i18n set up before we can translate. */ if( vips_init( "giant_banana" ) ) vips_error_clear(); /* We have to go via the old VipsFormat system so we can support the * "filename:option" syntax. */ if( strcmp( mode, "r" ) == 0 || strcmp( mode, "rd" ) == 0 ) { if( !(image = vips__deprecated_open_read( filename )) ) return( NULL ); } else if( strcmp( mode, "w" ) == 0 ) { if( !(image = vips__deprecated_open_write( filename )) ) return( NULL ); } else { if( !(image = vips_image_new_mode( filename, mode )) ) return( NULL ); } return( image ); }
int main( int argc, char **argv ) { GOptionContext *context; GError *error = NULL; int i; if( vips_init( argv[0] ) ) vips_error_exit( "unable to start VIPS" ); textdomain( GETTEXT_PACKAGE ); setlocale( LC_ALL, "" ); context = g_option_context_new( _( "- thumbnail generator" ) ); g_option_context_add_main_entries( context, options, GETTEXT_PACKAGE ); g_option_context_add_group( context, vips_get_option_group() ); if( !g_option_context_parse( context, &argc, &argv, &error ) ) { if( error ) { fprintf( stderr, "%s\n", error->message ); g_error_free( error ); } vips_error_exit( "try \"%s --help\"", g_get_prgname() ); } g_option_context_free( context ); if( sscanf( thumbnail_size, "%d x %d", &thumbnail_width, &thumbnail_height ) != 2 ) { if( sscanf( thumbnail_size, "%d", &thumbnail_width ) != 1 ) vips_error_exit( "unable to parse size \"%s\" -- " "use eg. 128 or 200x300", thumbnail_size ); thumbnail_height = thumbnail_width; } for( i = 1; i < argc; i++ ) { /* Hang resources for processing this thumbnail off @process. */ VipsObject *process = VIPS_OBJECT( vips_image_new() ); if( thumbnail_process( process, argv[i] ) ) { fprintf( stderr, "%s: unable to thumbnail %s\n", argv[0], argv[i] ); fprintf( stderr, "%s", vips_error_buffer() ); vips_error_clear(); } g_object_unref( process ); } vips_shutdown(); return( 0 ); }
/* Call this before vips stuff that uses stuff we need to have inited. */ void vips_check_init( void ) { /* Pass in a nonsense name for argv0 ... this init path is only here * for old programs which are missing an vips_init() call. We need * i18n set up before we can translate. */ if( vips_init( "giant_banana" ) ) vips_error_clear(); }
/** * vips_error_g: * @error: glib error pointer * * This function sets the glib error pointer from the vips error buffer and * clears it. It's handy for returning errors to glib functions from vips. * * See also: g_set_error(). */ void vips_error_g( GError **error ) { static GQuark vips_domain = 0; if( !vips_domain ) vips_domain = g_quark_from_string( "libvips" ); g_set_error( error, vips_domain, -1, "%s", vips_error_buffer() ); vips_error_clear(); }
// just g_object_set_property(), except we allow set enum from string static void set_property( VipsObject *object, const char *name, const GValue *value ) { VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object ); GType type = G_VALUE_TYPE( value ); GParamSpec *pspec; VipsArgumentClass *argument_class; VipsArgumentInstance *argument_instance; if( vips_object_get_argument( object, name, &pspec, &argument_class, &argument_instance ) ) { g_warning( "%s", vips_error_buffer() ); vips_error_clear(); return; } if( G_IS_PARAM_SPEC_ENUM( pspec ) && type == G_TYPE_STRING ) { GType pspec_type = G_PARAM_SPEC_VALUE_TYPE( pspec ); int enum_value; GValue value2 = { 0 }; if( (enum_value = vips_enum_from_nick( object_class->nickname, pspec_type, g_value_get_string( value ) )) < 0 ) { g_warning( "%s", vips_error_buffer() ); vips_error_clear(); return; } g_value_init( &value2, pspec_type ); g_value_set_enum( &value2, enum_value ); g_object_set_property( G_OBJECT( object ), name, &value2 ); g_value_unset( &value2 ); } else g_object_set_property( G_OBJECT( object ), name, value ); }
/** * vips_error_g: * @error: glib error pointer * * This function sets the glib error pointer from the vips error buffer and * clears it. It's handy for returning errors to glib functions from vips. * * See also: g_set_error(). */ void vips_error_g( GError **error ) { static GQuark vips_domain = 0; if( !vips_domain ) vips_domain = g_quark_from_string( "libvips" ); /* glib does not expect a trailing '\n' and vips always has one. */ g_mutex_lock( vips__global_lock ); vips_buf_removec( &vips_error_buf, '\n' ); g_mutex_unlock( vips__global_lock ); g_set_error( error, vips_domain, -1, "%s", vips_error_buffer() ); vips_error_clear(); }
int main( int argc, char **argv ) { GOptionContext *context; GOptionGroup *main_group; GError *error = NULL; int i; int result; if( VIPS_INIT( argv[0] ) ) vips_error_exit( "unable to start VIPS" ); textdomain( GETTEXT_PACKAGE ); setlocale( LC_ALL, "" ); context = g_option_context_new( _( "- thumbnail generator" ) ); main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL ); g_option_group_add_entries( main_group, options ); vips_add_option_entries( main_group ); g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE ); g_option_context_set_main_group( context, main_group ); if( !g_option_context_parse( context, &argc, &argv, &error ) ) { if( error ) { fprintf( stderr, "%s\n", error->message ); g_error_free( error ); } vips_error_exit( "try \"%s --help\"", g_get_prgname() ); } g_option_context_free( context ); if( sscanf( thumbnail_size, "%d x %d", &thumbnail_width, &thumbnail_height ) != 2 ) { if( sscanf( thumbnail_size, "%d", &thumbnail_width ) != 1 ) vips_error_exit( "unable to parse size \"%s\" -- " "use eg. 128 or 200x300", thumbnail_size ); thumbnail_height = thumbnail_width; } if( rotate_image ) { #ifndef HAVE_EXIF vips_warn( "vipsthumbnail", "%s", _( "auto-rotate disabled: " "libvips built without exif support" ) ); #endif /*!HAVE_EXIF*/ } result = 0; for( i = 1; i < argc; i++ ) { /* Hang resources for processing this thumbnail off @process. */ VipsObject *process = VIPS_OBJECT( vips_image_new() ); if( thumbnail_process( process, argv[i] ) ) { fprintf( stderr, "%s: unable to thumbnail %s\n", argv[0], argv[i] ); fprintf( stderr, "%s", vips_error_buffer() ); vips_error_clear(); /* We had a conversion failure: return an error code * when we finally exit. */ result = -1; } g_object_unref( process ); } vips_shutdown(); return( result ); }
static VipsImage * thumbnail_shrink( VipsObject *process, VipsImage *in ) { VipsImage **t = (VipsImage **) vips_object_local_array( process, 10 ); VipsInterpretation interpretation = linear_processing ? VIPS_INTERPRETATION_XYZ : VIPS_INTERPRETATION_sRGB; /* TRUE if we've done the import of an ICC transform and still need to * export. */ gboolean have_imported; /* TRUE if we've premultiplied and need to unpremultiply. */ gboolean have_premultiplied; VipsBandFormat unpremultiplied_format; /* Sniff the incoming image and try to guess what the alpha max is. */ double max_alpha; double shrink; /* RAD needs special unpacking. */ if( in->Coding == VIPS_CODING_RAD ) { vips_info( "vipsthumbnail", "unpacking Rad to float" ); /* rad is scrgb. */ if( vips_rad2float( in, &t[0], NULL ) ) return( NULL ); in = t[0]; } /* Try to guess what the maximum alpha might be. */ max_alpha = 255; if( in->BandFmt == VIPS_FORMAT_USHORT ) max_alpha = 65535; /* In linear mode, we import right at the start. * * We also have to import the whole image if it's CMYK, since * vips_colourspace() (see below) doesn't know about CMYK. * * This is only going to work for images in device space. If you have * an image in PCS which also has an attached profile, strange things * will happen. */ have_imported = FALSE; if( (linear_processing || in->Type == VIPS_INTERPRETATION_CMYK) && in->Coding == VIPS_CODING_NONE && (in->BandFmt == VIPS_FORMAT_UCHAR || in->BandFmt == VIPS_FORMAT_USHORT) && (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || import_profile) ) { if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) vips_info( "vipsthumbnail", "importing with embedded profile" ); else vips_info( "vipsthumbnail", "importing with profile %s", import_profile ); if( vips_icc_import( in, &t[1], "input_profile", import_profile, "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL ) ) return( NULL ); in = t[1]; have_imported = TRUE; } /* To the processing colourspace. This will unpack LABQ as well. */ vips_info( "vipsthumbnail", "converting to processing space %s", vips_enum_nick( VIPS_TYPE_INTERPRETATION, interpretation ) ); if( vips_colourspace( in, &t[2], interpretation, NULL ) ) return( NULL ); in = t[2]; /* If there's an alpha, we have to premultiply before shrinking. See * https://github.com/jcupitt/libvips/issues/291 */ have_premultiplied = FALSE; if( in->Bands == 2 || (in->Bands == 4 && in->Type != VIPS_INTERPRETATION_CMYK) || in->Bands == 5 ) { vips_info( "vipsthumbnail", "premultiplying alpha" ); if( vips_premultiply( in, &t[3], "max_alpha", max_alpha, NULL ) ) return( NULL ); have_premultiplied = TRUE; /* vips_premultiply() makes a float image. When we * vips_unpremultiply() below, we need to cast back to the * pre-premultiply format. */ unpremultiplied_format = in->BandFmt; in = t[3]; } shrink = calculate_shrink( in ); if( vips_resize( in, &t[4], 1.0 / shrink, NULL ) ) return( NULL ); in = t[4]; if( have_premultiplied ) { vips_info( "vipsthumbnail", "unpremultiplying alpha" ); if( vips_unpremultiply( in, &t[5], "max_alpha", max_alpha, NULL ) || vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) ) return( NULL ); in = t[6]; } /* Colour management. * * If we've already imported, just export. Otherwise, we're in * device space and we need a combined import/export to transform to * the target space. */ if( have_imported ) { if( export_profile || vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { vips_info( "vipsthumbnail", "exporting to device space with a profile" ); if( vips_icc_export( in, &t[7], "output_profile", export_profile, NULL ) ) return( NULL ); in = t[7]; } else { vips_info( "vipsthumbnail", "converting to sRGB" ); if( vips_colourspace( in, &t[7], VIPS_INTERPRETATION_sRGB, NULL ) ) return( NULL ); in = t[7]; } } else if( export_profile && (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || import_profile) ) { VipsImage *out; vips_info( "vipsthumbnail", "exporting with profile %s", export_profile ); /* We first try with the embedded profile, if any, then if * that fails try again with the supplied fallback profile. */ out = NULL; if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { vips_info( "vipsthumbnail", "importing with embedded profile" ); if( vips_icc_transform( in, &t[7], export_profile, "embedded", TRUE, NULL ) ) { vips_warn( "vipsthumbnail", _( "unable to import with " "embedded profile: %s" ), vips_error_buffer() ); vips_error_clear(); } else out = t[7]; } if( !out && import_profile ) { vips_info( "vipsthumbnail", "importing with fallback profile" ); if( vips_icc_transform( in, &t[7], export_profile, "input_profile", import_profile, "embedded", FALSE, NULL ) ) return( NULL ); out = t[7]; } /* If the embedded profile failed and there's no fallback or * the fallback failed, out will still be NULL. */ if( out ) in = out; } if( delete_profile && vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { vips_info( "vipsthumbnail", "deleting profile from output image" ); if( !vips_image_remove( in, VIPS_META_ICC_NAME ) ) return( NULL ); } return( in ); }
/** * 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 ); }
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 ); }