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:
parent
b0f993eec8
commit
3b6072437d
@ -13,6 +13,7 @@
|
|||||||
- add @unlimited to heifload [lovell]
|
- add @unlimited to heifload [lovell]
|
||||||
- edge antialiasing for mapim with @background, @extend and @premultiplied
|
- edge antialiasing for mapim with @background, @extend and @premultiplied
|
||||||
- add support for regions in C++ API [shado23]
|
- add support for regions in C++ API [shado23]
|
||||||
|
- add maxerror to gifsave [dloebl]
|
||||||
|
|
||||||
26/11/21 started 8.12.3
|
26/11/21 started 8.12.3
|
||||||
- better arg checking for hist_find_ndim [travisbell]
|
- better arg checking for hist_find_ndim [travisbell]
|
||||||
|
@ -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).
|
/* Compare pixels in a lossy way (allow a slight colour difference).
|
||||||
In combination with the GIF transparency optimization this leads to
|
* In combination with the GIF transparency optimization this leads to
|
||||||
less difference between frames and therefore improves the compression ratio.
|
* less difference between frames and therefore improves the compression ratio.
|
||||||
*/
|
*/
|
||||||
static gboolean
|
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 )
|
if( bef[3] != 0xFF )
|
||||||
/* Done. Cannot compare with alpha channel in frame before.
|
/* Solid pixels only.
|
||||||
*/
|
*/
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Test Euclidean distance between the two points.
|
/* Test Euclidean distance between the two points.
|
||||||
*/
|
*/
|
||||||
const int dR = cur[0] - bef[0];
|
const int dR = cur[0] - bef[0];
|
||||||
const int dG = cur[1] - bef[1];
|
const int dG = cur[1] - bef[1];
|
||||||
const int dB = cur[2] - bef[2];
|
const int dB = cur[2] - bef[2];
|
||||||
|
|
||||||
return( sqrt( dR * dR + dG * dG + dB * dB ) <= maxerror );
|
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.
|
* attach it as a local cmap when we write.
|
||||||
*/
|
*/
|
||||||
if( cgif->quantisation_result )
|
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 );
|
VIPS_FREEF( vips__quantise_result_destroy,
|
||||||
if( vips__quantise_image_quantize( cgif->input_image, cgif->attr,
|
cgif->quantisation_result );
|
||||||
&cgif->quantisation_result ) ) {
|
if( vips__quantise_image_quantize( cgif->input_image,
|
||||||
|
cgif->attr, &cgif->quantisation_result ) ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
"%s", _( "quantisation failed" ) );
|
"%s", _( "quantisation failed" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -258,15 +263,17 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
|
|||||||
|
|
||||||
/* Dither frame.
|
/* 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,
|
if( vips__quantise_write_remapped_image( cgif->quantisation_result,
|
||||||
cgif->input_image, cgif->index, n_pels ) ) {
|
cgif->input_image, cgif->index, n_pels ) ) {
|
||||||
vips_error( class->nickname, "%s", _( "dither failed" ) );
|
vips_error( class->nickname, "%s", _( "dither failed" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call vips__quantise_get_palette() after vips__quantise_write_remapped_image(),
|
/* Call vips__quantise_get_palette() after
|
||||||
* as palette is improved during remapping.
|
* vips__quantise_write_remapped_image(), as palette is improved
|
||||||
|
* during remapping.
|
||||||
*/
|
*/
|
||||||
cgif->lp = vips__quantise_get_palette( cgif->quantisation_result );
|
cgif->lp = vips__quantise_get_palette( cgif->quantisation_result );
|
||||||
rgb = cgif->palette_rgb;
|
rgb = cgif->palette_rgb;
|
||||||
@ -331,7 +338,8 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
|
|||||||
frame_config.transIndex = 0;
|
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 ) {
|
if( cgif->frame_bytes_head ) {
|
||||||
VipsPel *cur, *bef;
|
VipsPel *cur, *bef;
|
||||||
@ -340,12 +348,12 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
|
|||||||
bef = cgif->frame_bytes_head;
|
bef = cgif->frame_bytes_head;
|
||||||
if( !cgif->has_transparency ) {
|
if( !cgif->has_transparency ) {
|
||||||
const uint8_t trans_index = cgif->lp->count;
|
const uint8_t trans_index = cgif->lp->count;
|
||||||
const double maxerror = cgif->maxerror;
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for( i = 0; i < n_pels; 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;
|
cgif->index[i] = trans_index;
|
||||||
else {
|
else {
|
||||||
bef[0] = cur[0];
|
bef[0] = cur[0];
|
||||||
@ -353,14 +361,18 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
|
|||||||
bef[2] = cur[2];
|
bef[2] = cur[2];
|
||||||
bef[3] = cur[3];
|
bef[3] = cur[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
cur += 4;
|
cur += 4;
|
||||||
bef += 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;
|
frame_config.transIndex = trans_index;
|
||||||
} else {
|
}
|
||||||
/* Transparency trick not possible (alpha channel present).
|
else {
|
||||||
* Update head.
|
/* Transparency trick not possible (alpha channel
|
||||||
|
* present). Update head.
|
||||||
*/
|
*/
|
||||||
memcpy( bef, cur, 4 * n_pels);
|
memcpy( bef, cur, 4 * n_pels);
|
||||||
}
|
}
|
||||||
@ -600,8 +612,8 @@ vips_foreign_save_cgif_class_init( VipsForeignSaveCgifClass *class )
|
|||||||
1, 8, 8 );
|
1, 8, 8 );
|
||||||
|
|
||||||
VIPS_ARG_DOUBLE( class, "maxerror", 13,
|
VIPS_ARG_DOUBLE( class, "maxerror", 13,
|
||||||
_( "Max. error for lossy transparency setting"),
|
_( "Maximum error" ),
|
||||||
_( "Maximum pixel error to allow when identifying areas as identical (inter frame)" ),
|
_( "Maximum inter-frame error for transparency" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveCgif, maxerror ),
|
G_STRUCT_OFFSET( VipsForeignSaveCgif, maxerror ),
|
||||||
0, 32, 0.0 );
|
0, 32, 0.0 );
|
||||||
@ -794,8 +806,9 @@ vips_foreign_save_cgif_buffer_init( VipsForeignSaveCgifBuffer *buffer )
|
|||||||
* * @dither: %gdouble, quantisation dithering level
|
* * @dither: %gdouble, quantisation dithering level
|
||||||
* * @effort: %gint, quantisation CPU effort
|
* * @effort: %gint, quantisation CPU effort
|
||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @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
|
* Use @dither to set the degree of Floyd-Steinberg dithering
|
||||||
* and @effort to control the CPU effort (1 is the fastest,
|
* 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
|
* always reserved for transparency. For example, a bitdepth of
|
||||||
* 4 will allow the output to contain up to 15 colours.
|
* 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().
|
* See also: vips_image_new_from_file().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
@ -835,6 +852,7 @@ vips_gifsave( VipsImage *in, const char *filename, ... )
|
|||||||
* * @dither: %gdouble, quantisation dithering level
|
* * @dither: %gdouble, quantisation dithering level
|
||||||
* * @effort: %gint, quantisation CPU effort
|
* * @effort: %gint, quantisation CPU effort
|
||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @bitdepth: %gint, number of bits per pixel
|
||||||
|
* * @maxerror: %gdouble, maximum inter-frame error for transparency
|
||||||
*
|
*
|
||||||
* As vips_gifsave(), but save to a memory buffer.
|
* 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
|
* * @dither: %gdouble, quantisation dithering level
|
||||||
* * @effort: %gint, quantisation CPU effort
|
* * @effort: %gint, quantisation CPU effort
|
||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @bitdepth: %gint, number of bits per pixel
|
||||||
|
* * @maxerror: %gdouble, maximum inter-frame error for transparency
|
||||||
*
|
*
|
||||||
* As vips_gifsave(), but save to a target.
|
* As vips_gifsave(), but save to a target.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user