Merge pull request #190 from lovell/png-set-filter
Expose ability to control libpng's row filter
This commit is contained in:
commit
1589e84360
@ -2487,6 +2487,7 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
* @compression: compression level
|
||||
* @interlace: interlace image
|
||||
* @profile: ICC profile to embed
|
||||
* @filter: libpng row filter flag(s)
|
||||
*
|
||||
* Write a VIPS image to a file as PNG.
|
||||
*
|
||||
@ -2506,6 +2507,8 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
* 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).
|
||||
*
|
||||
* 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.
|
||||
@ -2539,6 +2542,7 @@ vips_pngsave( VipsImage *in, const char *filename, ... )
|
||||
* @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.
|
||||
*
|
||||
|
@ -59,6 +59,7 @@ typedef struct _VipsForeignSavePng {
|
||||
int compression;
|
||||
gboolean interlace;
|
||||
char *profile;
|
||||
VipsForeignPngFilter filter;
|
||||
} VipsForeignSavePng;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSavePngClass;
|
||||
@ -124,12 +125,21 @@ vips_foreign_save_png_class_init( VipsForeignSavePngClass *class )
|
||||
G_STRUCT_OFFSET( VipsForeignSavePng, profile ),
|
||||
NULL );
|
||||
|
||||
VIPS_ARG_FLAGS( class, "filter", 12,
|
||||
_( "Filter" ),
|
||||
_( "libpng row filter flag(s)" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSavePng, filter ),
|
||||
VIPS_TYPE_FOREIGN_PNG_FILTER,
|
||||
VIPS_FOREIGN_PNG_FILTER_ALL );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_png_init( VipsForeignSavePng *png )
|
||||
{
|
||||
png->compression = 6;
|
||||
png->filter = VIPS_FOREIGN_PNG_FILTER_ALL;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignSavePngFile {
|
||||
@ -155,7 +165,7 @@ vips_foreign_save_png_file_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write( save->ready, png_file->filename,
|
||||
png->compression, png->interlace, png->profile ) )
|
||||
png->compression, png->interlace, png->profile, png->filter ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -213,7 +223,7 @@ vips_foreign_save_png_buffer_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write_buf( save->ready, &obuf, &olen,
|
||||
png->compression, png->interlace, png->profile ) )
|
||||
png->compression, png->interlace, png->profile, png->filter ) )
|
||||
return( -1 );
|
||||
|
||||
blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen );
|
||||
|
@ -783,7 +783,8 @@ write_png_block( VipsRegion *region, VipsRect *area, void *a )
|
||||
/* Write a VIPS image to PNG.
|
||||
*/
|
||||
static int
|
||||
write_vips( Write *write, int compress, int interlace, const char *profile )
|
||||
write_vips( Write *write, int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter )
|
||||
{
|
||||
VipsImage *in = write->in;
|
||||
|
||||
@ -824,6 +825,10 @@ write_vips( Write *write, int compress, int interlace, const char *profile )
|
||||
*/
|
||||
png_set_compression_level( write->pPng, compress );
|
||||
|
||||
/* Set row filter.
|
||||
*/
|
||||
png_set_filter( write->pPng, 0, filter );
|
||||
|
||||
bit_depth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16;
|
||||
|
||||
switch( in->Bands ) {
|
||||
@ -921,7 +926,8 @@ write_vips( Write *write, int compress, int interlace, const char *profile )
|
||||
|
||||
int
|
||||
vips__png_write( VipsImage *in, const char *filename,
|
||||
int compress, int interlace, const char *profile )
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -940,7 +946,7 @@ vips__png_write( VipsImage *in, const char *filename,
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write, compress, interlace, profile ) ) {
|
||||
if( write_vips( write, compress, interlace, profile, filter ) ) {
|
||||
vips_error( "vips2png",
|
||||
_( "unable to write \"%s\"" ), filename );
|
||||
|
||||
@ -1027,7 +1033,7 @@ user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
|
||||
int
|
||||
vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
const char *profile )
|
||||
const char *profile, VipsForeignPngFilter filter )
|
||||
{
|
||||
WriteBuf *wbuf;
|
||||
Write *write;
|
||||
@ -1043,7 +1049,7 @@ vips__png_write_buf( VipsImage *in,
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write, compression, interlace, profile ) ) {
|
||||
if( write_vips( write, compression, interlace, profile, filter ) ) {
|
||||
write_buf_free( wbuf );
|
||||
vips_error( "vips2png",
|
||||
"%s", _( "unable to write to buffer" ) );
|
||||
|
@ -46,10 +46,11 @@ int vips__png_read_buffer( char *buffer, size_t length, VipsImage *out,
|
||||
int vips__png_header_buffer( char *buffer, size_t length, VipsImage *out );
|
||||
|
||||
int vips__png_write( VipsImage *in, const char *filename,
|
||||
int compress, int interlace, const char *profile );
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter );
|
||||
int vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
const char *profile );
|
||||
const char *profile, VipsForeignPngFilter filter );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ GType vips_foreign_tiff_predictor_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_TIFF_PREDICTOR (vips_foreign_tiff_predictor_get_type())
|
||||
GType vips_foreign_tiff_resunit_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_TIFF_RESUNIT (vips_foreign_tiff_resunit_get_type())
|
||||
GType vips_foreign_png_filter_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_PNG_FILTER (vips_foreign_png_filter_get_type())
|
||||
GType vips_foreign_dz_layout_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_DZ_LAYOUT (vips_foreign_dz_layout_get_type())
|
||||
GType vips_foreign_dz_depth_get_type (void) G_GNUC_CONST;
|
||||
|
@ -436,6 +436,28 @@ int vips_matrixprint( VipsImage *in, ... )
|
||||
int vips_magickload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
/**
|
||||
* VipsForeignPngFilter:
|
||||
* @VIPS_FOREIGN_PNG_FILTER_NONE
|
||||
* @VIPS_FOREIGN_PNG_FILTER_SUB
|
||||
* @VIPS_FOREIGN_PNG_FILTER_UP
|
||||
* @VIPS_FOREIGN_PNG_FILTER_AVG
|
||||
* @VIPS_FOREIGN_PNG_FILTER_PAETH
|
||||
* @VIPS_FOREIGN_PNG_FILTER_ALL
|
||||
*
|
||||
* http://www.w3.org/TR/PNG-Filters.html
|
||||
* The values mirror those of png.h in libpng.
|
||||
*/
|
||||
typedef enum /*< flags >*/ {
|
||||
VIPS_FOREIGN_PNG_FILTER_NONE = 0x08,
|
||||
VIPS_FOREIGN_PNG_FILTER_SUB = 0x10,
|
||||
VIPS_FOREIGN_PNG_FILTER_UP = 0x20,
|
||||
VIPS_FOREIGN_PNG_FILTER_AVG = 0x40,
|
||||
VIPS_FOREIGN_PNG_FILTER_PAETH = 0x80,
|
||||
VIPS_FOREIGN_PNG_FILTER_ALL = 0xEA,
|
||||
VIPS_FOREIGN_PNG_FILTER_LAST = 0xFF
|
||||
} VipsForeignPngFilter;
|
||||
|
||||
int vips_pngload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
|
@ -106,6 +106,28 @@ vips_foreign_tiff_resunit_get_type( void )
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_foreign_png_filter_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GFlagsValue values[] = {
|
||||
{VIPS_FOREIGN_PNG_FILTER_NONE, "VIPS_FOREIGN_PNG_FILTER_NONE", "none"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_SUB, "VIPS_FOREIGN_PNG_FILTER_SUB", "sub"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_UP, "VIPS_FOREIGN_PNG_FILTER_UP", "up"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_AVG, "VIPS_FOREIGN_PNG_FILTER_AVG", "avg"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_PAETH, "VIPS_FOREIGN_PNG_FILTER_PAETH", "paeth"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_ALL, "VIPS_FOREIGN_PNG_FILTER_ALL", "all"},
|
||||
{VIPS_FOREIGN_PNG_FILTER_LAST, "VIPS_FOREIGN_PNG_FILTER_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_flags_register_static( "VipsForeignPngFilter", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_foreign_dz_layout_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user