History

avfilter/palettegen: define the best axis to cut using the squared error

This is following the results from personal research¹. ¹: https://github.com/ubitux/research/tree/main/color-quantization#results

Clément Bœsch committed 3 years ago

Commit 86bced71 parent 21f78143 files · +27 −19Browse files

Showing the changes to libavfilter (1 of 3 files). Show all

Unified · Split

libavfilter/vf_palettegen.c+25−17
@@ -147,31 +147,39 @@ static av_always_inline int diff(const uint32_t a, const uint32_t b) · 146 unmodified lines
147 147
148static void compute_box_stats(PaletteGenContext *s, struct range_box *box)148static void compute_box_stats(PaletteGenContext *s, struct range_box *box)
149{149{
150 int rr, gr, br;150 int avg[3];
151 int64_t er2[3] = {0};
151 152
152 /* compute the box weight (sum all the weights of the colors in the153 /* Compute average color */
153 * range) and its boundings */154 uint64_t sr = 0, sg = 0, sb = 0;
154 uint8_t min[3] = {0xff, 0xff, 0xff};
155 uint8_t max[3] = {0x00, 0x00, 0x00};
156 box->weight = 0;155 box->weight = 0;
157 for (int i = box->start; i < box->start + box->len; i++) {156 for (int i = box->start; i < box->start + box->len; i++) {
158 const struct color_ref *ref = s->refs[i];157 const struct color_ref *ref = s->refs[i];
159 const uint32_t rgb = ref->color;158 sr += (ref->color >> 16 & 0xff) * ref->count;
160 const uint8_t r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff;159 sg += (ref->color >> 8 & 0xff) * ref->count;
161 min[0] = FFMIN(r, min[0]), max[0] = FFMAX(r, max[0]);160 sb += (ref->color & 0xff) * ref->count;
162 min[1] = FFMIN(g, min[1]), max[1] = FFMAX(g, max[1]);
163 min[2] = FFMIN(b, min[2]), max[2] = FFMAX(b, max[2]);
164 box->weight += ref->count;161 box->weight += ref->count;
165 }162 }
163 avg[0] = sr / box->weight;
164 avg[1] = sg / box->weight;
165 avg[2] = sb / box->weight;
166 166
167 /* define the axis to sort by according to the widest range of colors */167 /* Compute squared error of each color channel */
168 rr = max[0] - min[0];168 for (int i = box->start; i < box->start + box->len; i++) {
169 gr = max[1] - min[1];169 const struct color_ref *ref = s->refs[i];
170 br = max[2] - min[2];170 const int64_t dr = (int)(ref->color >> 16 & 0xff) - avg[0];
171 const int64_t dg = (int)(ref->color >> 8 & 0xff) - avg[1];
172 const int64_t db = (int)(ref->color & 0xff) - avg[2];
173 er2[0] += dr * dr * ref->count;
174 er2[1] += dg * dg * ref->count;
175 er2[2] += db * db * ref->count;
176 }
177
178 /* Define the best axis candidate for cutting the box */
171 box->major_axis = 1; // pick green by default (the color the eye is the most sensitive to)179 box->major_axis = 1; // pick green by default (the color the eye is the most sensitive to)
172 if (br >= rr && br >= gr) box->major_axis = 2;180 if (er2[2] >= er2[0] && er2[2] >= er2[1]) box->major_axis = 2;
173 if (rr >= gr && rr >= br) box->major_axis = 0;181 if (er2[0] >= er2[1] && er2[0] >= er2[2]) box->major_axis = 0;
174 if (gr >= rr && gr >= br) box->major_axis = 1; // prefer green again182 if (er2[1] >= er2[0] && er2[1] >= er2[2]) box->major_axis = 1; // prefer green again
175}183}
176 184
177/**185/**

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t