The variance computation is simple enough now (since we can use the axis squared errors) that it doesn't need to have a complex lazy computation logic.
Unified · Split
| @@ -135,16 +135,6 @@ static int cmp_color(const void *a, const void *b) · 134 unmodified lines | |||
| 135 | return FFDIFFSIGN(box1->color , box2->color); | 135 | return FFDIFFSIGN(box1->color , box2->color); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static av_always_inline int diff(const uint32_t a, const uint32_t b) | ||
| 139 | { | ||
| 140 | const uint8_t c1[] = {a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff}; | ||
| 141 | const uint8_t c2[] = {b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff}; | ||
| 142 | const int dr = c1[0] - c2[0]; | ||
| 143 | const int dg = c1[1] - c2[1]; | ||
| 144 | const int db = c1[2] - c2[2]; | ||
| 145 | return dr*dr + dg*dg + db*db; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void compute_box_stats(PaletteGenContext *s, struct range_box *box) | 138 | static void compute_box_stats(PaletteGenContext *s, struct range_box *box) |
| 149 | { | 139 | { |
| 150 | int avg[3]; | 140 | int avg[3]; |
| @@ -180,6 +170,8 @@ static void compute_box_stats(PaletteGenContext *s, struct range_box *box) · 29 unmodified lines | |||
| 180 | if (er2[2] >= er2[0] && er2[2] >= er2[1]) box->major_axis = 2; | 170 | if (er2[2] >= er2[0] && er2[2] >= er2[1]) box->major_axis = 2; |
| 181 | if (er2[0] >= er2[1] && er2[0] >= er2[2]) box->major_axis = 0; | 171 | if (er2[0] >= er2[1] && er2[0] >= er2[2]) box->major_axis = 0; |
| 182 | if (er2[1] >= er2[0] && er2[1] >= er2[2]) box->major_axis = 1; // prefer green again | 172 | if (er2[1] >= er2[0] && er2[1] >= er2[2]) box->major_axis = 1; // prefer green again |
| 173 | |||
| 174 | box->variance = er2[0] + er2[1] + er2[2]; | ||
| 183 | } | 175 | } |
| 184 | 176 | ||
| 185 | /** | 177 | /** |
| @@ -187,7 +179,7 @@ static void compute_box_stats(PaletteGenContext *s, struct range_box *box) · 1 unmodified line | |||
| 187 | */ | 179 | */ |
| 188 | static int get_next_box_id_to_split(PaletteGenContext *s) | 180 | static int get_next_box_id_to_split(PaletteGenContext *s) |
| 189 | { | 181 | { |
| 190 | int box_id, i, best_box_id = -1; | 182 | int box_id, best_box_id = -1; |
| 191 | int64_t max_variance = -1; | 183 | int64_t max_variance = -1; |
| 192 | 184 | ||
| 193 | if (s->nb_boxes == s->max_colors - s->reserve_transparent) | 185 | if (s->nb_boxes == s->max_colors - s->reserve_transparent) |
| @@ -195,24 +187,9 @@ static int get_next_box_id_to_split(PaletteGenContext *s) · 1 unmodified line | |||
| 195 | 187 | ||
| 196 | for (box_id = 0; box_id < s->nb_boxes; box_id++) { | 188 | for (box_id = 0; box_id < s->nb_boxes; box_id++) { |
| 197 | struct range_box *box = &s->boxes[box_id]; | 189 | struct range_box *box = &s->boxes[box_id]; |
| 198 | 190 | if (s->boxes[box_id].len >= 2 && box->variance > max_variance) { | |
| 199 | if (s->boxes[box_id].len >= 2) { | 191 | best_box_id = box_id; |
| 200 | 192 | max_variance = box->variance; | |
| 201 | if (box->variance == -1) { | ||
| 202 | int64_t variance = 0; | ||
| 203 | |||
| 204 | for (i = 0; i < box->len; i++) { | ||
| 205 | const struct color_ref *ref = s->refs[box->start + i]; | ||
| 206 | variance += diff(ref->color, box->color) * ref->count; | ||
| 207 | } | ||
| 208 | box->variance = variance; | ||
| 209 | } | ||
| 210 | if (box->variance > max_variance) { | ||
| 211 | best_box_id = box_id; | ||
| 212 | max_variance = box->variance; | ||
| 213 | } | ||
| 214 | } else { | ||
| 215 | box->variance = -1; | ||
| 216 | } | 193 | } |
| 217 | } | 194 | } |
| 218 | return best_box_id; | 195 | return best_box_id; |
| @@ -261,8 +238,8 @@ static void split_box(PaletteGenContext *s, struct range_box *box, int n) · 42 unmodified lines | |||
| 261 | 238 | ||
| 262 | box->color = get_avg_color(s->refs, box); | 239 | box->color = get_avg_color(s->refs, box); |
| 263 | new_box->color = get_avg_color(s->refs, new_box); | 240 | new_box->color = get_avg_color(s->refs, new_box); |
| 264 | box->variance = -1; | 241 | compute_box_stats(s, box); |
| 265 | new_box->variance = -1; | 242 | compute_box_stats(s, new_box); |
| 266 | } | 243 | } |
| 267 | 244 | ||
| 268 | /** | 245 | /** |
| @@ -359,14 +336,13 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) · 90 unmodified lines | |||
| 359 | box->len = s->nb_refs; | 336 | box->len = s->nb_refs; |
| 360 | box->sorted_by = -1; | 337 | box->sorted_by = -1; |
| 361 | box->color = get_avg_color(s->refs, box); | 338 | box->color = get_avg_color(s->refs, box); |
| 362 | box->variance = -1; | 339 | compute_box_stats(s, box); |
| 363 | s->nb_boxes = 1; | 340 | s->nb_boxes = 1; |
| 364 | 341 | ||
| 365 | while (box && box->len > 1) { | 342 | while (box && box->len > 1) { |
| 366 | int i; | 343 | int i; |
| 367 | uint64_t median, box_weight; | 344 | uint64_t median, box_weight; |
| 368 | 345 | ||
| 369 | compute_box_stats(s, box); | ||
| 370 | box_weight = box->weight; | 346 | box_weight = box->weight; |
| 371 | 347 | ||
| 372 | ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" sort by %c (already sorted:%c) ", | 348 | ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" sort by %c (already sorted:%c) ", |