add new param to gifsave docs

also note in changelog and revise layout for 80 columns

see https://github.com/libvips/libvips/pull/2628
This commit is contained in:
John Cupitt 2022-02-28 16:38:02 +00:00
parent b0f993eec8
commit 3b6072437d
2 changed files with 41 additions and 21 deletions

View File

@ -13,6 +13,7 @@
- add @unlimited to heifload [lovell]
- edge antialiasing for mapim with @background, @extend and @premultiplied
- add support for regions in C++ API [shado23]
- add maxerror to gifsave [dloebl]
26/11/21 started 8.12.3
- better arg checking for hist_find_ndim [travisbell]

View File

@ -161,21 +161,24 @@ static int vips__cgif_write( void *target, const uint8_t *buffer,
}
/* Compare pixels in a lossy way (allow a slight colour difference).
In combination with the GIF transparency optimization this leads to
less difference between frames and therefore improves the compression ratio.
* In combination with the GIF transparency optimization this leads to
* less difference between frames and therefore improves the compression ratio.
*/
static gboolean
cgif_pixels_are_equal(const VipsPel *cur, const VipsPel *bef, double maxerror)
vips_foreign_save_cgif_pixels_are_equal( const VipsPel *cur, const VipsPel *bef,
double maxerror )
{
if( bef[3] != 0xFF )
/* Done. Cannot compare with alpha channel in frame before.
/* Solid pixels only.
*/
return FALSE;
/* Test Euclidean distance between the two points.
*/
const int dR = cur[0] - bef[0];
const int dG = cur[1] - bef[1];
const int dB = cur[2] - bef[2];
return( sqrt( dR * dR + dG * dG + dB * dB ) <= maxerror );
}
@ -241,11 +244,13 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
* attach it as a local cmap when we write.
*/
if( cgif->quantisation_result )
cgif->cgif_config.attrFlags |= CGIF_ATTR_NO_GLOBAL_TABLE;
cgif->cgif_config.attrFlags |=
CGIF_ATTR_NO_GLOBAL_TABLE;
VIPS_FREEF( vips__quantise_result_destroy, cgif->quantisation_result );
if( vips__quantise_image_quantize( cgif->input_image, cgif->attr,
&cgif->quantisation_result ) ) {
VIPS_FREEF( vips__quantise_result_destroy,
cgif->quantisation_result );
if( vips__quantise_image_quantize( cgif->input_image,
cgif->attr, &cgif->quantisation_result ) ) {
vips_error( class->nickname,
"%s", _( "quantisation failed" ) );
return( -1 );
@ -258,15 +263,17 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
/* Dither frame.
*/
vips__quantise_set_dithering_level( cgif->quantisation_result, cgif->dither );
vips__quantise_set_dithering_level( cgif->quantisation_result,
cgif->dither );
if( vips__quantise_write_remapped_image( cgif->quantisation_result,
cgif->input_image, cgif->index, n_pels ) ) {
vips_error( class->nickname, "%s", _( "dither failed" ) );
return( -1 );
}
/* Call vips__quantise_get_palette() after vips__quantise_write_remapped_image(),
* as palette is improved during remapping.
/* Call vips__quantise_get_palette() after
* vips__quantise_write_remapped_image(), as palette is improved
* during remapping.
*/
cgif->lp = vips__quantise_get_palette( cgif->quantisation_result );
rgb = cgif->palette_rgb;
@ -331,7 +338,8 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
frame_config.transIndex = 0;
}
/* Do the transparency trick (only possible when no alpha channel present)
/* Pixels which are equal to pixels in the previous frame can be made
* transparent.
*/
if( cgif->frame_bytes_head ) {
VipsPel *cur, *bef;
@ -340,12 +348,12 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
bef = cgif->frame_bytes_head;
if( !cgif->has_transparency ) {
const uint8_t trans_index = cgif->lp->count;
const double maxerror = cgif->maxerror;
int i;
for( i = 0; i < n_pels; i++ ) {
if( cgif_pixels_are_equal( cur, bef, maxerror ) )
if( vips_foreign_save_cgif_pixels_are_equal(
cur, bef, cgif->maxerror ) )
cgif->index[i] = trans_index;
else {
bef[0] = cur[0];
@ -353,14 +361,18 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
bef[2] = cur[2];
bef[3] = cur[3];
}
cur += 4;
bef += 4;
}
frame_config.attrFlags |= CGIF_FRAME_ATTR_HAS_SET_TRANS;
frame_config.attrFlags |=
CGIF_FRAME_ATTR_HAS_SET_TRANS;
frame_config.transIndex = trans_index;
} else {
/* Transparency trick not possible (alpha channel present).
* Update head.
}
else {
/* Transparency trick not possible (alpha channel
* present). Update head.
*/
memcpy( bef, cur, 4 * n_pels);
}
@ -600,8 +612,8 @@ vips_foreign_save_cgif_class_init( VipsForeignSaveCgifClass *class )
1, 8, 8 );
VIPS_ARG_DOUBLE( class, "maxerror", 13,
_( "Max. error for lossy transparency setting"),
_( "Maximum pixel error to allow when identifying areas as identical (inter frame)" ),
_( "Maximum error" ),
_( "Maximum inter-frame error for transparency" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveCgif, maxerror ),
0, 32, 0.0 );
@ -794,8 +806,9 @@ vips_foreign_save_cgif_buffer_init( VipsForeignSaveCgifBuffer *buffer )
* * @dither: %gdouble, quantisation dithering level
* * @effort: %gint, quantisation CPU effort
* * @bitdepth: %gint, number of bits per pixel
* * @maxerror: %gdouble, maximum inter-frame error for transparency
*
* Write a VIPS image to a file as GIF.
* Write to a file in GIF format.
*
* Use @dither to set the degree of Floyd-Steinberg dithering
* and @effort to control the CPU effort (1 is the fastest,
@ -806,6 +819,10 @@ vips_foreign_save_cgif_buffer_init( VipsForeignSaveCgifBuffer *buffer )
* always reserved for transparency. For example, a bitdepth of
* 4 will allow the output to contain up to 15 colours.
*
* Use @maxerror to set the threshold below which pixels are considered equal.
* Pixels which don't change from frame to frame can be made transparent,
* improving the compression rate. Default 0.
*
* See also: vips_image_new_from_file().
*
* Returns: 0 on success, -1 on error.
@ -835,6 +852,7 @@ vips_gifsave( VipsImage *in, const char *filename, ... )
* * @dither: %gdouble, quantisation dithering level
* * @effort: %gint, quantisation CPU effort
* * @bitdepth: %gint, number of bits per pixel
* * @maxerror: %gdouble, maximum inter-frame error for transparency
*
* As vips_gifsave(), but save to a memory buffer.
*
@ -885,6 +903,7 @@ vips_gifsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* * @dither: %gdouble, quantisation dithering level
* * @effort: %gint, quantisation CPU effort
* * @bitdepth: %gint, number of bits per pixel
* * @maxerror: %gdouble, maximum inter-frame error for transparency
*
* As vips_gifsave(), but save to a target.
*