\section{Core C API} VIPS is built on top of several other libraries, two of which, glib and gobject, are exposed at various points in the C API. You can read up on glib at the GTK+ website: \begin{verbatim} http://www.gtk.org \end{verbatim} There's also an excellent book by Matthias Warkus, \emph{The Official GNOME 2 Developer's Guide}, which covers the same material in a tutorial manner. \subsection{Startup} Before calling any VIPS function, you need to start VIPS up: \begin{verbatim} int im_init_world( const char *argv0 ); \end{verbatim} The \verb+argv0+ argument is the value of \verb+argv[0]+ your program was passed by the host operating system. VIPS uses this with \verb+im_guess_prefix()+ and \verb+im_guess_libdir()+ to try to find various VIPS data files. If you don't call this function, VIPS will call it for you the first time you use a VIPS function. But it won't be able to get the \verb+argv0+ value for you, so it may not be able to find it's data files. VIPS also offers the optional: \begin{verbatim} GOptionGroup *im_get_option_group( void ); \end{verbatim} You can use this with GOption to parse your program's command-line arguments. It adds several useful VIPS flags, including \verb+--vips-concurrency+. \fref{fg:hello} shows both these functions in use. Again, the GOption stuff is optional and just lets VIPS add some flags to your program. You do need the \verb+im_init_world()+ though. \begin{fig2} \begin{verbatim} #include #include static gboolean print_stuff; static GOptionEntry options[] = { { "print", 'p', 0, G_OPTION_ARG_NONE, &print_stuff, "print \"hello world!\"", NULL }, { NULL } }; int main( int argc, char **argv ) { GOptionContext *context; GError *error = NULL; if( im_init_world( argv[0] ) ) error_exit( "unable to start VIPS" ); context = g_option_context_new( "- my program" ); g_option_context_add_main_entries( context, options, "main" ); g_option_context_add_group( context, im_get_option_group() ); if( !g_option_context_parse( context, &argc, &argv, &error ) ) { if( error ) { fprintf( stderr, "%s\n", error->message ); g_error_free( error ); } error_exit( "try \"%s --help\"", g_get_prgname() ); } g_option_context_free( context ); if( print_stuff ) printf( "hello, world!\n" ); return( 0 ); } \end{verbatim} \caption{Hello World for VIPS} \label{fg:hello} \end{fig2} \subsection{Image descriptors} The base level of the VIPS I/O system provides \verb+IMAGE+ descriptors. An image represented by a descriptor may be an image file on disc, an area of memory that has been allocated for the image, an output file, a delayed computation, and so on. Programs need (usually) only know that they have a descriptor, they do not see many of the details. \fref{fg:image} shows the definition of the \verb+IMAGE+ descriptor. \begin{fig2} \begin{verbatim} typedef struct { /* Fields from image header. */ int Xsize; /* Pels per line */ int Ysize; /* Lines */ int Bands; /* Number of bands */ int Bbits; /* Bits per band */ int BandFmt; /* Band format */ int Coding; /* Coding type */ int Type; /* Type of file */ float XRes; /* Horizontal res in pels/mm */ float YRes; /* Vertical res in pels/mm */ int Length; /* Obsolete (unused) */ short Compression; /* Obsolete (unused) */ short Level; /* Obsolete (unused) */ int Xoffset; /* Position of origin */ int Yoffset; /* Derived fields that may be read by the user. */ char *filename; /* File name */ im_time_t *time; /* Timing for eval callback */ int kill; /* Set to non-zero to block eval */ ... and lots of other private fields used by VIPS for ... housekeeping. } IMAGE; \end{verbatim} \caption{The \texttt{IMAGE} descriptor} \label{fg:image} \end{fig2} The first set of fields simply come from the image file header: see \pref{sec:header} for a full description of all the fields. The next set are maintained for you by the VIPS I/O system. \verb+filename+ is the name of the file that this image came from. If you have attached an eval callback to this image, \verb+time+ points to a set of timing statistics which can be used by user-interfaces built on VIPS to provide feedback about the progress of evaluation --- see \pref{sec:eval}. Finally, if you set \verb+kill+ to non-zero, VIPS will block any pipelines which use this descriptor as an intermediate. See \pref{sec:block}. The remaining fields are private and are used by VIPS for housekeeping. \subsection{Header fields} \label{sec:fields} You can access header fields either directly (as \verb+im->Xsize+, for example) or programmatically with \verb+im_header_int()+ and friends. For example: \begin{verbatim} int i; im_header_int( im, "Xsize", &i ); \end{verbatim} There's also \verb+im_header_map()+ to loop over header fields, and \verb+im_header_get_type+ to test the type of fields. These functions work for image meta fields as well, see \pref{sec:meta}. \subsection{Opening and closing} \label{sec:open} Descriptors are created with \verb+im_open()+. You can also read images with the format system: see \pref{sec:format}. The two APIs are complimentary, though \verb+im_open()+ is more useful. At the command-line, try: \begin{verbatim} $ vips --list classes \end{verbatim} /noindent to see a list of all the supported file formats. \verb+im_open()+ takes a file name and a string representing the mode with which the descriptor is to be opened: \begin{verbatim} IMAGE *im_open( const char *filename, const char *mode ) \end{verbatim} The possible values for mode are: \begin{description} \item[\texttt{"r"}] The file is opened read-only. If you open a non-VIPS image, or a VIPS image written on a machine with a different byte ordering, \verb+im_open()+ will automatically convert it to native VIPS format. If the underlying file does not support random access (JPEG, for example), the entire file will be converted in memory. VIPS can read images in many file formats. You can control the details of the conversion with extra characters embedded in the filename. For example: \begin{verbatim} fred = im_open( "fred.tif:2", "r" ); \end{verbatim} \noindent will read page 2 of a multi-page TIFF. See the man pages for details. \item[\texttt{"w"}] An \verb+IMAGE+ descriptor is created which, when written to, will write pixels to disc in the specified file. Any existing file of that name is deleted. VIPS looks at the filename suffix to determine the save format. If there is no suffix, or the filename ends in \verb+".v"+, the image is written in VIPS native format. If you want to control the details of the conversion to the disc format (such as setting the Q factor for a JPEG, for example), you embed extra control characters in the filename. For example: \begin{verbatim} fred = im_open( "fred.jpg:95", "w" ); \end{verbatim} \noindent writes to \verb+fred+ will write a JPEG with Q 95. Again, see the man pages for the conversion functions for details. \item[\texttt{"t"}] As the \verb+"w"+ mode, but pels written to the descriptor will be saved in a temporary memory buffer. \item[\texttt{"p"}] This creates a special partial image. Partial images are used to join VIPS operations together, see \pref{sec:joinup}. \item[\texttt{"rw"}] As the \verb+"r"+ mode, but the image is mapped into the caller's address space read-write. This mode is only provided for the use of paintbox-style applications which need to directly modify an image. Most programs should use the \verb+"w"+ mode for image output. \end{description} If an error occurs opening the image, \verb+im_open()+ calls \verb+im_error()+ with a string describing the cause of the error and returns \verb+NULL+. \verb+im_error()+ has type \begin{verbatim} void im_error( const char *domain, const char *format, ... ) \end{verbatim} \noindent The first argument is a string giving the name of the thing that raised the error (just \verb+"im_open"+, for example). The format and subsequent arguments work exactly as \verb+printf()+. It formats the message and appends the string formed to the error log. You can get a pointer to the error text with \verb+im_error_buffer()+. \begin{verbatim} const char *im_error_buffer() \end{verbatim} \noindent Applications may display this string to give users feedback about the cause of the error. The VIPS exit function, \verb+error_exit()+, prints \verb+im_error_buffer()+ to \verb+stderr+ and terminates the program with an error code of 1. \begin{verbatim} void error_exit( const char *format, ... ) \end{verbatim} \noindent There are other functions for handling errors: see the man page for \verb+im_error()+. Descriptors are closed with \verb+im_close()+. It has type: \begin{verbatim} int im_close( IMAGE *im ) \end{verbatim} \verb+im_close()+ returns 0 on success and non-zero on error. \subsection{Examples} \label{sec:examples} As an example, \fref{fg:widthheight} will print the width and height of an image stored on disc. \begin{fig2} \begin{verbatim} #include #include int main( int argc, char **argv ) { IMAGE *im; /* Check arguments. */ if( im_init_world( argv[0] ) ) error_exit( "unable to start VIPS" ); if( argc != 2 ) error_exit( "usage: %s filename", argv[0] ); /* Open file. */ if( !(im = im_open( argv[1], "r" )) ) error_exit( "unable to open %s for input", argv[1] ); /* Process. */ printf( "width = %d, height = %d\n", im->Xsize, im->Ysize ); /* Close. */ if( im_close( im ) ) error_exit( "unable to close %s", argv[1] ); return( 0 ); } \end{verbatim} \label{fg:widthheight} \caption{Print width and height of an image} \end{fig2} To compile this example, use: \begin{verbatim} cc `pkg-config vips-7.14 \ --cflags --libs` myfunc.c \end{verbatim} As a slightly more complicated example, \fref{fg:negative} will calculate the photographic negative of an image. \begin{fig2} \begin{verbatim} #include #include int main( int argc, char **argv ) { IMAGE *in, *out; /* Check arguments. */ if( im_init_world( argv[0] ) ) error_exit( "unable to start VIPS" ); if( argc != 3 ) error_exit( "usage: %s infile outfile", argv[0] ); /* Open images for read and write, invert, update the history with our * args, and close. */ if( !(in = im_open( argv[1], "r" )) || !(out = im_open( argv[2], "w" )) || im_invert( in, out ) || im_updatehist( out, argc, argv ) || im_close( in ) || im_close( out ) ) error_exit( argv[0] ); return( 0 ); } \end{verbatim} \label{fg:negative} \caption{Find photographic negative} \end{fig2} \subsection{Metadata} \label{sec:meta} VIPS lets you attach arbitrary metadata to an IMAGE. For example, ICC profiles, EXIF tags, image history, whatever you like. VIPS will efficiently propagate metadata as images are processed (usually just by copying pointers) and will automatically save and load metadata from VIPS files (see \pref{sec:header}). A piece of metadata is a value and an identifying name. A set of convenience functions let you set and get int, double, string and blob. For example: \begin{verbatim} int im_meta_set_int( IMAGE *, const char *field, int ); int im_meta_get_int( IMAGE *, const char *field, int * ); \end{verbatim} So you can do: \begin{verbatim} if( im_meta_set_int( im, "poop", 42 ) ) return( -1 ); \end{verbatim} \noindent to create an int called \verb+"poop"+, then at some later point (possibly much, much later), in an image distantly derived from \verb+im+, you can use: \begin{verbatim} int i; if( im_meta_get_int( im, "poop", &i ) ) return( -1 ); \end{verbatim} \noindent And get the value 42 back. You can use \verb+im_meta_set()+ and \verb+im_meta_get()+ to attach arbitrary \verb+GValue+ to images. See the man page for \verb+im_meta_set()+ for full details. You can test for a field being present with \verb+im_meta_get_type()+ (you'll get \verb+G_TYPE_INT+ back for \verb+"poop"+, for example, or 0 if it is not defined for this image). \subsection{History} \label{sec:history} VIPS tracks the history of an image, that is, the sequence of operations which have led to the creation of an image. You can view a VIPS image's history with the \verb+header+ command, or with \nip{}'s \ct{View Header} menu. Whenever an application performs an action, it should append a line of shell script to the history which would perform the same action. The call to \verb+im_updatehist()+ in \fref{fg:negative} adds a line to the image history noting the invocation of this program, its arguments, and the time and date at which it was run. You may also find \verb+im_histlin()+ helpful. It has type: \begin{verbatim} void im_histlin( IMAGE *im, const char *fmt, ... ) \end{verbatim} \noindent It formats its arguments as \verb+printf()+ and appends the string formed to the image history. You read an image's history with \verb+im_history_get()+. It returns the entire history of an image, one action per line. No need to free the result. \begin{verbatim} const char * im_history_get( IMAGE *im ); \end{verbatim} \subsection{Eval callbacks} \label{sec:eval} VIPS lets you attach callbacks to image descriptors. These are functions you provide which VIPS will call when certain events occur. See \pref{sec:callback} for more detail. Eval callbacks are called repeatedly during evaluation and can be used by user-interface programs to give feedback about the progress of evaluation. \subsection{Detailed rules for descriptors} These rules are intended to answer awkward questions. \begin{enumerate} \item You can output to a descriptor only once. \item You can use a descriptor as an input many times. \item You can only output to a descriptor that was opened with modes \verb+"w"+, \verb+"t"+ and \verb+"p"+. \item You can only use a descriptor as input if it was opened with modes \verb+"r"+ or \verb+"rw"+. \item If you have output to a descriptor, you may subsequently use it as an input. \verb+"w"+ descriptors are automatically changed to \verb+"r"+ descriptors. If the function you are passing the descriptor to uses WIO (see \pref{sec:limit}), then \verb+"p"+ descriptors become \verb+"t"+. If the function you are passing the descriptor to uses PIO, then \verb+"p"+ descriptors are unchanged. \end{enumerate} \subsection{Automatic resource deallocation} VIPS lets you allocate resources local to an image descriptor, that is, when the descriptor is closed, all resources which were allocated local to that descriptor are automatically released for you. \subsubsection{Local image descriptors} VIPS provides a function which will open a new image local to an existing image. \verb+im_open_local()+ has type: \begin{verbatim} IMAGE *im_open_local( IMAGE *im, const char *filename, const char *mode ) \end{verbatim} It behaves exactly as \verb+im_open()+, except that you do not need to close the descriptor it returns. It will be closed automatically when its parent descriptor \verb+im+ is closed. \begin{fig2} \begin{verbatim} /* Add another image to the accumulated total. */ static int sum1( IMAGE *acc, IMAGE **in, int nin, IMAGE *out ) { IMAGE *t; if( nin == 0 ) /* All done ... copy to out. */ return( im_copy( acc, out ) ); /* Make a new intermediate, and add to it.. */ return( !(t = im_open_local( out, "sum1:1", "p" )) || im_add( acc, in[0], t ) || sum1( t, in + 1, nin - 1, out ) ); } /* Sum the array of images in[]. nin is the number of images in * in[], out is the descriptor we write the final image to. */ int total( IMAGE **in, int nin, IMAGE *out ) { /* Check that we have at least one image. */ if( nin <= 0 ) { im_error( "total", "nin should be > 0" ); return( -1 ); } /* More than 1, sum recursively. */ return( sum1( in[0], in + 1, nin - 1, out ) ); } \end{verbatim} \caption{Sum an array of images} \label{fg:addemup} \end{fig2} \fref{fg:addemup} is a function which will sum an array of images. We need never close any of the (unknown) number of intermediate images which we open. They will all be closed for us by our caller, when our caller finally closes \verb+out+. VIPS lets local images themselves have local images and automatically makes sure that all are closed in the correct order. It is very important that these intermediate images are made local to \verb+out+ rather than \verb+in+, for reasons which should become apparent in the section on combining operations below. There's also \verb+im_open_local_array()+ for when you need a lot of local descriptors, see the man page. \subsubsection{Local memory allocation} \label{sec:malloc} VIPS includes a set of functions for memory allocation local to an image descriptor. The base memory allocation function is \verb+im_malloc()+. It has type: \begin{verbatim} void *im_malloc( IMAGE *, size_t ) \end{verbatim} It operates exactly as the standard \verb+malloc()+ C library function, except that the area of memory it allocates is local to an image. If \verb+im_malloc()+ is unable to allocate memory, it returns \verb+NULL+. If you pass \verb+NULL+ instead of a valid image descriptor, then \verb+im_malloc()+ allocates memory globally and you must free it yourself at some stage. To free memory explicitly, use \verb+im_free()+: \begin{verbatim} int im_free( void * ) \end{verbatim} \noindent \verb+im_free()+ always returns 0, so you can use it as an argument to a callback. Three macros make memory allocation even easier. \verb+IM_NEW()+ allocates a new object. You give it a descriptor and a type, and it returns a pointer to enough space to hold an object of that type. It has type: \begin{verbatim} type-name *IM_NEW( IMAGE *, type-name ) \end{verbatim} The second macro, \verb+IM_ARRAY()+, is very similar, but allocates space for an array of objects. Note that, unlike the usual \verb+calloc()+ C library function, it does not initialise the array to zero. It has type: \begin{verbatim} type-name *IM_ARRAY( IMAGE *, int, type-name ) \end{verbatim} Finally, \verb+IM_NUMBER()+ returns the number of elements in an array of defined size. See the man pages for a series of examples, or see \pref{sec:number}. \subsubsection{Other local operations} The above facilities are implemented with the VIPS core function \verb+im_add_close_callback()+. You can use this facility to make your own local resource allocators for other types of object --- see the manual page for more help. \subsection{Error handling} All VIPS operations return 0 on success and non-zero on error, setting \verb+im_error()+. As a consequence, when a VIPS function fails, you do not need to generate an error message --- you can simply propagate the error back up to your caller. If however you detect some error yourself (for example, the bad parameter in the example above), you must call \verb+im_error()+ to let your caller know what the problem was. VIPS provides two more functions for error message handling: \verb+im_warn()+ and \verb+im_diag()+. These are intended to be used for less serious messages, as their names suggest. Currently, they simply format and print their arguments to \verb+stderr+, optionally suppressed by the setting of an environment variable. Future releases of VIPS may allow more sophisticated trapping of these functions to allow their text to be easily presented to the user by VIPS applications. See the manual pages. \subsection{Joining operations together} \label{sec:joinup} VIPS lets you join image processing operations together so that they behave as a single unit. \fref{fg:join} shows the definition of the function \verb+im_Lab2disp()+ from the VIPS library. This function converts an image in \cielab{} colour space to an RGB image for a monitor. The monitor characteristics (gamma, phosphor type, etc.) are described by the \verb+im_col_display+ structure, see the man page for \verb+im_col_XYZ2rgb()+. \begin{fig2} \begin{verbatim} int im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp ) { IMAGE *t1; if( !(t1 = im_open_local( out, "im_Lab2disp:1", "p" )) || im_Lab2XYZ( in, t1 ) || im_XYZ2disp( t1, out, disp ) ) return( -1 ); return( 0 ); } \end{verbatim} \caption{Two image-processing operations joined together} \label{fg:join} \end{fig2} The special \verb+"p"+ mode (for partial) used to open the image descriptor used as the intermediate image in this function `glues' the two operations together. When you use \verb+im_Lab2disp()+, the two operations inside it will execute together and no extra storage is necessary for the intermediate image (\verb+t1+ in this example). This is important if you want to process images larger than the amount of RAM you have on your machine. As an added bonus, if you have more than one CPU in your computer, the work will be automatically spread across the processors for you. You can control this parallelization with the \verb+IM_CONCURRENCY+ environment variable, \verb+im_concurrency_set()+, and with the \verb+--vips-concurrency+ command-line switch. See the man page for \verb+im_generate()+. \subsubsection{How it works} When a VIPS function is asked to output to a \verb+"p"+ image descriptor, all the fields in the descriptor are set (the output image size and type are set, for example), but no image data is actually generated. Instead, the function attaches callbacks to the image descriptor which VIPS can use later to generate any piece of the output image that might be needed. When a VIPS function is asked to output to a \verb+"w"+ or a \verb+"t"+ descriptor (a real disc file or a real memory buffer), it evaluates immediately and its evaluation in turn forces the evaluation of any earlier \verb+"p"+ images. In the example in \fref{fg:join}, whether or not any pixels are really processed when \verb+im_Lab2disp()+ is called depends upon the mode in which \verb+out+ was opened. If \verb+out+ is also a partial image, then no pixels will be calculated --- instead, a pipeline of VIPS operations will be constructed behind the scenes and attached to \verb+out+. Conversely, if \verb+out+ is a real image (that is, either \verb+"w"+ or \verb+"t"+), then the final VIPS operation in the function (\verb+im_XYZ2disp()+) will output the entire image to \verb+out+, causing the earlier parts of \verb+im_Lab2disp()+ (and indeed possibly some earlier pieces of program, if \verb+in+ was also a \verb+"p"+ image) to run. When a VIPS pipeline does finally evaluate, all of the functions in the pipeline execute together, sucking image data through the system in small pieces. As a consequence, no intermediate images are generated, large amounts of RAM are not needed, and no slow disc I/O needs to be performed. Since VIPS partial I/O is demand-driven rather than data-driven this works even if some of the operations perform coordinate transformations. We could, for example, include a call to \verb+im_affine()+, which performs arbitrary rotation and scaling, and everything would still work correctly. \subsubsection{Pitfalls with partials} To go with all of the benefits that partial image I/O brings, there are also some problems. The most serious is that you are often not quite certain when computation will happen. This can cause problems if you close an input file, thinking that it is finished with, when in fact that file has not been processed yet. Doing this results in dangling pointers and an almost certain core-dump. You can prevent this from happening with careful use of \verb+im_open_local()+. If you always open local to your output image, you can be sure that the input will not be closed before the output has been generated to a file or memory buffer. You do not need to be so careful with non-image arguments. VIPS functions which take extra non-image arguments (a matrix, perhaps) are careful to make their own copy of the object before returning. \subsubsection{Non-image output} Some VIPS functions consume images, but make no image output. \verb+im_stats()+ for example, scans an image calculating various statistical values. When you use \verb+im_stats()+, it behaves as a data sink, sucking image data through any earlier pipeline stages. \subsubsection{Calculating twice} In some circumstances, the same image data can be generated twice. \fref{fg:thrmean} is a function which finds the mean value of an image, and writes a new image in which pixels less than the mean are set to 0 and images greater than the mean are set to 255. \begin{fig2} \begin{verbatim} int threshold_at_mean( IMAGE *in, IMAGE *out ) { double mean; if( im_avg( in, &mean ) || im_moreconst( in, out, mean ) ) return( -1 ); return( 0 ); } \end{verbatim} \caption{Threshold an image at the mean value} \label{fg:thrmean} \end{fig2} This seems straightforward --- but consider if image \verb+in+ were a \verb+"p"+, and represented the output of a large pipeline of operations. The call to \verb+im_avg()+ would force the evaluation of the entire pipeline, and throw it all away, keeping only the average value. The subsequent call to \verb+im_moreconst()+ will cause the pipeline to be evaluated a second time. When designing a program, it is sensible to pay attention to these issues. It might be faster, in some cases, to output to a file before calling \verb+im_avg()+, find the average of the disc file, and then run \verb+im_moreconst()+ from that. There's also \verb+im_cache()+ which can keep recent parts of a very large image. \subsubsection{Blocking computation} \label{sec:block} \verb+IMAGE+ descriptors have a flag called \verb+kill+ which can be used to block computation. If \verb+im->kill+ is set to a non-zero value, then any VIPS pipelines which use \verb+im+ as an intermediate will fail with an error message. This is useful for user-interface writers --- suppose your interface is forced to close an image which many other images are using as a source of data. You can just set the \verb+kill+ flag in all of the deleted image's immediate children and prevent any dangling pointers from being followed. \subsubsection{Limitations} \label{sec:limit} Not all VIPS operations are partial-aware. These non-partial operations use a pre-VIPS 7.0 I/O scheme in which the whole of the input image has to be present at the same time. In some cases, this is because partial I/O simply makes no sense --- for example, a Fourier Transform can produce no output until it has seen all of the input. \verb+im_fwfft()+ is therefore not a partial operation. In other cases, we have simply not got around to rewriting the old non-partial operation in the newer partial style. You can mix partial and non-partial VIPS operations freely, without worrying about which type they are. The only effect will be on the time your pipeline takes to execute, and the memory requirements of the intermediate images. VIPS uses the following rules when you mix the two styles of operation: \begin{enumerate} \item When a non-partial operation is asked to output to a partial image descriptor, the \verb+"p"+ descriptor is magically transformed into a \verb+"t"+ descriptor. \item When a non-partial operation is asked to read from a \verb+"p"+ descriptor, the \verb+"p"+ descriptor is turned into a \verb+"t"+ type, and any earlier stages in the pipeline forced to evaluate into that memory buffer. The non-partial operation then processes from the memory buffer. \end{enumerate} These rules have the consequence that you may only process very large images if you only use partial operations. If you use any non-partial operations, then parts of your pipelines will fall back to old whole-image I/O and you will need to think carefully about where your intermediates should be stored.