clean up foreign

various cosmetic changes:

- pngsave_buffer now uses Write, not WriteBuf, same change for
  radsave_buffer

- move C wrappers out to class defs from foreign.c

- use g_free() not vips_free() for buffer free from low-level savers

- fix var names in some comments

- various style changes for radiance.c
This commit is contained in:
John Cupitt 2016-05-24 10:57:02 +01:00
parent 0cdfc8396c
commit 50468a07a2
24 changed files with 1666 additions and 1698 deletions

3
TODO
View File

@ -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

View File

@ -40,8 +40,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_CFITSIO
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -50,6 +48,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -43,14 +43,14 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_CFITSIO
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#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 );
}

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_GIFLIB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -55,6 +53,8 @@
#include <vips/internal.h>
#include <vips/debug.h>
#ifdef HAVE_GIFLIB
#include <gif_lib.h>
/* 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 );
}

View File

@ -43,13 +43,17 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_JPEG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#ifdef HAVE_JPEG
#ifdef HAVE_EXIF
#ifdef UNTAGGED_EXIF
#include <exif-data.h>
@ -64,10 +68,6 @@
#endif /*UNTAGGED_EXIF*/
#endif /*HAVE_EXIF*/
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#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", &amp;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 );
}

View File

@ -41,13 +41,17 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_JPEG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#ifdef HAVE_JPEG
#ifdef HAVE_EXIF
#ifdef UNTAGGED_EXIF
#include <exif-data.h>
@ -62,10 +66,6 @@
#endif /*UNTAGGED_EXIF*/
#endif /*HAVE_EXIF*/
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -46,8 +46,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_MAGICK
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -56,6 +54,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -42,8 +42,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_MATIO
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -52,6 +50,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -40,8 +40,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_OPENEXR
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -50,6 +48,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -47,8 +47,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_OPENSLIDE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -57,6 +55,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -42,8 +42,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_POPPLER
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -53,6 +51,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#ifdef HAVE_POPPLER
#include <cairo.h>
#include <poppler.h>
@ -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 );
}

View File

@ -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 );
}

View File

@ -43,14 +43,14 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_PNG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#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 );
}

View File

@ -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 );
}

View File

@ -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().

View File

@ -40,8 +40,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_RSVG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -52,6 +50,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#ifdef HAVE_RSVG
#include <cairo.h>
#include <librsvg/rsvg.h>
@ -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 );
}

View File

@ -40,8 +40,6 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_TIFF
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -50,6 +48,8 @@
#include <vips/buf.h>
#include <vips/internal.h>
#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 );
}

View File

@ -47,14 +47,14 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_TIFF
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#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 );
}

View File

@ -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 );
}

View File

@ -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 );
}

View File

@ -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 );
}

View File

@ -43,12 +43,12 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_LIBWEBP
#include <string.h>
#include <vips/vips.h>
#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 );
}

View File

@ -41,12 +41,12 @@
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifdef HAVE_LIBWEBP
#include <stdlib.h>
#include <vips/vips.h>
#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 );
}