Unified · Split
| @@ -40,6 +40,8 @@ struct color_ref { · 39 unmodified lines | ||
| 40 | 40 | /* Store a range of colors */ |
| 41 | 41 | struct range_box { |
| 42 | 42 | uint32_t color; // average color |
| 43 | + int major_axis; // best axis candidate for cutting the box | |
| 44 | + uint64_t weight; // sum of all the weights of the colors | |
| 43 | 45 | int64_t variance; // overall variance of the box (how much the colors are spread) |
| 44 | 46 | int start; // index in PaletteGenContext->refs |
| 45 | 47 | int len; // number of referenced colors |
| @@ -143,6 +145,35 @@ static av_always_inline int diff(const uint32_t a, const uint32_t b) · 97 unmodified lines | ||
| 143 | 145 | return dr*dr + dg*dg + db*db; |
| 144 | 146 | } |
| 145 | 147 | |
| 148 | +static void compute_box_stats(PaletteGenContext *s, struct range_box *box) | |
| 149 | +{ | |
| 150 | + int rr, gr, br; | |
| 151 | + | |
| 152 | + /* compute the box weight (sum all the weights of the colors in the | |
| 153 | + * range) and its boundings */ | |
| 154 | + uint8_t min[3] = {0xff, 0xff, 0xff}; | |
| 155 | + uint8_t max[3] = {0x00, 0x00, 0x00}; | |
| 156 | + box->weight = 0; | |
| 157 | + for (int i = box->start; i < box->start + box->len; i++) { | |
| 158 | + const struct color_ref *ref = s->refs[i]; | |
| 159 | + const uint32_t rgb = ref->color; | |
| 160 | + const uint8_t r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff; | |
| 161 | + min[0] = FFMIN(r, min[0]), max[0] = FFMAX(r, max[0]); | |
| 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; | |
| 165 | + } | |
| 166 | + | |
| 167 | + /* define the axis to sort by according to the widest range of colors */ | |
| 168 | + rr = max[0] - min[0]; | |
| 169 | + gr = max[1] - min[1]; | |
| 170 | + br = max[2] - min[2]; | |
| 171 | + 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; | |
| 173 | + if (rr >= gr && rr >= br) box->major_axis = 0; | |
| 174 | + if (gr >= rr && gr >= br) box->major_axis = 1; // prefer green again | |
| 175 | +} | |
| 176 | + | |
| 146 | 177 | /** |
| 147 | 178 | * Find the next box to split: pick the one with the highest variance |
| 148 | 179 | */ |
| @@ -324,35 +355,16 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) · 175 unmodified lines | ||
| 324 | 355 | s->nb_boxes = 1; |
| 325 | 356 | |
| 326 | 357 | while (box && box->len > 1) { |
| 327 | − int i, rr, gr, br, longest; | |
| 328 | − uint64_t median, box_weight = 0; | |
| 329 | − | |
| 330 | − /* compute the box weight (sum all the weights of the colors in the | |
| 331 | − * range) and its boundings */ | |
| 332 | − uint8_t min[3] = {0xff, 0xff, 0xff}; | |
| 333 | − uint8_t max[3] = {0x00, 0x00, 0x00}; | |
| 334 | − for (i = box->start; i < box->start + box->len; i++) { | |
| 335 | − const struct color_ref *ref = s->refs[i]; | |
| 336 | − const uint32_t rgb = ref->color; | |
| 337 | − const uint8_t r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff; | |
| 338 | − min[0] = FFMIN(r, min[0]), max[0] = FFMAX(r, max[0]); | |
| 339 | − min[1] = FFMIN(g, min[1]), max[1] = FFMAX(g, max[1]); | |
| 340 | − min[2] = FFMIN(b, min[2]), max[2] = FFMAX(b, max[2]); | |
| 341 | − box_weight += ref->count; | |
| 342 | − } | |
| 358 | + int i, longest; | |
| 359 | + uint64_t median, box_weight; | |
| 343 | 360 | |
| 344 | − /* define the axis to sort by according to the widest range of colors */ | |
| 345 | − rr = max[0] - min[0]; | |
| 346 | − gr = max[1] - min[1]; | |
| 347 | − br = max[2] - min[2]; | |
| 348 | − longest = 1; // pick green by default (the color the eye is the most sensitive to) | |
| 349 | − if (br >= rr && br >= gr) longest = 2; | |
| 350 | − if (rr >= gr && rr >= br) longest = 0; | |
| 351 | − if (gr >= rr && gr >= br) longest = 1; // prefer green again | |
| 361 | + compute_box_stats(s, box); | |
| 362 | + longest = box->major_axis; | |
| 363 | + box_weight = box->weight; | |
| 352 | 364 | |
| 353 | − ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" ranges:[%2x %2x %2x] sort by %c (already sorted:%c) ", | |
| 365 | + ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" sort by %c (already sorted:%c) ", | |
| 354 | 366 | box_id, box->start, box->start + box->len - 1, box->len, box_weight, |
| 355 | − rr, gr, br, "rgb"[longest], box->sorted_by == longest ? 'y':'n'); | |
| 367 | + "rgb"[longest], box->sorted_by == longest ? 'y':'n'); | |
| 356 | 368 | |
| 357 | 369 | /* sort the range by its longest axis if it's not already sorted */ |
| 358 | 370 | if (box->sorted_by != longest) { |