From d6aa4ef74dc25762bfdf0e3d0b4001aefc9a486c Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 4 Feb 2010 14:38:12 +0000 Subject: [PATCH] format stuff --- libvips/conversion/im_text.c | 2 +- libvips/format/format.c | 150 +++++++++++++++++++++++++++---- libvips/format/im_analyze2vips.c | 19 ++++ libvips/format/im_csv2vips.c | 60 +++++++++++++ libvips/format/im_exr2vips.c | 28 +++++- libvips/format/im_jpeg2vips.c | 58 +++++++++++- libvips/format/im_vips2csv.c | 43 +++++++-- libvips/format/im_vips2jpeg.c | 53 ++++++++++- 8 files changed, 383 insertions(+), 30 deletions(-) diff --git a/libvips/conversion/im_text.c b/libvips/conversion/im_text.c index 3e042365..4a21b599 100644 --- a/libvips/conversion/im_text.c +++ b/libvips/conversion/im_text.c @@ -194,7 +194,7 @@ text_render_to_image( PangoContext *context, IMAGE *out, * are used for anti-aliasing. * * @text is the text to render as a UTF-8 string. It can contain Pango markup, - * for example "The Guardian". + * for example "<i>The</i>Guardian". * * @font is the font to render with, selected by fontconfig. Examples might be * "sans 12" or perhaps "bitstream charter bold 10". diff --git a/libvips/format/format.c b/libvips/format/format.c index 78b3c052..6071dd2e 100644 --- a/libvips/format/format.c +++ b/libvips/format/format.c @@ -50,19 +50,18 @@ * * VIPS has a simple system for representing image load and save operations in * a generic way. - * You can ask for a loader for a certain file, select a saver based on a - * filename, or register a new image file format. You can also call the - * converters directly, if you like. + * You can ask for a loader for a certain file or select a saver based on a + * filename. Once you have found a format, you can use it to load a file of + * that type, save an image to a file of that type, query files for their type + * and fields, and ask for supported features. You can also call the + * converters directly, if you like. * - * Each format has a priority. Some loaders (such as the libMagick one) can - * handle several formats. Priorities let you ensure that these generic - * loaders are only used as a last resort. - * - * Each format has a set of flags you can read which hint about the loader's - * capabilities. See #VipsFormatFlags. + * If you define a new format, support for + * it automatically appears in all VIPS user-interfaces. It will also be + * transparently supported by im_open(). * * VIPS comes with loaders for TIFF, JPEG, PNG, Analyze, PPM, OpenEXR, CSV, - * RAW and one that wraps libMagick. + * RAW, VIPS and one that wraps libMagick. */ /** @@ -75,17 +74,136 @@ * typedef struct _VipsFormatClass { * VipsObjectClass parent_class; * - * gboolean (*is_a)( const char * ); - * int (*header)( const char *, IMAGE * ); - * int (*load)( const char *, IMAGE * ); - * int (*save)( IMAGE *, const char * ); - * VipsFormatFlags (*get_flags)( const char * ); + * gboolean (*is_a)( const char *filename ); + * int (*header)( const char *filename, IMAGE *out ); + * int (*load)( const char *filename, IMAGE *out ); + * int (*save)( IMAGE *in, const char *filename ); + * VipsFormatFlags (*get_flags)( const char *filename ); * int priority; * const char **suffs; * } VipsFormatClass; * ]| * - * Subclasses need to implement at least load() or save(). + * Add a new format to VIPS by subclassing VipsFormat. Subclasses need to + * implement at least load() or save(). + * + * These members are: + * + * + * + * + * is_a() This function should return %TRUE if the file + * contains an image of this type. If you don't define this function, VIPS + * will use the list of suffixes you supply instead. + * + * + * + * + * header() This function should load the image header, + * but not load any pixel data. If you don't define it, VIPS will use your + * load() method instead. Return 0 for success, -1 for error, setting + * im_error(). + * + * + * + * + * load() This function should load the image, or perhaps use im_generate() to + * attach something to load sections of the image on demand. + * Users can embed + * load options in the filename, see (for example) im_jpeg2vips(). + * If you don't + * define this method, you can still define save() and have a save-only + * format. + * Return 0 for success, -1 for error, setting + * im_error(). + * + * + * + * + * save() This function should save the image to the file. + * Users can embed + * save options in the filename, see (for example) im_vips2tiff(). + * If you don't + * define this method, you can still define load() and have a load-only + * format. + * Return 0 for success, -1 for error, setting + * im_error(). + * + * + * + * + * get_flags() This function should return a hint about the properties of this + * loader on this file. If you don't define it, users will always see '0', or + * no flags. + * + * + * + * + * priority Where this format should fit in this + * list of + * supported formats. 0 is a sensible value for most formats. Set a negative + * value if you want to be lower on the list, positive to move up. + * + * + * + * + * suffs A %NULL-terminated list of possible file + * name + * suffixes, for example: + * |[ + * static const char *tiff_suffs[] = { ".tif", ".tiff", NULL }; + * ]| + * The suffix list is used to select a format to save a file in, and to pick a + * loader if you don't define is_a(). + * + * + * + * + * You should also define nickname and + * description in #VipsObject. + * + * At the command-line, use: + * + * |[ + * vips --list classes | grep Format + * ]| + * + * To see a list of all the supported formats. + * + * For example, the TIFF format is defined like this: + * +|[ +typedef VipsFormat VipsFormatTiff; +typedef VipsFormatClass VipsFormatTiffClass; + +static void +vips_format_tiff_class_init( VipsFormatTiffClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "tiff"; + object_class->description = _( "TIFF" ); + + format_class->is_a = istiff; + format_class->header = tiff2vips_header; + format_class->load = im_tiff2vips; + format_class->save = im_vips2tiff; + format_class->get_flags = tiff_flags; + format_class->suffs = tiff_suffs; +} + +static void +vips_format_tiff_init( VipsFormatTiff *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatTiff, vips_format_tiff, VIPS_TYPE_FORMAT ); +]| + * + * Then call vips_format_tiff_get_type() somewhere in your init code to link + * the format into VIPS (though of course the tiff format is linked in for you + * already). * */ diff --git a/libvips/format/im_analyze2vips.c b/libvips/format/im_analyze2vips.c index 81037c9f..5b5af292 100644 --- a/libvips/format/im_analyze2vips.c +++ b/libvips/format/im_analyze2vips.c @@ -8,6 +8,8 @@ * - fix signed/unsigned warning * 13/1/09 * - try harder not to generate error messages in "isanalyze" + * 4/2/10 + * - gtkdoc */ /* @@ -549,6 +551,23 @@ analyze2vips_header( const char *filename, IMAGE *out ) return( 0 ); } +/** + * im_analyze2vips: + * @filename: file to load + * @out: image to write to + * + * Load an Analyze 6.0 file. If @filename is "fred.img", this will look for + * an image header called "fred.hdr" and pixel data in "fred.img". You can + * also load "fred" or "fred.hdr". + * + * Images are + * loaded lazilly and byte-swapped, if necessary. The Analyze metadata is read + * and attached. + * + * See also: #VipsFormat, im_meta_get(), im_grid(). + * + * Returns: 0 on success, -1 on error. + */ int im_analyze2vips( const char *filename, IMAGE *out ) { diff --git a/libvips/format/im_csv2vips.c b/libvips/format/im_csv2vips.c index 8e8d417d..1278311a 100644 --- a/libvips/format/im_csv2vips.c +++ b/libvips/format/im_csv2vips.c @@ -9,6 +9,8 @@ * - oop, unquoted trailing columns could get missed * 17/5/07 * - added im_csv2vips_header() + * 4/2/10 + * - gtkdoc */ /* @@ -251,6 +253,64 @@ read_csv( FILE *fp, IMAGE *out, return( 0 ); } +/** + * im_csv2vips: + * @filename: file to load + * @out: image to write to + * + * Load a CSV (comma-separated values) file. The output image is always 1 + * band (monochrome), %IM_BANDFMT_DOUBLE. + * The reader is deliberately rather fussy: it will fail if there are any + * short lines, or if the file is too short. It will ignore lines that are + * too long. + * + * Read options can be embedded in the filename. The options can be given + * in any order and are: + * + * + * + * + * skip:lines-to-skip The number of lines to skip at + * the start of the file. Default zero. + * + * + * + * + * line:lines-to-read + * The number of lines to read from the file. Default -1, meaning read to end of + * file. + * + * + * + * + * whi:whitespace-characters + * The skippable whitespace characters. Default space and + * double quotes ("). + * Whitespace characters are always run together. + * + * + * + * + * sep:separator-characters + * The characters that separate fields. Default ;,tab. + * Separators are never run together. + * + * + * + * + * For example: + * + * |[ + * im_csv2vips( "fred.csv:skip:58,sep:\,,line:3", out ); + * ]| + * + * Will read three lines starting at line 59, with comma as the only + * allowed separator. Note that the ',' has to be escaped with a backslash. + * + * See also: #VipsFormat, im_vips2csv(), im_read_dmask(), im_ppm2vips(). + * + * Returns: 0 on success, -1 on error. + */ int im_csv2vips( const char *filename, IMAGE *out ) { diff --git a/libvips/format/im_exr2vips.c b/libvips/format/im_exr2vips.c index 98260b5e..3a9d6cd2 100644 --- a/libvips/format/im_exr2vips.c +++ b/libvips/format/im_exr2vips.c @@ -8,6 +8,10 @@ * - added tiled read, with a separate cache * - removed *255 we had before, better to do something clever with * chromaticities + * 4/2/10 + * - gtkdoc + + TODO - colour management - attributes @@ -417,18 +421,34 @@ exr2vips( Read *read ) return( 0 ); } -/* Read a OpenEXR file into a VIPS image. +/** + * im_exr2vips: + * @filename: file to load + * @out: image to write to + * + * Read a OpenEXR file into a VIPS image. + * + * The reader can handle scanline and tiled OpenEXR images. It can't handle + * OpenEXR colour management, image attributes, many pixel formats, anything + * other than RGBA. + * + * This reader uses the rather limited OpenEXR C API. It should really be + * redone in C++. + * + * See also: #VipsFormat. + * + * Returns: 0 on success, -1 on error. */ int -im_exr2vips( const char *name, IMAGE *out ) +im_exr2vips( const char *filename, IMAGE *out ) { Read *read; #ifdef DEBUG - printf( "im_exr2vips: reading \"%s\"\n", name ); + printf( "im_exr2vips: reading \"%s\"\n", filename ); #endif /*DEBUG*/ - if( !(read = read_new( name, out )) || + if( !(read = read_new( filename, out )) || exr2vips( read ) ) return( -1 ); diff --git a/libvips/format/im_jpeg2vips.c b/libvips/format/im_jpeg2vips.c index 056da952..0cc6929f 100644 --- a/libvips/format/im_jpeg2vips.c +++ b/libvips/format/im_jpeg2vips.c @@ -26,6 +26,8 @@ * - added "fail" option ... fail on any warnings * 12/10/09 * - also set scale_num on shrink (thanks Guido) + * 4/2/10 + * - gtkdoc */ /* @@ -706,12 +708,62 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only ) return( result ); } -/* Read a JPEG file into a VIPS image. +/** + * im_jpeg2vips: + * @filename: file to load + * @out: image to write to + * + * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, + * including CMYK and YCbCr. + * + * You can embed options in the filename. They have the form: + * + * |[ + * filename.jpg:shrink-factor,fail + * ]| + * + * + * + * + * shrink-factor + * Shrink by this integer factor during load. Allowed values are 1, 2, 4 + * and 8. Shrinking during read is very much faster than decompressing the + * whole image and then shrinking. + * + * + * + * + * fail + * This makes the JPEG reader fail on any warnings. This can be useful for + * detecting truncated files, for example. Normally reading these produces + * a warning, but no fatal error. + * + * + * + * + * Example: + * + * |[ + * im_jpeg2vips( "fred.jpg:8" out ); + * im_jpeg2vips( "fred.jpg:,fail" out ); + * ]| + * + * The first example will shrink by a factor of 8 during load. The second will + * fail with an error if there are any problems loading the file. + * + * Any embedded ICC profiles are ignored: you always just get the RGB from + * the file. Instead, the embedded profile will be attached to the image as + * metadata. You need to use something like im_icc_import() to get CIE + * values from the file. Any EXIF data is also attached as VIPS metadata. + * + * See also: #VipsFormat, im_vips2jpeg(). + * + * Returns: 0 on success, -1 on error. */ int -im_jpeg2vips( const char *name, IMAGE *out ) +im_jpeg2vips( const char *filename, IMAGE *out ) { - return( jpeg2vips( name, out, FALSE ) ); + return( jpeg2vips( filename, out, FALSE ) ); } static int diff --git a/libvips/format/im_vips2csv.c b/libvips/format/im_vips2csv.c index 74dc0340..94022e71 100644 --- a/libvips/format/im_vips2csv.c +++ b/libvips/format/im_vips2csv.c @@ -103,6 +103,41 @@ vips2csv( IMAGE *in, FILE *fp, const char *sep ) return( 0 ); } +/** + * im_vips2csv: + * @in: image to save + * @filename: file to write to + * + * Save a CSV (comma-separated values) file. The image is written + * one line of text per scanline. Complex numbers are written as + * "(real,imaginary)" and will need extra parsing I guess. The image must + * have a single band. + * + * Write options can be embedded in the filename. The options can be given + * in any order and are: + * + * + * + * + * sep:separator-string + * The string to use to separate numbers in the output. + * The default is "\\t" (tab). + * + * + * + * + * For example: + * + * |[ + * im_csv2vips( in, "fred.csv:sep:\t" ); + * ]| + * + * Will write to fred.csv, separating numbers with tab characters. + * + * See also: #VipsFormat, im_csv2vips(), im_write_dmask(), im_vips2ppm(). + * + * Returns: 0 on success, -1 on error. + */ int im_vips2csv( IMAGE *in, const char *filename ) { @@ -122,12 +157,10 @@ im_vips2csv( IMAGE *in, const char *filename ) separator = r; } - if( im_incheck( in ) ) + if( im_incheck( in ) || + im_check_mono( "im_vips2csv", in ) || + im_check_uncoded( "im_vips2csv", in ) ) return( -1 ); - if( in->Coding != IM_CODING_NONE ) { - im_error( "im_vips2csv", "%s", _( "input must be uncoded" ) ); - return( -1 ); - } if( !(fp = fopen( name, "w" )) ) { im_error( "im_cvips2csv", _( "unable to open \"%s\"" ), diff --git a/libvips/format/im_vips2jpeg.c b/libvips/format/im_vips2jpeg.c index 45f7d918..d719593f 100644 --- a/libvips/format/im_vips2jpeg.c +++ b/libvips/format/im_vips2jpeg.c @@ -29,6 +29,8 @@ * - fix signed/unsigned warning * 13/8/09 * - allow "none" for profile, meaning don't embed one + * 4/2/10 + * - gtkdoc */ /* @@ -640,7 +642,56 @@ write_vips( Write *write, int qfac, const char *profile ) return( 0 ); } -/* Write a VIPS image to a file as JPEG. +/** + * im_vips2jpeg: + * @in: image to save + * @filename: file to write to + * + * Write a VIPS image to a file as JPEG. + * + * You can embed options in the filename. They have the form: + * + * |[ + * filename.jpg:compression,profile + * ]| + * + * + * + * + * compression + * Compress with this quality factor. Default 75. + * + * + * + * + * profile + * Attach this ICC profile. For example, "fred.jpg:,/home/john/srgb.icc" will + * embed the profile stored in the file "/home/john/srgb.icc" in the JPEG + * image. This does not affect the pixels which are written, just the way + * they are tagged. You can use the special string "none" to mean + * "don't attach a profile". + * + * + * + * + * If no profile is specified in the save string and the VIPS header + * contains an ICC profile named IM_META_ICC_NAME ("icc-profile-data"), the + * profile from the VIPS header will be attached. + * + * The image is automatically converted to RGB, Monochrome or CMYK before + * saving. Any metadata attached to the image is saved as EXIF, if possible. + * + * Example: + * + * |[ + * im_vips2jpeg( in, "fred.jpg:99,none" out ); + * ]| + * + * Will write "fred.jpg" at high-quality with no ICC profile. + * + * See also: #VipsFormat, im_jpeg2vips(). + * + * Returns: 0 on success, -1 on error. */ int im_vips2jpeg( IMAGE *in, const char *filename )