cgifsave: remove regressions from 2853 (#2870)

* cgifsave: pick the best quantizer instead of the first good enough

* cgifsave: fix palettes comparison

* cgifsave: don't copy unchanged pixels to previous_frame
This commit is contained in:
Sergey Alexandrovich 2022-06-19 15:15:40 +04:00 committed by GitHub
parent 5b79a744a7
commit 41da0d28e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 28 additions and 17 deletions

View File

@ -214,18 +214,25 @@ vips_foreign_save_cgif_set_transparent( VipsForeignSaveCgif *cgif,
} }
} }
if( index[i] != trans ) {
old[0] = new[0];
old[1] = new[1];
old[2] = new[2];
old[3] = new[3];
}
old += 4; old += 4;
new += 4; new += 4;
} }
} }
static int static double
vips__cgif_compare_palettes( const VipsQuantisePalette *new, vips__cgif_compare_palettes( const VipsQuantisePalette *new,
const VipsQuantisePalette *old ) const VipsQuantisePalette *old )
{ {
int i, j; int i, j;
int best_dist, dist, rd, gd, bd; double best_dist, dist, rd, gd, bd;
int total_dist; double total_dist;
g_assert( new->count <= 256 ); g_assert( new->count <= 256 );
g_assert( old->count <= 256 ); g_assert( old->count <= 256 );
@ -337,19 +344,23 @@ vips_foreign_save_cgif_pick_quantiser( VipsForeignSaveCgif *cgif,
const VipsQuantisePalette *prev = vips__quantise_get_palette( const VipsQuantisePalette *prev = vips__quantise_get_palette(
cgif->previous_quantisation_result ); cgif->previous_quantisation_result );
double global_diff = vips__cgif_compare_palettes( this, global );
double prev_diff = ( prev == global ) ? global_diff :
vips__cgif_compare_palettes( this, prev );
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "vips_foreign_save_cgif_write_frame: " printf( "vips_foreign_save_cgif_write_frame: "
"this -> global distance = %d\n", "this -> global distance = %g\n",
vips__cgif_compare_palettes( this, global ) ); global_diff );
printf( "vips_foreign_save_cgif_write_frame: " printf( "vips_foreign_save_cgif_write_frame: "
"this -> prev distance = %d\n", "this -> prev distance = %g\n",
vips__cgif_compare_palettes( this, prev ) ); prev_diff );
printf( "vips_foreign_save_cgif_write_frame: " printf( "vips_foreign_save_cgif_write_frame: "
"threshold = %g\n", cgif->interpalette_maxerror ); "threshold = %g\n", cgif->interpalette_maxerror );
#endif/*DEBUG_VERBOSE*/ #endif/*DEBUG_VERBOSE*/
if( vips__cgif_compare_palettes( this, global ) < if( global_diff <= prev_diff &&
cgif->interpalette_maxerror ) { global_diff < cgif->interpalette_maxerror ) {
/* Global is good enough, use that. /* Global is good enough, use that.
*/ */
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
@ -365,8 +376,7 @@ vips_foreign_save_cgif_pick_quantiser( VipsForeignSaveCgif *cgif,
*result = cgif->quantisation_result; *result = cgif->quantisation_result;
*use_local = FALSE; *use_local = FALSE;
} }
else if( vips__cgif_compare_palettes( this, prev ) < else if( prev_diff < cgif->interpalette_maxerror ) {
cgif->interpalette_maxerror ) {
/* Previous is good enough, use that again. /* Previous is good enough, use that again.
*/ */
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
@ -564,6 +574,11 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
frame_config.attrFlags |= CGIF_FRAME_ATTR_HAS_SET_TRANS; frame_config.attrFlags |= CGIF_FRAME_ATTR_HAS_SET_TRANS;
frame_config.transIndex = trans; frame_config.transIndex = trans;
} }
else {
/* Take a copy of the RGBA frame.
*/
memcpy( cgif->previous_frame, frame_bytes, 4 * n_pels );
}
if( cgif->delay && if( cgif->delay &&
page_index < cgif->delay_length ) page_index < cgif->delay_length )
@ -583,10 +598,6 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
frame_config.pImageData = cgif->index; frame_config.pImageData = cgif->index;
cgif_addframe( cgif->cgif_context, &frame_config ); cgif_addframe( cgif->cgif_context, &frame_config );
/* Take a copy of the RGBA frame.
*/
memcpy( cgif->previous_frame, frame_bytes, 4 * n_pels );
return( 0 ); return( 0 );
} }
@ -861,7 +872,7 @@ vips_foreign_save_cgif_class_init( VipsForeignSaveCgifClass *class )
_( "Maximum inter-palette error for palette reusage" ), _( "Maximum inter-palette error for palette reusage" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveCgif, interpalette_maxerror ), G_STRUCT_OFFSET( VipsForeignSaveCgif, interpalette_maxerror ),
0, 256, 40.0 ); 0, 256, 3.0 );
} }
static void static void
@ -872,7 +883,7 @@ vips_foreign_save_cgif_init( VipsForeignSaveCgif *gif )
gif->bitdepth = 8; gif->bitdepth = 8;
gif->interframe_maxerror = 0.0; gif->interframe_maxerror = 0.0;
gif->reoptimise = FALSE; gif->reoptimise = FALSE;
gif->interpalette_maxerror = 40.0; gif->interpalette_maxerror = 3.0;
gif->mode = VIPS_FOREIGN_SAVE_CGIF_MODE_GLOBAL; gif->mode = VIPS_FOREIGN_SAVE_CGIF_MODE_GLOBAL;
} }