Skip to content

Commit

Permalink
Change --lossy algorithm to use current colorspace.
Browse files Browse the repository at this point in the history
* The loss score is scaled to errors in the current colorspace by
  normalizing to the distance between rgb(0,0,0) and rgb(0,0,LOSS).
* Reset accumulated error at the start of each line (don't want to
  carry error into a different region of the image).
* The previous difference algorithm would accumulate differences
  in the difference score. The new algorithm does not. Rather, the
  error term is used only to eliminate candidates. A color is a
  valid candidate iff it is both close enough to the real pixel,
  and close enough to the real pixel modified by accumulated error.
* Rather than choosing the longest sequence with minimum error,
  compute a score that considers both length and error.

The results look reasonable, but the argument to `--lossy` has
different effects. For `--gamma=1`, this commit results
in better compression than the former commit (1.644M v. 2.202M),
on the falling-beecat gif from pull request #16,
at the cost of modest posterization (long runs of the same pixel,
rather than dithering). For `--gamma=srgb`, this commit
compresses worse than the old version, but with fewer artifacts,
and `--lossy=40` still looks ok.
  • Loading branch information
kohler committed Feb 20, 2024
1 parent 99f4845 commit 1fb65e0
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 151 deletions.
8 changes: 3 additions & 5 deletions src/gifsicle.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,18 +899,14 @@ set_new_fixed_colormap(const char *name)
static void
do_colormap_change(Gif_Stream *gfs)
{
if (active_output_data.colormap_fixed || active_output_data.colormap_size > 0)
kc_set_gamma(active_output_data.colormap_gamma_type,
active_output_data.colormap_gamma);

if (active_output_data.colormap_fixed)
colormap_stream(gfs, active_output_data.colormap_fixed,
&active_output_data);

if (active_output_data.colormap_size > 0) {
kchist kch;
Gif_Colormap* (*adapt_func)(kchist*, Gt_OutputData*);
Gif_Colormap *new_cm;
Gif_Colormap* new_cm;

/* set up the histogram */
{
Expand Down Expand Up @@ -1025,6 +1021,8 @@ merge_and_write_frames(const char *outfile, int f1, int f2)
w = active_output_data.resize_width;
h = active_output_data.resize_height;
}
kc_set_gamma(active_output_data.colormap_gamma_type,
active_output_data.colormap_gamma);
if (active_output_data.scaling != GT_SCALING_NONE)
resize_stream(out, w, h, active_output_data.resize_flags,
active_output_data.scale_method,
Expand Down
6 changes: 6 additions & 0 deletions src/gifsicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ enum {
int set_dither_type(Gt_OutputData* od, const char* name);
void colormap_stream(Gif_Stream*, Gif_Colormap*, Gt_OutputData*);

struct kchist;
Gif_Colormap* colormap_blend_diversity(struct kchist* kch, Gt_OutputData* od);
Gif_Colormap* colormap_flat_diversity(struct kchist* kch, Gt_OutputData* od);
Gif_Colormap* colormap_median_cut(struct kchist* kch, Gt_OutputData* od);


/*****
* parsing stuff
**/
Expand Down
Loading

0 comments on commit 1fb65e0

Please sign in to comment.