diff --git a/TODO b/TODO index 16c41fbe..300d9b0d 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,6 @@ +- setting suffs on the base rad class made hdr save fail silently, why was + there no message? + - add more webp tests to py suite - try moving some more of the CLI tests to py diff --git a/libvips/foreign/fitsload.c b/libvips/foreign/fitsload.c index 179e497c..4b5dea8e 100644 --- a/libvips/foreign/fitsload.c +++ b/libvips/foreign/fitsload.c @@ -40,8 +40,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_CFITSIO - #include #include #include @@ -50,6 +48,8 @@ #include #include +#ifdef HAVE_CFITSIO + #include "fits.h" typedef struct _VipsForeignLoadFits { @@ -133,3 +133,36 @@ vips_foreign_load_fits_init( VipsForeignLoadFits *fits ) } #endif /*HAVE_CFITSIO*/ + +/** + * vips_fitsload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Read a FITS image file into a VIPS image. + * + * This operation can read images with up to three dimensions. Any higher + * dimensions must be empty. + * + * It can read 8, 16 and 32-bit integer images, signed and unsigned, float and + * double. + * + * FITS metadata is attached with the "fits-" prefix. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_fitsload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "fitsload", ap, filename, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/fitssave.c b/libvips/foreign/fitssave.c index d86943e2..50fbd9f7 100644 --- a/libvips/foreign/fitssave.c +++ b/libvips/foreign/fitssave.c @@ -43,14 +43,14 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_CFITSIO - #include #include #include #include +#ifdef HAVE_CFITSIO + #include "fits.h" typedef struct _VipsForeignSaveFits { @@ -148,3 +148,28 @@ vips_foreign_save_fits_init( VipsForeignSaveFits *fits ) } #endif /*HAVE_CFITSIO*/ + +/** + * vips_fitssave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Write a VIPS image to a file in FITS format. + * + * See also: vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_fitssave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "fitssave", ap, in, filename ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index b0e754b6..811f774b 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1765,1458 +1765,3 @@ vips_foreign_operation_init( void ) vips_foreign_load_openexr_get_type(); #endif /*HAVE_OPENEXR*/ } - -/** - * vips_vipsload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Read in a vips image. - * - * See also: vips_vipssave(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_vipsload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "vipsload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_vipssave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Write @in to @filename in VIPS format. - * - * See also: vips_vipsload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_vipssave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "vipssave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_magickload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @all_frames: %gboolean, load all frames in sequence - * * @density: string, canvas resolution for rendering vector formats like SVG - * - * Read in an image using libMagick, the ImageMagick library. This library can - * read more than 80 file formats, including SVG, BMP, EPS, DICOM and many - * others. - * The reader can handle any ImageMagick image, including the float and double - * formats. It will work with any quantum size, including HDR. Any metadata - * attached to the libMagick image is copied on to the VIPS image. - * - * The reader should also work with most versions of GraphicsMagick. See the - * "--with-magickpackage" configure option. - * - * Normally it will only load the first image in a many-image sequence (such - * as a GIF). Set @all_frames to true to read the whole image sequence. - * - * @density is "WxH" in DPI, e.g. "600x300" or "600" (default is "72x72"). See - * the [density - * docs](http://www.imagemagick.org/script/command-line-options.php#density) - * on the imagemagick website. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_magickload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "magickload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_magickload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @all_frames: %gboolean, load all frames in sequence - * * @density: string, canvas resolution for rendering vector formats like SVG - * - * Read an image memory block using libMagick into a VIPS image. Exactly as - * vips_magickload(), but read from a memory source. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_magickload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_magickload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "magickload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_tiffload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: int, load this page - * - * Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader, - * with extensions for tiled images, multipage images, LAB colour space, - * pyramidal images and JPEG compression. including CMYK and YCbCr. - * - * @page means load this page from the file. By default the first page (page - * 0) is read. - * - * Any ICC profile is read and attached to the VIPS image. Any XMP metadata is - * read and attached to the image. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_tiffload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "tiffload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_tiffload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page - * - * Read a TIFF-formatted memory block into a VIPS image. Exactly as - * vips_tiffload(), but read from a memory source. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_tiffload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "tiffload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_tiffsave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: use this #VipsForeignTiffCompression - * * @Q: %gint quality factor - * * @predictor: use this #VipsForeignTiffPredictor - * * @profile: filename of ICC profile to attach - * * @tile: set %TRUE to write a tiled tiff - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @pyramid: set %TRUE to write an image pyramid - * * @squash: set %TRUE to squash 8-bit images down to 1 bit - * * @miniswhite: set %TRUE to write 1-bit images as MINISWHITE - * * @resunit: #VipsForeignTiffResunit for resolution unit - * * @xres: %gdouble horizontal resolution in pixels/mm - * * @yres: %gdouble vertical resolution in pixels/mm - * * @bigtiff: set %TRUE to write a BigTiff file - * - * Write a VIPS image to a file as TIFF. - * - * Use @compression to set the tiff compression. Currently jpeg, packbits, - * fax4, lzw, none and deflate are supported. The default is no compression. - * JPEG compression is a good lossy compressor for photographs, packbits is - * good for 1-bit images, and deflate is the best lossless compression TIFF - * can do. LZW has patent problems and is no longer recommended. - * - * Use @Q to set the JPEG compression factor. Default 75. - * - * Use @predictor to set the predictor for lzw and deflate compression. - * - * Predictor is not set by default. There are three predictor values recognised - * at the moment (2007, July): 1 is no prediction, 2 is a horizontal - * differencing and 3 is a floating point predictor. Refer to the libtiff - * specifications for further discussion of various predictors. In short, - * predictor helps to better compress image, especially in case of digital - * photos or scanned images and bit depths > 8. Try it to find whether it - * works for your images. - * - * Use @profile to give the filename of a profile to be embedded in the TIFF. - * 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 and the VIPS header - * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the - * profile from the VIPS header will be attached. - * - * Set @tile to TRUE to write a tiled tiff. By default tiff are written in - * strips. Use @tile_width and @tile_height to set the tile size. The defaiult - * is 128 by 128. - * - * Set @pyramid to write the image as a set of images, one per page, of - * decreasing size. - * - * Set @squash to make 8-bit uchar images write as 1-bit TIFFs. Values >128 - * are written as white, values <=128 as black. Normally vips will write - * MINISBLACK TIFFs where black is a 0 bit, but if you set @miniswhite, it - * will use 0 for a white bit. Many pre-press applications only work with - * images which use this sense. @miniswhite only affects one-bit images, it - * does nothing for greyscale images. - * - * Use @resunit to override the default resolution unit. - * The default - * resolution unit is taken from the header field "resolution-unit" - * (#VIPS_META_RESOLUTION_UNIT in C). If this field is not set, then - * VIPS defaults to cm. - * - * Use @xres and @yres to override the default horizontal and vertical - * resolutions. By default these values are taken from the VIPS image header. - * libvips resolution is always in pixels per millimetre. - * - * Set @bigtiff to attempt to write a bigtiff. - * Bigtiff is a variant of the TIFF - * format that allows more than 4GB in a file. - * - * If @in has a field called VIPS_META_XMP_NAME ("xmp-data") it is written to - * the tiff image. - * - * See also: vips_tiffload(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_tiffsave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "tiffsave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_jpegload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * * @fail: %gboolean, fail on warnings - * * @autorotate: %gboolean, use exif Orientation tag to rotate the image during load - * - * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, - * including CMYK and YCbCr. - * - * @shrink means shrink by this integer factor during load. Possible values - * are 1, 2, 4 and 8. Shrinking during read is very much faster than - * decompressing the whole image and then shrinking later. - * - * Setting @fail to %TRUE 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. - * - * Setting @autorotate to %TRUE will make the loader interpret the EXIF - * Orientation field and automatically rotate the image appropriately during - * load. After rotation, the Orientation tag will be removed to prevent - * accidental double-rotation. - * - * Using @autorotate can be much slower than doing the rotate later - * in processing. See vips_autorot(). - * - * Example: - * - * |[ - * vips_jpegload( "fred.jpg", &out, - * "shrink", 8, - * "fail", TRUE, - * NULL ); - * ]| - * - * 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 - * @VIPS_META_ICC_NAME ("icc-profile-data"). You need to use something like - * vips_icc_import() to get CIE values from the file. - * - * EXIF metadata is attached as @VIPS_META_EXIF_NAME ("exif-data"), IPCT as - * @VIPS_META_IPCT_NAME ("ipct-data"), and XMP as VIPS_META_XMP_NAME - * ("xmp-data"). - * - * The int metadata item "jpeg-multiscan" is set to the result of - * jpeg_has_multiple_scans(). Interlaced jpeg images need a large amount of - * memory to load, so this field gives callers a chance to handle these - * images differently. - * - * The EXIF thumbnail, if present, is attached to the image as - * "jpeg-thumbnail-data". See vips_image_get_blob(). - * - * This function only reads the image header and does not decompress any pixel - * data. Decompression only occurs when pixels are accessed. - * - * See also: vips_jpegload_buffer(), vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "jpegload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_jpegload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * * @fail: %gboolean, fail on warnings - * - * Read a JPEG-formatted memory block into a VIPS image. Exactly as - * vips_jpegload(), but read from a memory buffer. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_jpegload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "jpegload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_jpegsave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @profile: filename of ICC profile to attach - * * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * * @interlace: %gboolean, write an interlaced (progressive) jpeg - * * @strip: %gboolean, remove all metadata from image - * * @no-subsample: %gboolean, disable chroma subsampling - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * - * Write a VIPS image to a file as JPEG. - * - * Use @Q to set the JPEG compression factor. Default 75. - * - * Use @profile to give the filename of a profile to be embedded in the JPEG. - * 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 and the VIPS header - * contains an ICC profile named VIPS_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. - * - * EXIF data is constructed from @VIPS_META_EXIF_NAME ("exif-data"), then - * modified with any other related tags on the image before being written to - * the file. - * - * IPCT as @VIPS_META_IPCT_NAME ("ipct-data") and XMP as VIPS_META_XMP_NAME - * ("xmp-data") are coded and attached. - * - * If @optimize_coding is set, the Huffman tables are optimised. This is - * sllightly slower and produces slightly smaller files. - * - * If @interlace is set, the jpeg files will be interlaced (progressive jpeg, - * in jpg parlance). These files may be better for display over a slow network - * conection, but need much more memory to encode and decode. - * - * If @strip is set, no EXIF data, IPCT data, ICC profile or XMP metadata is - * written into the output file. - * - * If @no-subsample is set, chrominance subsampling is disabled. This will - * improve quality at the cost of larger file size. Useful for high Q factors. - * - * If @trellis_quant is set and the version of libjpeg supports it - * (e.g. mozjpeg >= 3.0), apply trellis quantisation to each 8x8 block. - * Reduces file size but increases compression time. - * - * If @overshoot_deringing is set and the version of libjpeg supports it - * (e.g. mozjpeg >= 3.0), apply overshooting to samples with extreme values - * for example 0 and 255 for 8-bit. Overshooting may reduce ringing artifacts - * from compression, in particular in areas where black text appears on a - * white background. - * - * If @optimize_scans is set and the version of libjpeg supports it - * (e.g. mozjpeg >= 3.0), split the spectrum of DCT coefficients into - * separate scans. Reduces file size but increases compression time. - * - * If @quant_table is set and the version of libjpeg supports it - * (e.g. mozjpeg >= 3.0) it selects the quantization table to use: - * - * * 0 — Tables from JPEG Annex K (vips and libjpeg default) - * * 1 — Flat table - * * 2 — Table tuned for MSSIM on Kodak image set - * * 3 — Table from ImageMagick by N. Robidoux (current mozjpeg default) - * * 4 — Table tuned for PSNR-HVS-M on Kodak image set - * * 5 — Table from Relevance of Human Vision to JPEG-DCT Compression (1992) - * * 6 — Table from DCTune Perceptual Optimization of Compressed Dental - * X-Rays (1997) - * * 7 — Table from A Visual Detection Model for DCT Coefficient - * Quantization (1993) - * * 8 — Table from An Improved Detection Model for DCT Coefficient - * Quantization (1993) - * - * Quantization table 0 is the default in vips and libjpeg(-turbo), but it - * tends to favor detail over color accuracy, producting colored patches and - * stripes as well as heavy banding in flat areas at high compression ratios. - * Quantization table 2 is a good candidate to try if the default quantization - * table produces banding or color shifts and is well suited for hires images. - * Quantization table 3 is the default in mozjpeg and has been tuned to produce - * good results at the default quality setting; banding at high compression. - * Quantization table 4 is the most accurate at the cost of compression ratio. - * Tables 5-7 are based on older research papers, but generally achieve worse - * compression ratios and/or quality than 2 or 4. - * - * See also: vips_jpegsave_buffer(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegsave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "jpegsave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_jpegsave_buffer: - * @in: image to save - * @buf: return output buffer here - * @len: return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: JPEG quality factor - * * @profile: attach this ICC profile - * * @optimize_coding: compute optimal Huffman coding tables - * * @interlace: write an interlaced (progressive) jpeg - * * @strip: remove all metadata from image - * * @no-subsample: disable chroma subsampling - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * - * As vips_jpegsave(), but save to a memory buffer. - * - * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_jpegsave(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) -{ - va_list ap; - VipsArea *area; - int result; - - area = NULL; - - va_start( ap, len ); - result = vips_call_split( "jpegsave_buffer", ap, in, &area ); - va_end( ap ); - - if( !result && - area ) { - if( buf ) { - *buf = area->data; - area->free_fn = NULL; - } - if( len ) - *len = area->length; - - vips_area_unref( area ); - } - - return( result ); -} - -/** - * vips_jpegsave_mime: - * @in: image to save - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: JPEG quality factor - * * @profile: attach this ICC profile - * * @optimize_coding: compute optimal Huffman coding tables - * * @strip: remove all metadata from image - * * @no-subsample: disable chroma subsampling - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * - * As vips_jpegsave(), but save as a mime jpeg on stdout. - * - * See also: vips_jpegsave(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegsave_mime( VipsImage *in, ... ) -{ - va_list ap; - int result; - - va_start( ap, in ); - result = vips_call_split( "jpegsave_mime", ap, in ); - va_end( ap ); - - return( result ); -} - -/** - * vips_webpload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * - * Read a WebP file into a VIPS image. - * - * Use @shrink to specify a shrink-on-load factor. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_webpload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "webpload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_webpload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * - * Read a WebP-formatted memory block into a VIPS image. Exactly as - * vips_webpload(), but read from a memory buffer. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_webpload() - * - * Returns: 0 on success, -1 on error. - */ -int -vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "webpload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_webpsave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint quality factor - * * @lossless: %gboolean enables lossless compression - * * @preset: #VipsForeignWebpPreset choose lossy compression preset - * * @smart_subsample: %gboolean enables high quality chroma subsampling - * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) - * * @alpha_q: %gint set alpha quality in lossless mode - * - * Write an image to a file in WebP format. - * - * By default, images are saved in lossy format, with - * @Q giving the WebP quality factor. It has the range 0 - 100, with the - * default 75. - * - * Use @preset to hint the image type to the lossy compressor. The default is - * #VIPS_FOREIGN_WEBP_PRESET_DEFAULT. - * Set @smart_subsample to enable high quality chroma subsampling. - * Use @alpha_q to set the quality for the alpha channel in lossy mode. It has - * the range 1 - 100, with the default 100. - * - * Set @lossless to use lossless compression, or combine @near_lossless - * with @Q 80, 60, 40 or 20 to apply increasing amounts of preprocessing - * which improves the near-lossless compression ratio by up to 50%. - * - * See also: vips_webpload(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_webpsave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "webpsave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_webpsave_buffer: - * @in: image to save - * @buf: return output buffer here - * @len: return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint quality factor - * * @lossless: %gboolean enables lossless compression - * * @preset: #VipsForeignWebpPreset choose lossy compression preset - * * @smart_subsample: %gboolean enables high quality chroma subsampling - * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) - * * @alpha_q: %gint set alpha quality in lossless mode - * - * As vips_webpsave(), but save to a memory buffer. - * - * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_webpsave(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) -{ - va_list ap; - VipsArea *area; - int result; - - area = NULL; - - va_start( ap, len ); - result = vips_call_split( "webpsave_buffer", ap, in, &area ); - va_end( ap ); - - if( !result && - area ) { - if( buf ) { - *buf = area->data; - area->free_fn = NULL; - } - if( len ) - *len = area->length; - - vips_area_unref( area ); - } - - return( result ); -} - -/** - * vips_webpsave_mime: - * @in: image to save - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint quality factor - * * @lossless: %gboolean enables lossless compression - * * @preset: #VipsForeignWebpPreset choose lossy compression preset - * * @smart_subsample: %gboolean enables high quality chroma subsampling - * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) - * * @alpha_q: %gint set alpha quality in lossless mode - * - * As vips_webpsave(), but save as a mime webp on stdout. - * - * See also: vips_webpsave(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_webpsave_mime( VipsImage *in, ... ) -{ - va_list ap; - int result; - - va_start( ap, in ); - result = vips_call_split( "webpsave_mime", ap, in ); - va_end( ap ); - - return( result ); -} - -/** - * vips_openexrload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * 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: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_openexrload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "openexrload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_openslideload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @level: load this level - * * @associated: load this associated image - * * @autocrop: crop to image bounds - * - * Read a virtual slide supported by the OpenSlide library into a VIPS image. - * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, - * and Ventana formats. - * - * To facilitate zooming, virtual slide formats include multiple scaled-down - * versions of the high-resolution image. These are typically called - * "levels". By default, vips_openslideload() reads the highest-resolution - * level (level 0). Set @level to the level number you want. - * - * In addition to the slide image itself, virtual slide formats sometimes - * include additional images, such as a scan of the slide's barcode. - * OpenSlide calls these "associated images". To read an associated image, - * set @associated to the image's name. - * A slide's associated images are listed in the - * "slide-associated-images" metadata item. - * - * The output of this operator is always RGBA. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_openslideload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "openslideload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_fitsload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Read a FITS image file into a VIPS image. - * - * This operation can read images with up to three dimensions. Any higher - * dimensions must be empty. - * - * It can read 8, 16 and 32-bit integer images, signed and unsigned, float and - * double. - * - * FITS metadata is attached with the "fits-" prefix. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_fitsload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "fitsload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_fitssave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Write a VIPS image to a file in FITS format. - * - * See also: vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_fitssave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "fitssave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_pngload: - * @filename: file to load - * @out: decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Read a PNG file into a VIPS image. It can read all png images, including 8- - * and 16-bit images, 1 and 3 channel, with and without an alpha channel. - * - * Any ICC profile is read and attached to the VIPS image. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pngload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "pngload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_pngload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Read a PNG-formatted memory block into a VIPS image. It can read all png - * images, including 8- and 16-bit images, 1 and 3 channel, with and without - * an alpha channel. - * - * Any ICC profile is read and attached to the VIPS image. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_pngload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "pngload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_pngsave: - * @in: image to save - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: compression level - * * @interlace: interlace image - * * @profile: ICC profile to embed - * * @filter: #VipsForeignPngFilter row filter flag(s) - * - * Write a VIPS image to a file as PNG. - * - * @compression means compress with this much effort (0 - 9). Default 6. - * - * Set @interlace to %TRUE to interlace the image with ADAM7 - * interlacing. Beware - * than an interlaced PNG can be up to 7 times slower to write than a - * non-interlaced image. - * - * Use @profile to give the filename of a profile to be embedded in the PNG. - * 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 @profile is specified and the VIPS header - * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the - * profile from the VIPS header will be attached. - * - * Use @filter to specify one or more filters (instead of adaptive filtering), - * see #VipsForeignPngFilter. - * - * The image is automatically converted to RGB, RGBA, Monochrome or Mono + - * alpha before saving. Images with more than one byte per band element are - * saved as 16-bit PNG, others are saved as 8-bit PNG. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pngsave( VipsImage *in, const char *filename, ... ) -{ - va_list ap; - int result; - - va_start( ap, filename ); - result = vips_call_split( "pngsave", ap, in, filename ); - va_end( ap ); - - return( result ); -} - -/** - * vips_pngsave_buffer: - * @in: image to save - * @buf: return output buffer here - * @len: return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: compression level - * * @interlace: interlace image - * * @profile: ICC profile to embed - * * @filter: libpng row filter flag(s) - * - * As vips_pngsave(), but save to a memory buffer. - * - * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_pngsave(), vips_image_write_to_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) -{ - va_list ap; - VipsArea *area; - int result; - - area = NULL; - - va_start( ap, len ); - result = vips_call_split( "pngsave_buffer", ap, in, &area ); - va_end( ap ); - - if( !result && - area ) { - if( buf ) { - *buf = area->data; - area->free_fn = NULL; - } - if( len ) - *len = area->length; - - vips_area_unref( area ); - } - - return( result ); -} - -/** - * vips_matload: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Read a Matlab save file into a VIPS image. - * - * This operation searches the save - * file for the first array variable with between 1 and 3 dimensions and loads - * it as an image. It will not handle complex images. It does not handle - * sparse matrices. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_matload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "matload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_pdfload: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page, numbered from zero - * * @n: %gint, load this many pages - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * - * Render a PDF file into a VIPS image. Rendering uses the libpoppler library - * and should be fast. - * - * The output image is always RGBA --- CMYK PDFs will be - * converted. If you need CMYK bitmaps, you should use vips_magickload() - * instead. - * - * Rendering is progressive, that is, the image is rendered in strips equal in - * height to the tile height. If your PDF contains large image files and - * they span several strips in the output image, they will be decoded multiple - * times. To fix this, increase the the tile height, for example: - * - * |[ - * vips copy huge.pdf x.png --vips-tile-height=1024 - * ]| - * - * Will process images in 1024-pixel high strips, potentially much faster, - * though of course also using a lot more memory. - * - * Use @page to select a page to render, numbering from zero. - * - * Use @n to select the number of pages to render. The default is 1. Pages are - * rendered in a vertical column, with each individual page aligned to the - * left. Set to -1 to mean "until the end of the document". Use vips_grid() - * to change page layout. - * - * Use @dpi to set the rendering resolution. The default is 72. Alternatively, - * you can scale the rendering from the default 1 point == 1 pixel by - * setting @scale. - * - * The operation fills a number of header fields with metadata, for example - * "pdf-author". They may be useful. - * - * This function only reads the image header and does not render any pixel - * data. Rendering occurs when pixels are accessed. - * - * See also: vips_image_new_from_file(), vips_magickload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pdfload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "pdfload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_pdfload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page, numbered from zero - * * @n: %gint, load this many pages - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * - * Read a PDF-formatted memory block into a VIPS image. Exactly as - * vips_pdfload(), but read from a memory buffer. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_pdfload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "pdfload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_svgload: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * - * Render a SVG file into a VIPS image. Rendering uses the librsvg library - * and should be fast. - * - * Use @dpi to set the rendering resolution. The default is 72. Alternatively, - * you can scale the rendering from the default 1 point == 1 pixel by @scale. - * - * This function only reads the image header and does not render any pixel - * data. Rendering occurs when pixels are accessed. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_svgload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "svgload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_svgload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * - * Read a SVG-formatted memory block into a VIPS image. Exactly as - * vips_svgload(), but read from a memory buffer. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_svgload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_svgload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "svgload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} - -/** - * vips_gifload: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %ginit, page (frame) to read - * - * Read a GIF file into a VIPS image. Rendering uses the giflib library. - * - * Use @page to set page number (frame number) to read. - * - * The whole GIF is parsed and read into memory on header access, the whole - * GIF is rendered on first pixel access. - * - * See also: vips_image_new_from_file(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_gifload( const char *filename, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "gifload", ap, filename, out ); - va_end( ap ); - - return( result ); -} - -/** - * vips_gifload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %ginit, page (frame) to read - * - * Read a GIF-formatted memory block into a VIPS image. Exactly as - * vips_gifload(), but read from a memory buffer. - * - * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. - * - * See also: vips_gifload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_gifload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsBlob *blob; - int result; - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "gifload_buffer", ap, blob, out ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - return( result ); -} diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index 5fc317db..421e5df3 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -42,8 +42,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_GIFLIB - #include #include #include @@ -55,6 +53,8 @@ #include #include +#ifdef HAVE_GIFLIB + #include /* giflib 5 is rather different :-( functions have error returns and there's @@ -734,5 +734,80 @@ vips_foreign_load_gif_buffer_init( VipsForeignLoadGifBuffer *buffer ) { } -#endif /*HAVE_RSVG*/ +#endif /*HAVE_GIFLIB*/ + +/** + * vips_gifload: + * @filename: file to load + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: %ginit, page (frame) to read + * + * Read a GIF file into a VIPS image. Rendering uses the giflib library. + * + * Use @page to set page number (frame number) to read. + * + * The whole GIF is parsed and read into memory on header access, the whole + * GIF is rendered on first pixel access. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_gifload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "gifload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_gifload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: %ginit, page (frame) to read + * + * Read a GIF-formatted memory block into a VIPS image. Exactly as + * vips_gifload(), but read from a memory buffer. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_gifload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_gifload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "gifload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index a07590d2..9b1e0711 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -43,13 +43,17 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_JPEG - #include #include #include #include +#include +#include +#include + +#ifdef HAVE_JPEG + #ifdef HAVE_EXIF #ifdef UNTAGGED_EXIF #include @@ -64,10 +68,6 @@ #endif /*UNTAGGED_EXIF*/ #endif /*HAVE_EXIF*/ -#include -#include -#include - #include "vipsjpeg.h" typedef struct _VipsForeignLoadJpeg { @@ -343,3 +343,122 @@ vips_foreign_load_jpeg_buffer_init( VipsForeignLoadJpegBuffer *buffer ) } #endif /*HAVE_JPEG*/ + +/** + * vips_jpegload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @shrink: %gint, shrink by this much on load + * * @fail: %gboolean, fail on warnings + * * @autorotate: %gboolean, use exif Orientation tag to rotate the image during load + * + * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, + * including CMYK and YCbCr. + * + * @shrink means shrink by this integer factor during load. Possible values + * are 1, 2, 4 and 8. Shrinking during read is very much faster than + * decompressing the whole image and then shrinking later. + * + * Setting @fail to %TRUE 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. + * + * Setting @autorotate to %TRUE will make the loader interpret the EXIF + * Orientation field and automatically rotate the image appropriately during + * load. After rotation, the Orientation tag will be removed to prevent + * accidental double-rotation. + * + * Using @autorotate can be much slower than doing the rotate later + * in processing. See vips_autorot(). + * + * Example: + * + * |[ + * vips_jpegload( "fred.jpg", &out, + * "shrink", 8, + * "fail", TRUE, + * NULL ); + * ]| + * + * 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 + * @VIPS_META_ICC_NAME ("icc-profile-data"). You need to use something like + * vips_icc_import() to get CIE values from the file. + * + * EXIF metadata is attached as @VIPS_META_EXIF_NAME ("exif-data"), IPCT as + * @VIPS_META_IPCT_NAME ("ipct-data"), and XMP as VIPS_META_XMP_NAME + * ("xmp-data"). + * + * The int metadata item "jpeg-multiscan" is set to the result of + * jpeg_has_multiple_scans(). Interlaced jpeg images need a large amount of + * memory to load, so this field gives callers a chance to handle these + * images differently. + * + * The EXIF thumbnail, if present, is attached to the image as + * "jpeg-thumbnail-data". See vips_image_get_blob(). + * + * This function only reads the image header and does not decompress any pixel + * data. Decompression only occurs when pixels are accessed. + * + * See also: vips_jpegload_buffer(), vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "jpegload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_jpegload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @shrink: %gint, shrink by this much on load + * * @fail: %gboolean, fail on warnings + * + * Read a JPEG-formatted memory block into a VIPS image. Exactly as + * vips_jpegload(), but read from a memory buffer. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_jpegload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "jpegload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} diff --git a/libvips/foreign/jpegsave.c b/libvips/foreign/jpegsave.c index 4fac9b99..5e9cfff5 100644 --- a/libvips/foreign/jpegsave.c +++ b/libvips/foreign/jpegsave.c @@ -41,13 +41,17 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_JPEG - #include #include #include #include +#include +#include +#include + +#ifdef HAVE_JPEG + #ifdef HAVE_EXIF #ifdef UNTAGGED_EXIF #include @@ -62,10 +66,6 @@ #endif /*UNTAGGED_EXIF*/ #endif /*HAVE_EXIF*/ -#include -#include -#include - #include "vipsjpeg.h" typedef struct _VipsForeignSaveJpeg { @@ -310,7 +310,9 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object ) jpeg->optimize_scans, jpeg->quant_table ) ) return( -1 ); - blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); + /* obuf is a g_free() buffer, not vips_free(). + */ + blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); g_object_set( file, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); @@ -405,3 +407,210 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime ) } #endif /*HAVE_JPEG*/ + +/** + * vips_jpegsave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: %gint, quality factor + * * @profile: filename of ICC profile to attach + * * @optimize_coding: %gboolean, compute optimal Huffman coding tables + * * @interlace: %gboolean, write an interlaced (progressive) jpeg + * * @strip: %gboolean, remove all metadata from image + * * @no-subsample: %gboolean, disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index + * + * Write a VIPS image to a file as JPEG. + * + * Use @Q to set the JPEG compression factor. Default 75. + * + * Use @profile to give the filename of a profile to be embedded in the JPEG. + * 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 and the VIPS header + * contains an ICC profile named VIPS_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. + * + * EXIF data is constructed from @VIPS_META_EXIF_NAME ("exif-data"), then + * modified with any other related tags on the image before being written to + * the file. + * + * IPCT as @VIPS_META_IPCT_NAME ("ipct-data") and XMP as VIPS_META_XMP_NAME + * ("xmp-data") are coded and attached. + * + * If @optimize_coding is set, the Huffman tables are optimised. This is + * sllightly slower and produces slightly smaller files. + * + * If @interlace is set, the jpeg files will be interlaced (progressive jpeg, + * in jpg parlance). These files may be better for display over a slow network + * conection, but need much more memory to encode and decode. + * + * If @strip is set, no EXIF data, IPCT data, ICC profile or XMP metadata is + * written into the output file. + * + * If @no-subsample is set, chrominance subsampling is disabled. This will + * improve quality at the cost of larger file size. Useful for high Q factors. + * + * If @trellis_quant is set and the version of libjpeg supports it + * (e.g. mozjpeg >= 3.0), apply trellis quantisation to each 8x8 block. + * Reduces file size but increases compression time. + * + * If @overshoot_deringing is set and the version of libjpeg supports it + * (e.g. mozjpeg >= 3.0), apply overshooting to samples with extreme values + * for example 0 and 255 for 8-bit. Overshooting may reduce ringing artifacts + * from compression, in particular in areas where black text appears on a + * white background. + * + * If @optimize_scans is set and the version of libjpeg supports it + * (e.g. mozjpeg >= 3.0), split the spectrum of DCT coefficients into + * separate scans. Reduces file size but increases compression time. + * + * If @quant_table is set and the version of libjpeg supports it + * (e.g. mozjpeg >= 3.0) it selects the quantization table to use: + * + * * 0 — Tables from JPEG Annex K (vips and libjpeg default) + * * 1 — Flat table + * * 2 — Table tuned for MSSIM on Kodak image set + * * 3 — Table from ImageMagick by N. Robidoux (current mozjpeg default) + * * 4 — Table tuned for PSNR-HVS-M on Kodak image set + * * 5 — Table from Relevance of Human Vision to JPEG-DCT Compression (1992) + * * 6 — Table from DCTune Perceptual Optimization of Compressed Dental + * X-Rays (1997) + * * 7 — Table from A Visual Detection Model for DCT Coefficient + * Quantization (1993) + * * 8 — Table from An Improved Detection Model for DCT Coefficient + * Quantization (1993) + * + * Quantization table 0 is the default in vips and libjpeg(-turbo), but it + * tends to favor detail over color accuracy, producting colored patches and + * stripes as well as heavy banding in flat areas at high compression ratios. + * Quantization table 2 is a good candidate to try if the default quantization + * table produces banding or color shifts and is well suited for hires images. + * Quantization table 3 is the default in mozjpeg and has been tuned to produce + * good results at the default quality setting; banding at high compression. + * Quantization table 4 is the most accurate at the cost of compression ratio. + * Tables 5-7 are based on older research papers, but generally achieve worse + * compression ratios and/or quality than 2 or 4. + * + * See also: vips_jpegsave_buffer(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegsave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "jpegsave", ap, in, filename ); + va_end( ap ); + + return( result ); +} + +/** + * vips_jpegsave_buffer: + * @in: image to save + * @buf: return output buffer here + * @len: return output length here + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: JPEG quality factor + * * @profile: attach this ICC profile + * * @optimize_coding: compute optimal Huffman coding tables + * * @interlace: write an interlaced (progressive) jpeg + * * @strip: remove all metadata from image + * * @no-subsample: disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index + * + * As vips_jpegsave(), but save to a memory buffer. + * + * The address of the buffer is returned in @obuf, the length of the buffer in + * @olen. You are responsible for freeing the buffer with g_free() when you + * are done with it. + * + * See also: vips_jpegsave(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + area = NULL; + + va_start( ap, len ); + result = vips_call_split( "jpegsave_buffer", ap, in, &area ); + va_end( ap ); + + if( !result && + area ) { + if( buf ) { + *buf = area->data; + area->free_fn = NULL; + } + if( len ) + *len = area->length; + + vips_area_unref( area ); + } + + return( result ); +} + +/** + * vips_jpegsave_mime: + * @in: image to save + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: JPEG quality factor + * * @profile: attach this ICC profile + * * @optimize_coding: compute optimal Huffman coding tables + * * @strip: remove all metadata from image + * * @no-subsample: disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index + * + * As vips_jpegsave(), but save as a mime jpeg on stdout. + * + * See also: vips_jpegsave(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegsave_mime( VipsImage *in, ... ) +{ + va_list ap; + int result; + + va_start( ap, in ); + result = vips_call_split( "jpegsave_mime", ap, in ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/magickload.c b/libvips/foreign/magickload.c index 4603c52c..d533e2c9 100644 --- a/libvips/foreign/magickload.c +++ b/libvips/foreign/magickload.c @@ -46,8 +46,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_MAGICK - #include #include #include @@ -56,6 +54,8 @@ #include #include +#ifdef HAVE_MAGICK + #include "magick.h" typedef struct _VipsForeignLoadMagick { @@ -298,3 +298,91 @@ vips_foreign_load_magick_buffer_init( VipsForeignLoadMagickBuffer *buffer ) } #endif /*HAVE_MAGICK*/ + +/** + * vips_magickload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @all_frames: %gboolean, load all frames in sequence + * * @density: string, canvas resolution for rendering vector formats like SVG + * + * Read in an image using libMagick, the ImageMagick library. This library can + * read more than 80 file formats, including SVG, BMP, EPS, DICOM and many + * others. + * The reader can handle any ImageMagick image, including the float and double + * formats. It will work with any quantum size, including HDR. Any metadata + * attached to the libMagick image is copied on to the VIPS image. + * + * The reader should also work with most versions of GraphicsMagick. See the + * "--with-magickpackage" configure option. + * + * Normally it will only load the first image in a many-image sequence (such + * as a GIF). Set @all_frames to true to read the whole image sequence. + * + * @density is "WxH" in DPI, e.g. "600x300" or "600" (default is "72x72"). See + * the [density + * docs](http://www.imagemagick.org/script/command-line-options.php#density) + * on the imagemagick website. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_magickload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "magickload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_magickload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @all_frames: %gboolean, load all frames in sequence + * * @density: string, canvas resolution for rendering vector formats like SVG + * + * Read an image memory block using libMagick into a VIPS image. Exactly as + * vips_magickload(), but read from a memory source. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_magickload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_magickload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "magickload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} diff --git a/libvips/foreign/matload.c b/libvips/foreign/matload.c index 4423894a..e33a2fd9 100644 --- a/libvips/foreign/matload.c +++ b/libvips/foreign/matload.c @@ -42,8 +42,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_MATIO - #include #include #include @@ -52,6 +50,8 @@ #include #include +#ifdef HAVE_MATIO + #include "matlab.h" typedef struct _VipsForeignLoadMat { @@ -143,3 +143,33 @@ vips_foreign_load_mat_init( VipsForeignLoadMat *mat ) } #endif /*HAVE_MATIO*/ + +/** + * vips_matload: + * @filename: file to load + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Read a Matlab save file into a VIPS image. + * + * This operation searches the save + * file for the first array variable with between 1 and 3 dimensions and loads + * it as an image. It will not handle complex images. It does not handle + * sparse matrices. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_matload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "matload", ap, filename, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/openexrload.c b/libvips/foreign/openexrload.c index cc0a432b..94a32287 100644 --- a/libvips/foreign/openexrload.c +++ b/libvips/foreign/openexrload.c @@ -40,8 +40,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_OPENEXR - #include #include #include @@ -50,6 +48,8 @@ #include #include +#ifdef HAVE_OPENEXR + #include "openexr2vips.h" typedef struct _VipsForeignLoadOpenexr { @@ -154,3 +154,35 @@ vips_foreign_load_openexr_init( VipsForeignLoadOpenexr *openexr ) } #endif /*HAVE_OPENEXR*/ + +/** + * vips_openexrload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * 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: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_openexrload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "openexrload", ap, filename, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/openslideload.c b/libvips/foreign/openslideload.c index 856dc57a..515f208f 100644 --- a/libvips/foreign/openslideload.c +++ b/libvips/foreign/openslideload.c @@ -47,8 +47,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_OPENSLIDE - #include #include #include @@ -57,6 +55,8 @@ #include #include +#ifdef HAVE_OPENSLIDE + #include "openslide2vips.h" typedef struct _VipsForeignLoadOpenslide { @@ -219,3 +219,50 @@ vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide ) } #endif /*HAVE_OPENSLIDE*/ + +/** + * vips_openslideload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @level: load this level + * * @associated: load this associated image + * * @autocrop: crop to image bounds + * + * Read a virtual slide supported by the OpenSlide library into a VIPS image. + * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, + * and Ventana formats. + * + * To facilitate zooming, virtual slide formats include multiple scaled-down + * versions of the high-resolution image. These are typically called + * "levels". By default, vips_openslideload() reads the highest-resolution + * level (level 0). Set @level to the level number you want. + * + * In addition to the slide image itself, virtual slide formats sometimes + * include additional images, such as a scan of the slide's barcode. + * OpenSlide calls these "associated images". To read an associated image, + * set @associated to the image's name. + * A slide's associated images are listed in the + * "slide-associated-images" metadata item. + * + * The output of this operator is always RGBA. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_openslideload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "openslideload", ap, filename, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index a97fc952..dd3b5ddc 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -42,8 +42,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_POPPLER - #include #include #include @@ -53,6 +51,8 @@ #include #include +#ifdef HAVE_POPPLER + #include #include @@ -649,3 +649,113 @@ vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer ) #endif /*HAVE_POPPLER*/ +/** + * vips_pdfload: + * @filename: file to load + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: %gint, load this page, numbered from zero + * * @n: %gint, load this many pages + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor + * + * Render a PDF file into a VIPS image. Rendering uses the libpoppler library + * and should be fast. + * + * The output image is always RGBA --- CMYK PDFs will be + * converted. If you need CMYK bitmaps, you should use vips_magickload() + * instead. + * + * Rendering is progressive, that is, the image is rendered in strips equal in + * height to the tile height. If your PDF contains large image files and + * they span several strips in the output image, they will be decoded multiple + * times. To fix this, increase the the tile height, for example: + * + * |[ + * vips copy huge.pdf x.png --vips-tile-height=1024 + * ]| + * + * Will process images in 1024-pixel high strips, potentially much faster, + * though of course also using a lot more memory. + * + * Use @page to select a page to render, numbering from zero. + * + * Use @n to select the number of pages to render. The default is 1. Pages are + * rendered in a vertical column, with each individual page aligned to the + * left. Set to -1 to mean "until the end of the document". Use vips_grid() + * to change page layout. + * + * Use @dpi to set the rendering resolution. The default is 72. Alternatively, + * you can scale the rendering from the default 1 point == 1 pixel by + * setting @scale. + * + * The operation fills a number of header fields with metadata, for example + * "pdf-author". They may be useful. + * + * This function only reads the image header and does not render any pixel + * data. Rendering occurs when pixels are accessed. + * + * See also: vips_image_new_from_file(), vips_magickload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pdfload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "pdfload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_pdfload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: %gint, load this page, numbered from zero + * * @n: %gint, load this many pages + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor + * + * Read a PDF-formatted memory block into a VIPS image. Exactly as + * vips_pdfload(), but read from a memory buffer. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_pdfload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "pdfload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} + diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index 63f5ee46..4bb7cdfc 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -223,3 +223,72 @@ vips_foreign_load_png_buffer_init( VipsForeignLoadPngBuffer *png ) #endif /*HAVE_PNG*/ +/** + * vips_pngload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Read a PNG file into a VIPS image. It can read all png images, including 8- + * and 16-bit images, 1 and 3 channel, with and without an alpha channel. + * + * Any ICC profile is read and attached to the VIPS image. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pngload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "pngload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_pngload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Read a PNG-formatted memory block into a VIPS image. It can read all png + * images, including 8- and 16-bit images, 1 and 3 channel, with and without + * an alpha channel. + * + * Any ICC profile is read and attached to the VIPS image. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_pngload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "pngload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} + + diff --git a/libvips/foreign/pngsave.c b/libvips/foreign/pngsave.c index 777d07f1..5b9e533b 100644 --- a/libvips/foreign/pngsave.c +++ b/libvips/foreign/pngsave.c @@ -43,14 +43,14 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_PNG - #include #include #include #include +#ifdef HAVE_PNG + #include "vipspng.h" typedef struct _VipsForeignSavePng { @@ -226,7 +226,10 @@ vips_foreign_save_png_buffer_build( VipsObject *object ) png->compression, png->interlace, png->profile, png->filter ) ) return( -1 ); - blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); + /* vips__png_write_buf() makes a buffer that needs g_free(), not + * vips_free(). + */ + blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); g_object_set( object, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); @@ -260,3 +263,110 @@ vips_foreign_save_png_buffer_init( VipsForeignSavePngBuffer *buffer ) } #endif /*HAVE_PNG*/ + +/** + * vips_pngsave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @compression: compression level + * * @interlace: interlace image + * * @profile: ICC profile to embed + * * @filter: #VipsForeignPngFilter row filter flag(s) + * + * Write a VIPS image to a file as PNG. + * + * @compression means compress with this much effort (0 - 9). Default 6. + * + * Set @interlace to %TRUE to interlace the image with ADAM7 + * interlacing. Beware + * than an interlaced PNG can be up to 7 times slower to write than a + * non-interlaced image. + * + * Use @profile to give the filename of a profile to be embedded in the PNG. + * 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 @profile is specified and the VIPS header + * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the + * profile from the VIPS header will be attached. + * + * Use @filter to specify one or more filters (instead of adaptive filtering), + * see #VipsForeignPngFilter. + * + * The image is automatically converted to RGB, RGBA, Monochrome or Mono + + * alpha before saving. Images with more than one byte per band element are + * saved as 16-bit PNG, others are saved as 8-bit PNG. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pngsave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "pngsave", ap, in, filename ); + va_end( ap ); + + return( result ); +} + +/** + * vips_pngsave_buffer: + * @in: image to save + * @buf: return output buffer here + * @len: return output length here + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @compression: compression level + * * @interlace: interlace image + * * @profile: ICC profile to embed + * * @filter: libpng row filter flag(s) + * + * As vips_pngsave(), but save to a memory buffer. + * + * The address of the buffer is returned in @buf, the length of the buffer in + * @len. You are responsible for freeing the buffer with g_free() when you + * are done with it. + * + * See also: vips_pngsave(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + area = NULL; + + va_start( ap, len ); + result = vips_call_split( "pngsave_buffer", ap, in, &area ); + va_end( ap ); + + if( !result && + area ) { + if( buf ) { + *buf = area->data; + area->free_fn = NULL; + } + if( len ) + *len = area->length; + + vips_area_unref( area ); + } + + return( result ); +} diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index 15ec3abe..2994f308 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -16,7 +16,7 @@ * - put the reader globals into a struct so we can have many active * readers * 23/5/16 - * - Add buffer save functions + * - add buffer save functions */ /* @@ -817,13 +817,18 @@ scanline_read( Buffer *buffer, COLR *scanline, int width ) /* write an RLE scanline. Write magic header. */ static void -rle_scanline_write( COLR *scanline, int width, unsigned char *buffer, int *buffer_pos ) +rle_scanline_write( COLR *scanline, int width, + unsigned char *buffer, int *length ) { -#define PUTC( CH ) { \ - buffer[(*buffer_pos)++] = (CH); \ - g_assert( *buffer_pos <= MAX_LINE ); \ -} int i, j, beg, cnt; + +#define PUTC( CH ) { \ + buffer[(*length)++] = (CH); \ + g_assert( *length <= MAX_LINE ); \ +} + + *length = 0; + PUTC( 2 ); PUTC( 2 ); PUTC( width >> 8 ); @@ -831,7 +836,7 @@ rle_scanline_write( COLR *scanline, int width, unsigned char *buffer, int *buffe for( i = 0; i < 4; i++ ) { for( j = 0; j < width; ) { - /* Not needed, but keeps gcc used-before-set wsrning + /* Not needed, but keeps gcc used-before-set warning * quiet. */ cnt = 1; @@ -883,20 +888,21 @@ rle_scanline_write( COLR *scanline, int width, unsigned char *buffer, int *buffe static int scanline_write( COLR *scanline, int width, FILE *fp ) { - unsigned char buffer[MAX_LINE]; - int buffer_pos = 0; - if( width < MINELEN || width > MAXELEN ) /* Write as a flat scanline. */ return( fwrite( scanline, sizeof( COLR ), width, fp ) - width ); + else { + /* An RLE scanline. + */ + unsigned char buffer[MAX_LINE]; + int length; - /* An RLE scanline. - */ - rle_scanline_write( scanline, width, buffer, &buffer_pos ); + rle_scanline_write( scanline, width, buffer, &length ); - return( fwrite( buffer, 1, buffer_pos, fp ) - buffer_pos ); + return( fwrite( buffer, 1, length, fp ) - length ); + } } /* What we track during radiance file read. @@ -1165,9 +1171,14 @@ vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind ) */ typedef struct { VipsImage *in; - char *filename; + char *filename; FILE *fout; + + char *buf; + size_t len; + size_t alloc; + char format[256]; double expos; COLOR colcor; @@ -1177,22 +1188,17 @@ typedef struct { } Write; static void -write_destroy_file( Write *write ) +write_destroy( Write *write ) { VIPS_FREE( write->filename ); VIPS_FREEF( fclose, write->fout ); + VIPS_FREE( write->buf ); vips_free( write ); } -static void -write_destroy( Write *write ) -{ - vips_free( write ); -} - static Write * -write_new( VipsImage *in) +write_new( VipsImage *in ) { Write *write; int i; @@ -1201,6 +1207,14 @@ write_new( VipsImage *in) return( NULL ); write->in = in; + + write->filename = NULL; + write->fout = NULL; + + write->buf = NULL; + write->len = 0; + write->alloc = 0; + strcpy( write->format, COLRFMT ); write->expos = 1.0; for( i = 0; i < 3; i++ ) @@ -1254,7 +1268,7 @@ vips2rad_make_header( Write *write ) static int vips2rad_put_header( Write *write ) { - vips2rad_make_header(write); + vips2rad_make_header( write ); fprintf( write->fout, "#?RADIANCE\n" ); @@ -1317,124 +1331,99 @@ vips__rad_save( VipsImage *in, const char *filename ) !write->fout || vips2rad_put_header( write ) || vips2rad_put_data( write ) ) { - write_destroy_file( write ); + write_destroy( write ); return( -1 ); } - write_destroy_file( write ); + write_destroy( write ); return( 0 ); } -typedef struct _WriteBuf { - char *buf; - size_t len; - size_t alloc; -} WriteBuf; - static void -write_buf_free( WriteBuf *wbuf ) +write_buf_grow( Write *write, size_t grow_len ) { - VIPS_FREE( wbuf->buf ); - VIPS_FREE( wbuf ); -} + size_t new_len = write->len + grow_len; -static WriteBuf * -write_buf_new( void ) -{ - WriteBuf *wbuf; + if( new_len > write->alloc ) { + size_t proposed_alloc = (16 + write->alloc) * 3 / 2; - if( !(wbuf = VIPS_NEW( NULL, WriteBuf )) ) - return( NULL ); + write->alloc = VIPS_MAX( proposed_alloc, new_len ); - wbuf->buf = NULL; - wbuf->len = 0; - wbuf->alloc = 0; - - return( wbuf ); -} - -static void -write_buf_grow( WriteBuf *wbuf, size_t grow_len ) -{ - size_t new_len = wbuf->len + grow_len; - - if( new_len > wbuf->alloc ) { - size_t proposed_alloc = (16 + wbuf->alloc) * 3 / 2; - - wbuf->alloc = VIPS_MAX( proposed_alloc, new_len ); - - /* There's no vips_realloc(), so we call g_realloc() directly. - * This is safe, since vips_malloc() / vips_free() are wrappers - * over g_malloc() / g_free(). - * - * FIXME: add vips_realloc(). + /* Our caller must free with g_free(), so we must use + * g_realloc(). */ - wbuf->buf = g_realloc( wbuf->buf, wbuf->alloc ); + write->buf = g_realloc( write->buf, write->alloc ); VIPS_DEBUG_MSG( "write_buf_grow: grown to %zd bytes\n", - wbuf->alloc ); + write->alloc ); } } static void -bprintf( WriteBuf *wbuf, const char *fmt, ... ) +bprintf( Write *write, const char *fmt, ... ) { - int length = 0; - char *write_start = NULL; + int length; + char *write_start; va_list ap; - /* Determine required size */ - va_start(ap, fmt); - length = vsnprintf(write_start, length, fmt, ap); - va_end(ap); + /* Determine required size. + */ + va_start( ap, fmt ); + length = vsnprintf( NULL, 0, fmt, ap ); + va_end( ap ); - write_buf_grow( wbuf, length + 1 ); + write_buf_grow( write, length + 1 ); - write_start = wbuf->buf + wbuf->len; + write_start = write->buf + write->len; - va_start(ap, fmt); - length = vsnprintf(write_start, length + 1, fmt, ap); - va_end(ap); + va_start( ap, fmt ); + length = vsnprintf( write_start, length + 1, fmt, ap ); + va_end( ap ); - wbuf->len += length; + write->len += length; - g_assert( wbuf->len <= wbuf->alloc ); + g_assert( write->len <= write->alloc ); } -#define bputformat(s,wb) bprintf(wb, "%s%s\n", FMTSTR, s) +#define bputformat( write, s ) \ + bprintf( write, "%s%s\n", FMTSTR, s ) -#define bputexpos(ex,wb) bprintf(wb,"%s%e\n",EXPOSSTR,ex) +#define bputexpos( write, ex ) \ + bprintf( write, "%s%e\n", EXPOSSTR, ex ) -#define bputcolcor(cc,wb) bprintf(wb,"%s %f %f %f\n",COLCORSTR, \ - (cc)[RED],(cc)[GRN],(cc)[BLU]) +#define bputcolcor( write, cc ) \ + bprintf( write, "%s %f %f %f\n", \ + COLCORSTR, (cc)[RED], (cc)[GRN], (cc)[BLU] ) -#define bputaspect(pa,wb) bprintf(wb,"%s%f\n",ASPECTSTR,pa) +#define bputaspect( write, pa ) \ + bprintf( write, "%s%f\n", ASPECTSTR, pa ) -#define bputprims(p,wb) bprintf(wb, \ - "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",\ - PRIMARYSTR, \ - (p)[RED][CIEX],(p)[RED][CIEY], \ - (p)[GRN][CIEX],(p)[GRN][CIEY], \ - (p)[BLU][CIEX],(p)[BLU][CIEY], \ - (p)[WHT][CIEX],(p)[WHT][CIEY]) +#define bputprims( write, p ) \ + bprintf( write, "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n", \ + PRIMARYSTR, \ + (p)[RED][CIEX], (p)[RED][CIEY], \ + (p)[GRN][CIEX], (p)[GRN][CIEY], \ + (p)[BLU][CIEX], (p)[BLU][CIEY], \ + (p)[WHT][CIEX], (p)[WHT][CIEY] ) -#define bputsresolu(rs,wb) bprintf(wb,"%s",resolu2str(resolu_buf,rs)) +#define bputsresolu( write, rs ) \ + bprintf( write, "%s", resolu2str( resolu_buf, rs ) ) static int -vips2rad_put_header_buf( WriteBuf *wbuf, Write *write ) +vips2rad_put_header_buf( Write *write ) { - vips2rad_make_header(write); + vips2rad_make_header( write ); - bprintf( wbuf, "#?RADIANCE\n" ); + bprintf( write, "#?RADIANCE\n" ); - bputformat( write->format, wbuf ); - bputexpos( write->expos, wbuf ); - bputcolcor( write->colcor, wbuf ); - bprintf( wbuf, "SOFTWARE=vips %s\n", vips_version_string() ); - bputaspect( write->aspect, wbuf ); - bputprims( write->prims, wbuf ); - bprintf( wbuf, "\n" ); - bputsresolu( &write->rs, wbuf ); + bputformat( write, write->format ); + bputexpos( write, write->expos ); + bputcolcor( write, write->colcor ); + bprintf( write, "SOFTWARE=vips %s\n", vips_version_string() ); + bputaspect( write, write->aspect ); + bputprims( write, write->prims ); + bprintf( write, "\n" ); + bputsresolu( write, &write->rs ); return( 0 ); } @@ -1442,41 +1431,42 @@ vips2rad_put_header_buf( WriteBuf *wbuf, Write *write ) /* Write a single scanline to buffer. */ static int -scanline_write_buf( COLR *scanline, int width, WriteBuf *wbuf ) +scanline_write_buf( Write *write, COLR *scanline, int width ) { - int buffer_pos = 0; + unsigned char *buffer; - write_buf_grow( wbuf, MAX_LINE ); - unsigned char *buffer = (unsigned char *) wbuf->buf + wbuf->len; + write_buf_grow( write, MAX_LINE ); + buffer = (unsigned char *) write->buf + write->len; if( width < MINELEN || width > MAXELEN ) { /* Write as a flat scanline. */ memcpy( buffer, scanline, sizeof( COLR ) * width ); - wbuf->len += sizeof( COLR ) * width; + write->len += sizeof( COLR ) * width; + } + else { + int length; - return( 0 ); + /* An RLE scanline. + */ + rle_scanline_write( scanline, width, buffer, &length ); + write->len += length; } - /* An RLE scanline. - */ - rle_scanline_write( scanline, width, buffer, &buffer_pos ); - - wbuf->len += buffer_pos; return( 0 ); } static int vips2rad_put_data_block_buf( VipsRegion *region, VipsRect *area, void *a ) { - WriteBuf *wbuf = (WriteBuf *) a; + Write *write = (Write *) a; int i; for( i = 0; i < area->height; i++ ) { VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i ); - if( scanline_write_buf( (COLR *) p, area->width, wbuf ) ) + if( scanline_write_buf( write, (COLR *) p, area->width ) ) return( -1 ); } @@ -1484,9 +1474,9 @@ vips2rad_put_data_block_buf( VipsRegion *region, VipsRect *area, void *a ) } static int -vips2rad_put_data_buf( WriteBuf *wbuf, Write *write ) +vips2rad_put_data_buf( Write *write ) { - if( vips_sink_disc( write->in, vips2rad_put_data_block_buf, wbuf ) ) + if( vips_sink_disc( write->in, vips2rad_put_data_block_buf, write ) ) return( -1 ); return( 0 ); @@ -1496,7 +1486,6 @@ int vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen ) { Write *write; - WriteBuf *wbuf; #ifdef DEBUG printf( "vips2rad: writing to buffer\n" ); @@ -1505,27 +1494,22 @@ vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen ) if( vips_image_pio_input( in ) || vips_check_coding_rad( "vips2rad", in ) ) return( -1 ); - if( !(wbuf = write_buf_new()) ) + if( !(write = write_new( in )) ) return( -1 ); - if( !(write = write_new( in )) ) { - write_buf_free( wbuf ); + + if( vips2rad_put_header_buf( write ) || + vips2rad_put_data_buf( write ) ) { + write_destroy( write ); return( -1 ); } - if( vips2rad_put_header_buf( wbuf, write ) || - vips2rad_put_data_buf( wbuf, write ) ) { - write_destroy( write ); - write_buf_free( wbuf ); - return( -1 ); - } + *obuf = write->buf; + write->buf = NULL; + if( olen ) + *olen = write->len; + write_destroy( write ); - *obuf = wbuf->buf; - wbuf->buf = NULL; - if( olen ) - *olen = wbuf->len; - - write_buf_free( wbuf ); return( 0 ); } diff --git a/libvips/foreign/radsave.c b/libvips/foreign/radsave.c index e6b54412..6727c5fd 100644 --- a/libvips/foreign/radsave.c +++ b/libvips/foreign/radsave.c @@ -3,7 +3,7 @@ * 2/12/11 * - wrap a class around the rad writer * 23/5/16 - * - split into file and buffer save classes + * - split into file and buffer save classes */ /* @@ -190,7 +190,10 @@ vips_foreign_save_rad_buffer_build( VipsObject *object ) if( vips__rad_save_buf( save->ready, &obuf, &olen ) ) return( -1 ); - blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); + /* vips__rad_save_buf() makes a buffer that needs g_free(), not + * vips_free(). + */ + blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); g_object_set( object, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); @@ -223,7 +226,6 @@ vips_foreign_save_rad_buffer_init( VipsForeignSaveRadBuffer *buffer ) { } - #endif /*HAVE_RADIANCE*/ /** @@ -262,8 +264,8 @@ vips_radsave( VipsImage *in, const char *filename, ... ) * * As vips_radsave(), but save to a memory buffer. * - * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you + * The address of the buffer is returned in @buf, the length of the buffer in + * @len. You are responsible for freeing the buffer with g_free() when you * are done with it. * * See also: vips_radsave(), vips_image_write_to_file(). diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 7b41e31a..d7983748 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -40,8 +40,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_RSVG - #include #include #include @@ -52,6 +50,8 @@ #include #include +#ifdef HAVE_RSVG + #include #include @@ -453,3 +453,82 @@ vips_foreign_load_svg_buffer_init( VipsForeignLoadSvgBuffer *buffer ) #endif /*HAVE_RSVG*/ +/** + * vips_svgload: + * @filename: file to load + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor + * + * Render a SVG file into a VIPS image. Rendering uses the librsvg library + * and should be fast. + * + * Use @dpi to set the rendering resolution. The default is 72. Alternatively, + * you can scale the rendering from the default 1 point == 1 pixel by @scale. + * + * This function only reads the image header and does not render any pixel + * data. Rendering occurs when pixels are accessed. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_svgload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "svgload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_svgload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor + * + * Read a SVG-formatted memory block into a VIPS image. Exactly as + * vips_svgload(), but read from a memory buffer. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_svgload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_svgload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "svgload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} + diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index 853e63f0..c745b90f 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -40,8 +40,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_TIFF - #include #include #include @@ -50,6 +48,8 @@ #include #include +#ifdef HAVE_TIFF + #include "tiff.h" typedef struct _VipsForeignLoadTiff { @@ -280,3 +280,81 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer ) } #endif /*HAVE_TIFF*/ + +/** + * vips_tiffload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: int, load this page + * + * Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader, + * with extensions for tiled images, multipage images, LAB colour space, + * pyramidal images and JPEG compression. including CMYK and YCbCr. + * + * @page means load this page from the file. By default the first page (page + * 0) is read. + * + * Any ICC profile is read and attached to the VIPS image. Any XMP metadata is + * read and attached to the image. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_tiffload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "tiffload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_tiffload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @page: %gint, load this page + * + * Read a TIFF-formatted memory block into a VIPS image. Exactly as + * vips_tiffload(), but read from a memory source. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_tiffload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "tiffload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} diff --git a/libvips/foreign/tiffsave.c b/libvips/foreign/tiffsave.c index 50e8444d..b0afda48 100644 --- a/libvips/foreign/tiffsave.c +++ b/libvips/foreign/tiffsave.c @@ -47,14 +47,14 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_TIFF - #include #include #include #include +#ifdef HAVE_TIFF + #include "tiff.h" typedef struct _VipsForeignSaveTiff { @@ -296,3 +296,103 @@ vips_foreign_save_tiff_init( VipsForeignSaveTiff *tiff ) } #endif /*HAVE_TIFF*/ + +/** + * vips_tiffsave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @compression: use this #VipsForeignTiffCompression + * * @Q: %gint quality factor + * * @predictor: use this #VipsForeignTiffPredictor + * * @profile: filename of ICC profile to attach + * * @tile: set %TRUE to write a tiled tiff + * * @tile_width: %gint for tile size + * * @tile_height: %gint for tile size + * * @pyramid: set %TRUE to write an image pyramid + * * @squash: set %TRUE to squash 8-bit images down to 1 bit + * * @miniswhite: set %TRUE to write 1-bit images as MINISWHITE + * * @resunit: #VipsForeignTiffResunit for resolution unit + * * @xres: %gdouble horizontal resolution in pixels/mm + * * @yres: %gdouble vertical resolution in pixels/mm + * * @bigtiff: set %TRUE to write a BigTiff file + * + * Write a VIPS image to a file as TIFF. + * + * Use @compression to set the tiff compression. Currently jpeg, packbits, + * fax4, lzw, none and deflate are supported. The default is no compression. + * JPEG compression is a good lossy compressor for photographs, packbits is + * good for 1-bit images, and deflate is the best lossless compression TIFF + * can do. LZW has patent problems and is no longer recommended. + * + * Use @Q to set the JPEG compression factor. Default 75. + * + * Use @predictor to set the predictor for lzw and deflate compression. + * + * Predictor is not set by default. There are three predictor values recognised + * at the moment (2007, July): 1 is no prediction, 2 is a horizontal + * differencing and 3 is a floating point predictor. Refer to the libtiff + * specifications for further discussion of various predictors. In short, + * predictor helps to better compress image, especially in case of digital + * photos or scanned images and bit depths > 8. Try it to find whether it + * works for your images. + * + * Use @profile to give the filename of a profile to be embedded in the TIFF. + * 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 and the VIPS header + * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the + * profile from the VIPS header will be attached. + * + * Set @tile to TRUE to write a tiled tiff. By default tiff are written in + * strips. Use @tile_width and @tile_height to set the tile size. The defaiult + * is 128 by 128. + * + * Set @pyramid to write the image as a set of images, one per page, of + * decreasing size. + * + * Set @squash to make 8-bit uchar images write as 1-bit TIFFs. Values >128 + * are written as white, values <=128 as black. Normally vips will write + * MINISBLACK TIFFs where black is a 0 bit, but if you set @miniswhite, it + * will use 0 for a white bit. Many pre-press applications only work with + * images which use this sense. @miniswhite only affects one-bit images, it + * does nothing for greyscale images. + * + * Use @resunit to override the default resolution unit. + * The default + * resolution unit is taken from the header field "resolution-unit" + * (#VIPS_META_RESOLUTION_UNIT in C). If this field is not set, then + * VIPS defaults to cm. + * + * Use @xres and @yres to override the default horizontal and vertical + * resolutions. By default these values are taken from the VIPS image header. + * libvips resolution is always in pixels per millimetre. + * + * Set @bigtiff to attempt to write a bigtiff. + * Bigtiff is a variant of the TIFF + * format that allows more than 4GB in a file. + * + * If @in has a field called VIPS_META_XMP_NAME ("xmp-data") it is written to + * the tiff image. + * + * See also: vips_tiffload(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_tiffsave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "tiffsave", ap, in, filename ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/vipsload.c b/libvips/foreign/vipsload.c index 317014a3..165520df 100644 --- a/libvips/foreign/vipsload.c +++ b/libvips/foreign/vipsload.c @@ -146,3 +146,28 @@ static void vips_foreign_load_vips_init( VipsForeignLoadVips *vips ) { } + +/** + * vips_vipsload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Read in a vips image. + * + * See also: vips_vipssave(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_vipsload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "vipsload", ap, filename, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 155d2032..619ce725 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -710,6 +710,11 @@ typedef struct { VipsImage *memory; FILE *fp; + + char *buf; + size_t len; + size_t alloc; + png_structp pPng; png_infop pInfo; png_bytep *row_pointer; @@ -720,6 +725,7 @@ write_finish( Write *write ) { VIPS_FREEF( fclose, write->fp ); VIPS_UNREF( write->memory ); + VIPS_FREE( write->buf ); if( write->pPng ) png_destroy_write_struct( &write->pPng, &write->pInfo ); } @@ -740,6 +746,10 @@ write_new( VipsImage *in ) memset( write, 0, sizeof( Write ) ); write->in = in; write->memory = NULL; + write->fp = NULL; + write->buf = NULL; + write->len = 0; + write->alloc = 0; g_signal_connect( in, "close", G_CALLBACK( write_destroy ), write ); @@ -976,72 +986,41 @@ vips__png_write( VipsImage *in, const char *filename, return( 0 ); } -typedef struct _WriteBuf { - char *buf; - size_t len; - size_t alloc; -} WriteBuf; - static void -write_buf_free( WriteBuf *wbuf ) +write_grow( Write *write, size_t grow_len ) { - VIPS_FREE( wbuf->buf ); - VIPS_FREE( wbuf ); -} + size_t new_len = write->len + grow_len; -static WriteBuf * -write_buf_new( void ) -{ - WriteBuf *wbuf; + if( new_len > write->alloc ) { + size_t proposed_alloc = (16 + write->alloc) * 3 / 2; - if( !(wbuf = VIPS_NEW( NULL, WriteBuf )) ) - return( NULL ); + write->alloc = VIPS_MAX( proposed_alloc, new_len ); - wbuf->buf = NULL; - wbuf->len = 0; - wbuf->alloc = 0; - - return( wbuf ); -} - -static void -write_buf_grow( WriteBuf *wbuf, size_t grow_len ) -{ - size_t new_len = wbuf->len + grow_len; - - if( new_len > wbuf->alloc ) { - size_t proposed_alloc = (16 + wbuf->alloc) * 3 / 2; - - wbuf->alloc = VIPS_MAX( proposed_alloc, new_len ); - - /* There's no vips_realloc(), so we call g_realloc() directly. - * This is safe, since vips_malloc() / vips_free() are wrappers - * over g_malloc() / g_free(). - * - * FIXME: add vips_realloc(). + /* Our result mujst be freedd with g_free(), so it's OK to use + * g_realloc(). */ - wbuf->buf = g_realloc( wbuf->buf, wbuf->alloc ); + write->buf = g_realloc( write->buf, write->alloc ); VIPS_DEBUG_MSG( "write_buf_grow: grown to %zd bytes\n", - wbuf->alloc ); + write->alloc ); } } static void user_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) { - WriteBuf *wbuf = (WriteBuf *) png_get_io_ptr( png_ptr ); + Write *write = (Write *) png_get_io_ptr( png_ptr ); char *write_start; - write_buf_grow( wbuf, length ); + write_grow( write, length ); - write_start = wbuf->buf + wbuf->len; + write_start = write->buf + write->len; memcpy( write_start, data, length ); - wbuf->len += length; + write->len += length; - g_assert( wbuf->len <= wbuf->alloc ); + g_assert( write->len <= write->alloc ); } int @@ -1049,36 +1028,28 @@ vips__png_write_buf( VipsImage *in, void **obuf, size_t *olen, int compression, int interlace, const char *profile, VipsForeignPngFilter filter ) { - WriteBuf *wbuf; Write *write; - if( !(wbuf = write_buf_new()) ) + if( !(write = write_new( in )) ) return( -1 ); - if( !(write = write_new( in )) ) { - write_buf_free( wbuf ); - return( -1 ); - } - png_set_write_fn( write->pPng, wbuf, user_write_data, NULL ); + png_set_write_fn( write->pPng, write, user_write_data, NULL ); /* Convert it! */ if( write_vips( write, compression, interlace, profile, filter ) ) { - write_buf_free( wbuf ); vips_error( "vips2png", "%s", _( "unable to write to buffer" ) ); return( -1 ); } - write_finish( write ); - - *obuf = wbuf->buf; - wbuf->buf = NULL; + *obuf = write->buf; + write->buf = NULL; if( olen ) - *olen = wbuf->len; + *olen = write->len; - write_buf_free( wbuf ); + write_finish( write ); return( 0 ); } diff --git a/libvips/foreign/vipssave.c b/libvips/foreign/vipssave.c index a502418e..ade2b152 100644 --- a/libvips/foreign/vipssave.c +++ b/libvips/foreign/vipssave.c @@ -123,3 +123,28 @@ vips_foreign_save_vips_init( VipsForeignSaveVips *vips ) { } +/** + * vips_vipssave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Write @in to @filename in VIPS format. + * + * See also: vips_vipsload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_vipssave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "vipssave", ap, in, filename ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/foreign/webpload.c b/libvips/foreign/webpload.c index 0922c957..65c513bc 100644 --- a/libvips/foreign/webpload.c +++ b/libvips/foreign/webpload.c @@ -43,12 +43,12 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_LIBWEBP - #include #include +#ifdef HAVE_LIBWEBP + #include "webp.h" typedef struct _VipsForeignLoadWebp { @@ -278,3 +278,75 @@ vips_foreign_load_webp_buffer_init( VipsForeignLoadWebpBuffer *buffer ) } #endif /*HAVE_LIBWEBP*/ + +/** + * vips_webpload: + * @filename: file to load + * @out: decompressed image + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @shrink: %gint, shrink by this much on load + * + * Read a WebP file into a VIPS image. + * + * Use @shrink to specify a shrink-on-load factor. + * + * See also: vips_image_new_from_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_webpload( const char *filename, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "webpload", ap, filename, out ); + va_end( ap ); + + return( result ); +} + +/** + * vips_webpload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @shrink: %gint, shrink by this much on load + * + * Read a WebP-formatted memory block into a VIPS image. Exactly as + * vips_webpload(), but read from a memory buffer. + * + * You must not free the buffer while @out is active. The + * #VipsObject::postclose signal on @out is a good place to free. + * + * See also: vips_webpload() + * + * Returns: 0 on success, -1 on error. + */ +int +vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsBlob *blob; + int result; + + /* We don't take a copy of the data or free it. + */ + blob = vips_blob_new( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "webpload_buffer", ap, blob, out ); + va_end( ap ); + + vips_area_unref( VIPS_AREA( blob ) ); + + return( result ); +} diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 77e65108..1f123f76 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -41,12 +41,12 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_LIBWEBP - #include #include +#ifdef HAVE_LIBWEBP + #include "webp.h" typedef struct _VipsForeignSaveWebp { @@ -258,7 +258,9 @@ vips_foreign_save_webp_buffer_build( VipsObject *object ) webp->alpha_q ) ) return( -1 ); - blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); + /* obuf is a g_free() buffer, not vips_free(). + */ + blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); g_object_set( file, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); @@ -352,3 +354,138 @@ vips_foreign_save_webp_mime_init( VipsForeignSaveWebpMime *mime ) } #endif /*HAVE_LIBWEBP*/ + +/** + * vips_webpsave: + * @in: image to save + * @filename: file to write to + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode + * + * Write an image to a file in WebP format. + * + * By default, images are saved in lossy format, with + * @Q giving the WebP quality factor. It has the range 0 - 100, with the + * default 75. + * + * Use @preset to hint the image type to the lossy compressor. The default is + * #VIPS_FOREIGN_WEBP_PRESET_DEFAULT. + * Set @smart_subsample to enable high quality chroma subsampling. + * Use @alpha_q to set the quality for the alpha channel in lossy mode. It has + * the range 1 - 100, with the default 100. + * + * Set @lossless to use lossless compression, or combine @near_lossless + * with @Q 80, 60, 40 or 20 to apply increasing amounts of preprocessing + * which improves the near-lossless compression ratio by up to 50%. + * + * See also: vips_webpload(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_webpsave( VipsImage *in, const char *filename, ... ) +{ + va_list ap; + int result; + + va_start( ap, filename ); + result = vips_call_split( "webpsave", ap, in, filename ); + va_end( ap ); + + return( result ); +} + +/** + * vips_webpsave_buffer: + * @in: image to save + * @buf: return output buffer here + * @len: return output length here + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode + * + * As vips_webpsave(), but save to a memory buffer. + * + * The address of the buffer is returned in @buf, the length of the buffer in + * @len. You are responsible for freeing the buffer with g_free() when you + * are done with it. + * + * See also: vips_webpsave(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + area = NULL; + + va_start( ap, len ); + result = vips_call_split( "webpsave_buffer", ap, in, &area ); + va_end( ap ); + + if( !result && + area ) { + if( buf ) { + *buf = area->data; + area->free_fn = NULL; + } + if( len ) + *len = area->length; + + vips_area_unref( area ); + } + + return( result ); +} + +/** + * vips_webpsave_mime: + * @in: image to save + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode + * + * As vips_webpsave(), but save as a mime webp on stdout. + * + * See also: vips_webpsave(), vips_image_write_to_file(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_webpsave_mime( VipsImage *in, ... ) +{ + va_list ap; + int result; + + va_start( ap, in ); + result = vips_call_split( "webpsave_mime", ap, in ); + va_end( ap ); + + return( result ); +}