diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index bea3292796..a047c75599 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -40,6 +40,8 @@ struct color_ref { /* Store a range of colors */ struct range_box { uint32_t color; // average color + int major_axis; // best axis candidate for cutting the box + uint64_t weight; // sum of all the weights of the colors int64_t variance; // overall variance of the box (how much the colors are spread) int start; // index in PaletteGenContext->refs int len; // number of referenced colors @@ -143,6 +145,35 @@ static av_always_inline int diff(const uint32_t a, const uint32_t b) return dr*dr + dg*dg + db*db; } +static void compute_box_stats(PaletteGenContext *s, struct range_box *box) +{ + int rr, gr, br; + + /* compute the box weight (sum all the weights of the colors in the + * range) and its boundings */ + uint8_t min[3] = {0xff, 0xff, 0xff}; + uint8_t max[3] = {0x00, 0x00, 0x00}; + box->weight = 0; + for (int i = box->start; i < box->start + box->len; i++) { + const struct color_ref *ref = s->refs[i]; + const uint32_t rgb = ref->color; + const uint8_t r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff; + min[0] = FFMIN(r, min[0]), max[0] = FFMAX(r, max[0]); + min[1] = FFMIN(g, min[1]), max[1] = FFMAX(g, max[1]); + min[2] = FFMIN(b, min[2]), max[2] = FFMAX(b, max[2]); + box->weight += ref->count; + } + + /* define the axis to sort by according to the widest range of colors */ + rr = max[0] - min[0]; + gr = max[1] - min[1]; + br = max[2] - min[2]; + box->major_axis = 1; // pick green by default (the color the eye is the most sensitive to) + if (br >= rr && br >= gr) box->major_axis = 2; + if (rr >= gr && rr >= br) box->major_axis = 0; + if (gr >= rr && gr >= br) box->major_axis = 1; // prefer green again +} + /** * Find the next box to split: pick the one with the highest variance */ @@ -324,35 +355,16 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) s->nb_boxes = 1; while (box && box->len > 1) { - int i, rr, gr, br, longest; - uint64_t median, box_weight = 0; + int i, longest; + uint64_t median, box_weight; - /* compute the box weight (sum all the weights of the colors in the - * range) and its boundings */ - uint8_t min[3] = {0xff, 0xff, 0xff}; - uint8_t max[3] = {0x00, 0x00, 0x00}; - for (i = box->start; i < box->start + box->len; i++) { - const struct color_ref *ref = s->refs[i]; - const uint32_t rgb = ref->color; - const uint8_t r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff; - min[0] = FFMIN(r, min[0]), max[0] = FFMAX(r, max[0]); - min[1] = FFMIN(g, min[1]), max[1] = FFMAX(g, max[1]); - min[2] = FFMIN(b, min[2]), max[2] = FFMAX(b, max[2]); - box_weight += ref->count; - } + compute_box_stats(s, box); + longest = box->major_axis; + box_weight = box->weight; - /* define the axis to sort by according to the widest range of colors */ - rr = max[0] - min[0]; - gr = max[1] - min[1]; - br = max[2] - min[2]; - longest = 1; // pick green by default (the color the eye is the most sensitive to) - if (br >= rr && br >= gr) longest = 2; - if (rr >= gr && rr >= br) longest = 0; - if (gr >= rr && gr >= br) longest = 1; // prefer green again - - ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" ranges:[%2x %2x %2x] sort by %c (already sorted:%c) ", + ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" sort by %c (already sorted:%c) ", box_id, box->start, box->start + box->len - 1, box->len, box_weight, - rr, gr, br, "rgb"[longest], box->sorted_by == longest ? 'y':'n'); + "rgb"[longest], box->sorted_by == longest ? 'y':'n'); /* sort the range by its longest axis if it's not already sorted */ if (box->sorted_by != longest) {