pngsave: expose quantisation effort setting (#2367)

This commit is contained in:
Lovell Fuller 2021-07-30 10:43:42 +01:00 committed by GitHub
parent 9221fae973
commit aabb1555d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 19 deletions

View File

@ -187,7 +187,7 @@ int vips__png_write_target( VipsImage *in, VipsTarget *target,
int compress, int interlace, const char *profile,
VipsForeignPngFilter filter, gboolean strip,
gboolean palette, int Q, double dither,
int bitdepth );
int bitdepth, int effort );
/* Map WEBP metadata names to vips names.
*/
@ -217,7 +217,7 @@ int vips__webp_write_target( VipsImage *image, VipsTarget *target,
int vips__quantise_image( VipsImage *in,
VipsImage **index_out, VipsImage **palette_out,
int colours, int Q, double dither );
int colours, int Q, double dither, int effort );
extern const char *vips_foreign_nifti_suffs[];

View File

@ -68,6 +68,7 @@ typedef struct _VipsForeignSavePng {
int Q;
double dither;
int bitdepth;
int effort;
/* Set by subclasses.
*/
@ -153,7 +154,7 @@ vips_foreign_save_png_build( VipsObject *object )
if( vips__png_write_target( in, png->target,
png->compression, png->interlace, png->profile, png->filter,
save->strip, png->palette, png->Q, png->dither,
png->bitdepth ) ) {
png->bitdepth, png->effort ) ) {
g_object_unref( in );
return( -1 );
}
@ -262,6 +263,13 @@ vips_foreign_save_png_class_init( VipsForeignSavePngClass *class )
G_STRUCT_OFFSET( VipsForeignSavePng, bitdepth ),
0, 8, 0 );
VIPS_ARG_INT( class, "effort", 18,
_( "Effort" ),
_( "Quantisation CPU effort" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSavePng, effort ),
1, 10, 7 );
VIPS_ARG_INT( class, "colours", 14,
_( "Colours" ),
_( "Max number of palette colours" ),
@ -278,6 +286,7 @@ vips_foreign_save_png_init( VipsForeignSavePng *png )
png->filter = VIPS_FOREIGN_PNG_FILTER_ALL;
png->Q = 100;
png->dither = 1.0;
png->effort = 7;
}
typedef struct _VipsForeignSavePngTarget {
@ -464,6 +473,7 @@ vips_foreign_save_png_buffer_init( VipsForeignSavePngBuffer *buffer )
* * @Q: %gint, quality for 8bpp quantisation
* * @dither: %gdouble, amount of dithering for 8bpp quantization
* * @bitdepth: %int, set write bit depth to 1, 2, 4 or 8
* * @effort: %int, quantisation CPU effort
*
* Write a VIPS image to a file as PNG.
*
@ -492,8 +502,9 @@ vips_foreign_save_png_buffer_init( VipsForeignSavePngBuffer *buffer )
*
* Set @palette to %TRUE to enable palette mode for RGB or RGBA images. A
* palette will be computed with enough space for @bitdepth (1, 2, 4 or 8)
* bits. Use @Q to set the optimisation effort, and @dither to set the degree of
* Floyd-Steinberg dithering.
* bits. Use @Q to set the optimisation effort, @dither to set the degree of
* Floyd-Steinberg dithering and @effort to control the CPU effort
* (1 is the fastest, 10 is the slowest, 7 is the default).
* This feature requires libvips to be compiled with libimagequant.
*
* You can also set @bitdepth for mono and mono + alpha images, and the image
@ -536,6 +547,7 @@ vips_pngsave( VipsImage *in, const char *filename, ... )
* * @Q: %gint, quality for 8bpp quantisation
* * @dither: %gdouble, amount of dithering for 8bpp quantization
* * @bitdepth: %int, set write bit depth to 1, 2, 4 or 8
* * @effort: %int, quantisation CPU effort
*
* As vips_pngsave(), but save to a memory buffer.
*
@ -591,6 +603,7 @@ vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* * @Q: quality for 8bpp quantisation
* * @dither: amount of dithering for 8bpp quantization
* * @bitdepth: %int, set write bit depth to 1, 2, 4 or 8
* * @effort: %int, quantisation CPU effort
*
* As vips_pngsave(), but save to a target.
*

View File

@ -53,11 +53,12 @@
*/
typedef struct _Quantise {
VipsImage *in;
VipsImage **index_out;
VipsImage **palette_out;
int colours;
int Q;
double dither;
VipsImage **index_out;
VipsImage **palette_out;
int colours;
int Q;
double dither;
int effort;
liq_attr *attr;
liq_image *input_image;
@ -83,7 +84,7 @@ vips__quantise_free( Quantise *quantise )
static Quantise *
vips__quantise_new( VipsImage *in,
VipsImage **index_out, VipsImage **palette_out,
int colours, int Q, double dither )
int colours, int Q, double dither, int effort )
{
Quantise *quantise;
int i;
@ -95,6 +96,7 @@ vips__quantise_new( VipsImage *in,
quantise->colours = colours;
quantise->Q = Q;
quantise->dither = dither;
quantise->effort = effort;
for( i = 0; i < VIPS_NUMBER( quantise->t ); i++ )
quantise->t[i] = NULL;
@ -104,7 +106,7 @@ vips__quantise_new( VipsImage *in,
int
vips__quantise_image( VipsImage *in,
VipsImage **index_out, VipsImage **palette_out,
int colours, int Q, double dither )
int colours, int Q, double dither, int effort )
{
Quantise *quantise;
VipsImage *index;
@ -113,7 +115,7 @@ vips__quantise_image( VipsImage *in,
int i;
quantise = vips__quantise_new( in, index_out, palette_out,
colours, Q, dither );
colours, Q, dither, effort );
/* Ensure input is sRGB.
*/
@ -145,13 +147,14 @@ vips__quantise_image( VipsImage *in,
quantise->attr = liq_attr_create();
liq_set_max_colors( quantise->attr, colours );
liq_set_quality( quantise->attr, 0, Q );
liq_set_speed( quantise->attr, 11 - effort );
quantise->input_image = liq_image_create_rgba( quantise->attr,
VIPS_IMAGE_ADDR( in, 0, 0 ), in->Xsize, in->Ysize, 0 );
if( liq_image_quantize( quantise->input_image, quantise->attr,
&quantise->quantisation_result ) ) {
vips_error( "vips2png", "%s", _( "quantisation failed" ) );
vips_error( "quantise", "%s", _( "quantisation failed" ) );
vips__quantise_free( quantise );
return( -1 );
}
@ -171,7 +174,7 @@ vips__quantise_image( VipsImage *in,
if( liq_write_remapped_image( quantise->quantisation_result,
quantise->input_image,
VIPS_IMAGE_ADDR( index, 0, 0 ), VIPS_IMAGE_N_PELS( index ) ) ) {
vips_error( "vips2png", "%s", _( "quantisation failed" ) );
vips_error( "quantise", "%s", _( "quantisation failed" ) );
vips__quantise_free( quantise );
return( -1 );
}

View File

@ -986,7 +986,7 @@ write_vips( Write *write,
int compress, int interlace, const char *profile,
VipsForeignPngFilter filter, gboolean strip,
gboolean palette, int Q, double dither,
int bitdepth )
int bitdepth, int effort )
{
VipsImage *in = write->in;
@ -1162,7 +1162,7 @@ write_vips( Write *write,
int trans_count;
if( vips__quantise_image( in, &im_index, &im_palette,
1 << bitdepth, Q, dither ) )
1 << bitdepth, Q, dither, effort ) )
return( -1 );
palette_count = im_palette->Xsize;
@ -1256,7 +1256,7 @@ vips__png_write_target( VipsImage *in, VipsTarget *target,
int compression, int interlace,
const char *profile, VipsForeignPngFilter filter, gboolean strip,
gboolean palette, int Q, double dither,
int bitdepth )
int bitdepth, int effort )
{
Write *write;
@ -1265,7 +1265,7 @@ vips__png_write_target( VipsImage *in, VipsTarget *target,
if( write_vips( write,
compression, interlace, profile, filter, strip, palette,
Q, dither, bitdepth ) ) {
Q, dither, bitdepth, effort ) ) {
write_destroy( write );
vips_error( "vips2png", _( "unable to write to target %s" ),
vips_connection_nick( VIPS_CONNECTION( target ) ) );