/* Define built-in VIPS types. * * J. Cupitt, 8/4/93. * * Modified: * 21/5/07 * - any length vector (Tom) * 23/8/10 * - add IM_TYPE_RW flag for im__rw_image */ /* This file is part of VIPS. VIPS is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk */ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ #include #include #include #include #include #include #include #include /* String containing each of the characters which can be used within a * single command line argument to separate the elements of a vector. */ #define VEC_SEPS " " /* Init function for input displays. Just a stub nowadays. */ static int input_display_init( im_object *obj, char *str ) { *obj = NULL; return( 0 ); } /* Input display type. */ im_type_desc im__input_display = { IM_TYPE_DISPLAY, /* It's a display */ 0, /* No storage needed */ IM_TYPE_ARG, /* It requires a command-line arg */ input_display_init, /* Init function */ NULL /* Destroy function */ }; /* Output display type. */ im_type_desc im__output_display = { IM_TYPE_DISPLAY, /* It's a display */ sizeof( void * ), /* Memory to allocate */ IM_TYPE_OUTPUT, /* Output object */ NULL, /* Init function */ NULL /* Destroy function */ }; /* Init function for input images. */ static int input_image_init( im_object *obj, char *str ) { IMAGE **im = (IMAGE **) obj; return( !(*im = vips__deprecated_open_read( str, FALSE )) ); } /* Input image type. */ im_type_desc im__input_image = { IM_TYPE_IMAGE, /* It's an image */ 0, /* No storage needed */ IM_TYPE_ARG, /* It requires a command-line arg */ (im_init_obj_fn) input_image_init,/* Init function */ (im_dest_obj_fn) im_close /* Destroy function */ }; /* Init function for output images. */ static int output_image_init( im_object *obj, char *str ) { IMAGE **im = (IMAGE **) obj; return( !(*im = vips__deprecated_open_write( str )) ); } /* Output image type. */ im_type_desc im__output_image = { IM_TYPE_IMAGE, /* It's an image */ 0, /* No storage to be allocated */ IM_TYPE_OUTPUT | IM_TYPE_ARG, /* Flags! */ (im_init_obj_fn) output_image_init,/* Init function */ (im_dest_obj_fn) im_close /* Destroy function */ }; /* Init function for RW images. */ static int rw_image_init( im_object *obj, char *str ) { IMAGE **im = (IMAGE **) obj; return( !(*im = im_open( str, "rw" )) ); } /* RW image type. */ im_type_desc im__rw_image = { IM_TYPE_IMAGE, /* It's an image */ 0, /* No storage to be allocated */ IM_TYPE_ARG | IM_TYPE_RW, /* Read-write object, needs an arg */ (im_init_obj_fn) rw_image_init, /* Init function */ (im_dest_obj_fn) im_close /* Destroy function */ }; /* im_imagevec_object destroy function. */ static int imagevec_dest( im_object obj ) { im_imagevec_object *iv = obj; if( iv->vec ) { int i; for( i = 0; i < iv->n; i++ ) if( iv->vec[i] ) { im_close( iv->vec[i] ); iv->vec[i] = NULL; } g_free( iv->vec ); iv->vec = NULL; iv->n = 0; } return( 0 ); } /* Init function for imagevec input. */ static int input_imagevec_init( im_object *obj, char *str ) { im_imagevec_object *iv = *obj; char **strv; int nargs; int i; strv = g_strsplit( str, VEC_SEPS, -1 ); nargs = g_strv_length( strv ); if( !(iv->vec = VIPS_ARRAY( NULL, nargs, IMAGE * )) ) { g_strfreev( strv ); return( -1 ); } iv->n = nargs; /* Must NULL them out in case we fail halfway though opening them all. */ for( i = 0; i < nargs; i++ ) iv->vec[i] = NULL; for( i = 0; i < nargs; i++ ) if( !(iv->vec[i] = im_open( strv[i], "rd" )) ) { g_strfreev( strv ); return( -1 ); } g_strfreev( strv ); return( 0 ); } /* Input image vector type. */ im_type_desc im__input_imagevec = { IM_TYPE_IMAGEVEC, /* It's an array of IMAGE */ sizeof( im_imagevec_object ), /* Memory to allocate in vec build */ IM_TYPE_ARG, /* It requires a command-line arg */ input_imagevec_init, /* Init function */ imagevec_dest /* Destroy function */ }; /* Init function for masks. "str" can be NULL for output masks. */ static int mask_init( im_object *obj, char *str ) { im_mask_object *mo = *obj; /* Install string, clear mask. */ if( str && !(mo->name = im_strdup( NULL, str )) ) return( -1 ); mo->mask = NULL; return( 0 ); } /* Init function for input dmasks. As above, but read in the mask. */ static int dmask_init( im_object *obj, char *str ) { im_mask_object *mo = *obj; if( mask_init( obj, str ) ) return( -1 ); if( !(mo->mask = im_read_dmask( str )) ) return( -1 ); return( 0 ); } /* Init function for input imasks. */ static int imask_init( im_object *obj, char *str ) { im_mask_object *mo = *obj; if( mask_init( obj, str ) ) return( -1 ); if( !(mo->mask = im_read_imask( str )) ) return( -1 ); return( 0 ); } /* DOUBLEMASK destroy function. */ static int dmask_dest( im_object obj ) { im_mask_object *mo = obj; VIPS_FREE( mo->name ); VIPS_FREEF( im_free_dmask, mo->mask ); return( 0 ); } /* INTMASK destroy function. */ static int imask_dest( im_object obj ) { im_mask_object *mo = obj; VIPS_FREE( mo->name ); VIPS_FREEF( im_free_imask, mo->mask ); return( 0 ); } /* As above, but save the mask first. */ static int save_dmask_dest( im_object obj ) { im_mask_object *mo = obj; if( mo->mask && im_write_dmask( mo->mask ) ) return( -1 ); return( dmask_dest( obj ) ); } /* As above, but save the mask first. */ static int save_imask_dest( im_object obj ) { im_mask_object *mo = obj; if( mo->mask && im_write_imask( mo->mask ) ) return( -1 ); return( imask_dest( obj ) ); } /* Output dmask type. */ im_type_desc im__output_dmask = { IM_TYPE_DMASK, /* It's a mask */ sizeof( im_mask_object ), /* Storage for mask object */ IM_TYPE_OUTPUT | IM_TYPE_ARG, /* Flags */ mask_init, /* Init function */ save_dmask_dest /* Save and destroy function */ }; /* Input dmask type. */ im_type_desc im__input_dmask = { IM_TYPE_DMASK, /* It's a mask */ sizeof( im_mask_object ), /* Storage for mask object */ IM_TYPE_ARG, /* It requires a command-line arg */ dmask_init, /* Init function */ dmask_dest /* Destroy function */ }; /* Output imask type. */ im_type_desc im__output_imask = { IM_TYPE_IMASK, /* It's a mask */ sizeof( im_mask_object ), /* Storage for mask object */ IM_TYPE_OUTPUT | IM_TYPE_ARG, /* Flags */ mask_init, /* Init function */ save_imask_dest /* Save and destroy function */ }; /* Input imask type. */ im_type_desc im__input_imask = { IM_TYPE_IMASK, /* It's a mask */ sizeof( im_mask_object ), /* Storage for mask object */ IM_TYPE_ARG, /* It requires a command-line arg */ imask_init, /* Init function */ imask_dest /* Destroy function */ }; /* Output dmask to screen type. Set a `print' function to get actual output. * Used for things like "stats". */ im_type_desc im__output_dmask_screen = { IM_TYPE_DMASK, /* It's a mask */ sizeof( im_mask_object ), /* Storage for mask object */ IM_TYPE_OUTPUT, /* It's an output argument */ mask_init, /* Init function */ dmask_dest /* Destroy function */ }; /* Init function for double input. */ static int input_double_init( im_object *obj, char *str ) { double *d = (double *) *obj; *d = g_ascii_strtod( str, NULL ); return( 0 ); } /* Input double type. */ im_type_desc im__input_double = { IM_TYPE_DOUBLE, /* It's a double */ sizeof( double ), /* Memory to allocate */ IM_TYPE_ARG, /* It requires a command-line arg */ input_double_init, /* Init function */ NULL /* Destroy function */ }; /* im_doublevec_object destroy function. */ static int doublevec_dest( im_object obj ) { im_doublevec_object *dv = obj; if( dv->vec ) { g_free( dv->vec ); dv->vec = NULL; dv->n = 0; } return( 0 ); } /* Init function for doublevec input. */ static int input_doublevec_init( im_object *obj, char *str ) { im_doublevec_object *dv = *obj; char **strv; int nargs; int i; strv = g_strsplit( str, VEC_SEPS, -1 ); nargs = g_strv_length( strv ); if( !(dv->vec = VIPS_ARRAY( NULL, nargs, double )) ) { g_strfreev( strv ); return( -1 ); } dv->n = nargs; for( i = 0; i < nargs; i++ ) { dv->vec[i] = g_ascii_strtod( strv[i], NULL ); if( errno ) { vips_error_system( errno, "input_doublevec_init", _( "bad double \"%s\"" ), strv[i] ); g_strfreev( strv ); return( -1 ); } } g_strfreev( strv ); return( 0 ); } /* Input double vector type. */ im_type_desc im__input_doublevec = { IM_TYPE_DOUBLEVEC, /* It's an array of double */ sizeof( im_doublevec_object ), /* Memory to allocate in vec build */ IM_TYPE_ARG, /* It requires a command-line arg */ input_doublevec_init, /* Init function */ doublevec_dest /* Destroy function */ }; /* Print function for doublevec output. */ int im__dvprint( im_object obj ) { im_doublevec_object *dv = obj; int i; for( i = 0; i < dv->n; i++ ) printf( "%G ", dv->vec[i] ); printf( "\n" ); return( 0 ); } /* Output double vector type. */ im_type_desc im__output_doublevec = { IM_TYPE_DOUBLEVEC, /* It's an array of double */ sizeof( im_doublevec_object ), /* Memory to allocate in vec build */ IM_TYPE_OUTPUT, /* Output type */ NULL, /* Init function */ doublevec_dest /* Destroy function */ }; /* im_intvec_object destroy function. */ static int intvec_dest( im_object obj ) { im_intvec_object *iv = obj; if( iv->vec ) { g_free( iv->vec ); iv->vec = NULL; iv->n = 0; } return( 0 ); } /* Init function for intvec input. */ static int input_intvec_init( im_object *obj, char *str ) { im_intvec_object *iv = *obj; char **strv; int nargs; int i; strv = g_strsplit( str, VEC_SEPS, -1 ); nargs = g_strv_length( strv ); if( !(iv->vec = VIPS_ARRAY( NULL, nargs, int )) ) { g_strfreev( strv ); return( -1 ); } iv->n = nargs; for( i = 0; i < nargs; i++ ) { long int val= strtol( strv[i], NULL, 10 ); if( errno ) { vips_error_system( errno, "input_intvec_init", _( "bad integer \"%s\"" ), strv[i] ); g_strfreev( strv ); return( -1 ); } if( INT_MAX < val || INT_MIN > val ) { vips_error( "input_intvec_init", "%ld overflows integer type", val ); } iv->vec[i] = (int) val; } g_strfreev( strv ); return( 0 ); } /* Input int vector type. */ im_type_desc im__input_intvec = { IM_TYPE_INTVEC, /* It's an array of int */ sizeof( im_intvec_object ), /* Memory to allocate in vec build */ IM_TYPE_ARG, /* It requires a command-line arg */ input_intvec_init, /* Init function */ intvec_dest /* Destroy function */ }; /* Print function for intvec output. */ int im__ivprint( im_object obj ) { im_intvec_object *iv = obj; int i; for( i = 0; i < iv->n; i++ ) printf( "%d ", iv->vec[i] ); printf( "\n" ); return( 0 ); } /* Output int vector type. */ im_type_desc im__output_intvec = { IM_TYPE_INTVEC, /* It's an array of int */ sizeof( im_intvec_object ), /* Memory to allocate in vec build */ IM_TYPE_OUTPUT, /* Output arg */ (im_init_obj_fn)NULL, /* Init function */ (im_dest_obj_fn)intvec_dest /* Destroy function */ }; /* Init function for int input. */ static int input_int_init( im_object *obj, char *str ) { int *i = (int *) *obj; if( sscanf( str, "%d", i ) != 1 ) { vips_error( "input_int", "%s", _( "bad format" ) ); return( -1 ); } return( 0 ); } /* Input int type. */ im_type_desc im__input_int = { IM_TYPE_INT, /* It's an int */ sizeof( int ), /* Memory to allocate */ IM_TYPE_ARG, /* It requires a command-line arg */ input_int_init, /* Init function */ NULL /* Destroy function */ }; /* Init function for string input. */ static int input_string_init( im_object *obj, char *str ) { if( !(*obj = (im_object) im_strdup( NULL, str )) ) return( -1 ); return( 0 ); } /* Input string type. */ im_type_desc im__input_string = { IM_TYPE_STRING, /* It's a string */ 0, /* Memory to allocate */ IM_TYPE_ARG, /* It requires a command-line arg */ input_string_init, /* Init function */ vips_free /* Destroy function */ }; /* Output string type. */ im_type_desc im__output_string = { IM_TYPE_STRING, /* It's a string */ 0, /* Memory to allocate */ IM_TYPE_OUTPUT, /* It's an output argument */ NULL, /* Init function */ vips_free /* Destroy function */ }; /* Output double type. */ im_type_desc im__output_double = { IM_TYPE_DOUBLE, /* It's a double */ sizeof( double ), /* Memory to allocate */ IM_TYPE_OUTPUT, /* It's an output argument */ NULL, /* Init function */ NULL /* Destroy function */ }; /* Output complex type. */ im_type_desc im__output_complex = { IM_TYPE_COMPLEX, /* It's a complex */ 2 * sizeof( double ), /* Memory to allocate */ IM_TYPE_OUTPUT, /* It's an output argument */ NULL, /* Init function */ NULL /* Destroy function */ }; /* Output int type. */ im_type_desc im__output_int = { IM_TYPE_INT, /* It's an int */ sizeof( int ), /* Memory to allocate */ IM_TYPE_OUTPUT, /* It's an output argument */ NULL, /* Init function */ NULL /* Destroy function */ }; /* Print function for int output. */ int im__iprint( im_object obj ) { int *i = (int *) obj; printf( "%d\n", *i ); return( 0 ); } /* Print function for string output. */ int im__sprint( im_object obj ) { char *s = (char *) obj; printf( "%s\n", s ); return( 0 ); } /* Print function for double output. */ int im__dprint( im_object obj ) { double *d = (double *) obj; printf( "%G\n", *d ); return( 0 ); } /* Print function for complex output. */ int im__cprint( im_object obj ) { double *d = (double *) obj; printf( "%G %G\n", d[0], d[1] ); return( 0 ); } /* Statistics to stdout. */ int im__dmsprint( im_object obj ) { DOUBLEMASK *mask = ((im_mask_object *) obj)->mask; double *row; int i, j; /* Print statistics band stats eg: 2 bands:b 0,1 */ printf( "band minimum maximum sum " "sum^2 mean deviation\n" ); for( j = 0; j < mask->ysize; j++ ) { row = mask->coeff + j * mask->xsize; if( j == 0 ) printf( "all" ); else printf( "%2d ", j ); for( i = 0; i < 6; i++ ) printf( "%12g", row[i] ); printf( "\n" ); } return( 0 ); } /* GValue */ /* Init function for input gvalue. Just make a string ... will get cast to * whatever later. */ static int input_gvalue_init( im_object *obj, char *str ) { GValue *value = *obj; g_value_init( value, G_TYPE_STRING ); g_value_set_string( value, str ); return( 0 ); } static int gvalue_free( im_object obj ) { GValue *value = obj; /* If it's just zeros (built but not used) we'll get an error if we * unset(). */ if( G_IS_VALUE( value ) ) g_value_unset( value ); return( 0 ); } /* Input GValue type. */ im_type_desc im__input_gvalue = { IM_TYPE_GVALUE, sizeof( GValue ), /* Need some storage */ IM_TYPE_ARG, /* It requires a command-line arg */ (im_init_obj_fn) input_gvalue_init, /* Init function */ (im_dest_obj_fn) gvalue_free /* Destroy function */ }; int im__gprint( im_object obj ) { GValue *value = obj; char *str_value; str_value = g_strdup_value_contents( value ); printf( "%s\n", str_value ); g_free( str_value ); return( 0 ); } /* Init function for output gvalue. Just init to zero. */ static int output_gvalue_init( im_object *obj ) { GValue *value = *obj; memset( value, 0, sizeof( GValue ) ); return( 0 ); } im_type_desc im__output_gvalue = { IM_TYPE_GVALUE, sizeof( GValue ), /* Need some storage */ IM_TYPE_OUTPUT, /* No arg needed (just print) */ (im_init_obj_fn) output_gvalue_init, /* Init function */ (im_dest_obj_fn) gvalue_free /* Destroy function */ }; /* Init function for input interpolate. * * This is used as a helper function by the C++ interface, so amke it public. */ int vips__input_interpolate_init( im_object *obj, char *str ) { GType type = g_type_from_name( "VipsInterpolate" ); VipsObjectClass *class = VIPS_OBJECT_CLASS( g_type_class_ref( type ) ); VipsObject *object; g_assert( class ); if( !(object = vips_object_new_from_string( class, str )) ) return( -1 ); if( vips_object_build( object ) ) { g_object_unref( object ); return( -1 ); } *obj = object; return( 0 ); } static int input_interpolate_dest( im_object obj ) { g_object_unref( (GObject *) obj ); return( 0 ); } im_type_desc im__input_interpolate = { IM_TYPE_INTERPOLATE, 0, /* No storage required */ IM_TYPE_ARG, /* It requires a command-line arg */ vips__input_interpolate_init, /* Init function */ input_interpolate_dest /* Destroy function */ };