From patchwork Sat Nov 5 15:26:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39165 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085019pzb; Sat, 5 Nov 2022 08:26:47 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4748cXeYcZfd0V3z8FrZYtz96AfFdaYP6vkaFXDs0l4/398X01r2CutwIVb5dCBHKM0CEo X-Received: by 2002:a17:906:9bcd:b0:7ae:2679:c47 with SMTP id de13-20020a1709069bcd00b007ae26790c47mr11099102ejc.353.1667662007703; Sat, 05 Nov 2022 08:26:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662007; cv=none; d=google.com; s=arc-20160816; b=iqjHrouRq5+s29nKfRVuJtNDtWoMq4aWh59fzjjT7AOHwhN/Vw5/CAtH3Oz/9A5naW 4+AYGsfc6Z/rLxsvxpgKbuckOU1xSOsO4iX/cEaAG6DOIaUldBI7tRi6Rr9Pg9+Rb7Dw Wtbp2M6wd3VwjbVVDaIrXxcUoWLfF+fae03UjbyCPy8gLyBA8GkPGOJXYakFljwZdEwP gJACSd1cgpZRiPQIw+xTzhyqcvg+fmRzKZXziHn+TkSsfPC6ajJkH3hQfo9/nMuoUaUH pUDqAR6aMTpvW5FQiRvuDMajBSd0owd07jOTh6nNoE9eWrPV5OldIsJJQYRSKhEJPjfK C6FQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=sjhx2Py19PeaJ1M/U0IzGdQyzTMG6JnWtkbePyj0Hsg=; b=l2vfKjQkHchR8GDpYWlwfo1Znt8F6TkDnL1C4OeRG5lDNWMuu5uCZCrJzvJtDNkbdu CcvhFznl+dSh3882TjoByk/wYWxdxP2toxuouXfKvw7FfXdEpcC+TqwFqhKacmY35Cxe F1QJEbg8Da8N3SGVCKlqIY3sCLDRSzImmE3OuZs0oQPUs9LJeic15QEJMvrNcIZcFM8E ly9ddDpMSAtZx8ZfiTdnAewP0Ejt1+18CmsiXtJJGUZboMVBwR6YJFPRsFE1iSZO3/00 y85zAQnCMSmbao0fKKQ+V6+qG1GjYyFlX7w0TH2IUnZEVYTzODJukCuW1HiiWZm9xewn obJQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=oQrPzCas; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id wj7-20020a170907050700b007330c08fe49si1541199ejb.206.2022.11.05.08.26.47; Sat, 05 Nov 2022 08:26:47 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=oQrPzCas; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 58AC568B1E1; Sat, 5 Nov 2022 17:26:32 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EAC3D68B0DD for ; Sat, 5 Nov 2022 17:26:25 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661980; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0RHvZRuEYar7qNxl/M/nk1LWeRlZuGs/D15p6tCCfig=; b=oQrPzCasEj3ziMaFBbAZGBeVmaOP8wsoqNDKgUgXR/nwpen2wcn5+5I4W3pRs3M/bbIFvj f7EOspJG0KoqbasaeaAsCXHzBtfr/ItYozphtCXSTqJOwJtEn4y9KCABG3JncOWuLguOtS Hlbb3fahkU6SXgwjlxETVJ4Uojok5Dc= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id dac09a57; Sat, 5 Nov 2022 15:26:20 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:03 +0100 Message-Id: <20221105152617.1809282-2-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 01/15] Revert "avfilter/vf_palette(gen|use): support palettes with alpha" X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: mNWEXJyATLtS This reverts commit dea673d0d548c864ec85f9260d8900d944ef7a2a. This change cannot work for several reasons, the most obvious ones are: - the alpha is being part of the scoring of the color difference, even though we can not interpret the alpha as part of the perception of the color (we don't even know if it's premultiplied or postmultiplied) - the colors are averaged with their alpha value which simply cannot work The command proposed in the original thread of the patch actually produces a completely broken file: ffmpeg -y -loglevel verbose -i fate-suite/apng/o_sample.png -filter_complex "split[split1][split2];[split1]palettegen=max_colors=254:use_alpha=1[pal1];[split2][pal1]paletteuse=use_alpha=1" -frames:v 1 out.png We can see that many color pixels are off, but more importantly some colors have a random alpha value: https://imgur.com/eFQ2UK7 I don't see any easy fix for this unfortunately, the approach appears to be flawed by design. --- doc/filters.texi | 8 -- libavfilter/vf_palettegen.c | 135 +++++++--------------- libavfilter/vf_paletteuse.c | 225 +++++++++++++++--------------------- 3 files changed, 138 insertions(+), 230 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 721549c2c7..251f647ee9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18288,9 +18288,6 @@ Compute new histogram for each frame. @end table Default value is @var{full}. -@item use_alpha -Create a palette of colors with alpha components. -Setting this, will automatically disable 'reserve_transparent'. @end table The filter also exports the frame metadata @code{lavfi.color_quant_ratio} @@ -18369,11 +18366,6 @@ will be treated as completely opaque, and values below this threshold will be treated as completely transparent. The option must be an integer value in the range [0,255]. Default is @var{128}. - -@item use_alpha -Apply the palette by taking alpha values into account. Only useful with -palettes that are containing multiple colors with alpha components. -Setting this will automatically disable 'alpha_treshold'. @end table @subsection Examples diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 27f74fd147..d335ef91e6 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -59,7 +59,7 @@ enum { }; #define NBITS 5 -#define HIST_SIZE (1<<(4*NBITS)) +#define HIST_SIZE (1<<(3*NBITS)) typedef struct PaletteGenContext { const AVClass *class; @@ -67,7 +67,6 @@ typedef struct PaletteGenContext { int max_colors; int reserve_transparent; int stats_mode; - int use_alpha; AVFrame *prev_frame; // previous frame used for the diff stats_mode struct hist_node histogram[HIST_SIZE]; // histogram/hashtable of the colors @@ -89,7 +88,6 @@ static const AVOption palettegen_options[] = { { "full", "compute full frame histograms", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_ALL_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, { "diff", "compute histograms only for the part that differs from previous frame", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_DIFF_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, { "single", "compute new histogram for each frame", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_SINGLE_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, - { "use_alpha", "create a palette including alpha values", OFFSET(use_alpha), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, { NULL } }; @@ -115,16 +113,15 @@ static int cmp_##name(const void *pa, const void *pb) \ { \ const struct color_ref * const *a = pa; \ const struct color_ref * const *b = pb; \ - return (int)((*a)->color >> (8 * (3 - (pos))) & 0xff) \ - - (int)((*b)->color >> (8 * (3 - (pos))) & 0xff); \ + return (int)((*a)->color >> (8 * (2 - (pos))) & 0xff) \ + - (int)((*b)->color >> (8 * (2 - (pos))) & 0xff); \ } -DECLARE_CMP_FUNC(a, 0) -DECLARE_CMP_FUNC(r, 1) -DECLARE_CMP_FUNC(g, 2) -DECLARE_CMP_FUNC(b, 3) +DECLARE_CMP_FUNC(r, 0) +DECLARE_CMP_FUNC(g, 1) +DECLARE_CMP_FUNC(b, 2) -static const cmp_func cmp_funcs[] = {cmp_a, cmp_r, cmp_g, cmp_b}; +static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; /** * Simple color comparison for sorting the final palette @@ -146,17 +143,6 @@ static av_always_inline int diff(const uint32_t a, const uint32_t b) return dr*dr + dg*dg + db*db; } -static av_always_inline int diff_alpha(const uint32_t a, const uint32_t b) -{ - const uint8_t c1[] = {a >> 24 & 0xff, a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff}; - const uint8_t c2[] = {b >> 24 & 0xff, b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff}; - const int da = c1[0] - c2[0]; - const int dr = c1[1] - c2[1]; - const int dg = c1[2] - c2[2]; - const int db = c1[3] - c2[3]; - return da*da + dr*dr + dg*dg + db*db; -} - /** * Find the next box to split: pick the one with the highest variance */ @@ -178,10 +164,7 @@ static int get_next_box_id_to_split(PaletteGenContext *s) for (i = 0; i < box->len; i++) { const struct color_ref *ref = s->refs[box->start + i]; - if (s->use_alpha) - variance += (int64_t)diff_alpha(ref->color, box->color) * ref->count; - else - variance += (int64_t)diff(ref->color, box->color) * ref->count; + variance += diff(ref->color, box->color) * ref->count; } box->variance = variance; } @@ -201,31 +184,24 @@ static int get_next_box_id_to_split(PaletteGenContext *s) * specified box. Takes into account the weight of each color. */ static uint32_t get_avg_color(struct color_ref * const *refs, - const struct range_box *box, int use_alpha) + const struct range_box *box) { int i; const int n = box->len; - uint64_t a = 0, r = 0, g = 0, b = 0, div = 0; + uint64_t r = 0, g = 0, b = 0, div = 0; for (i = 0; i < n; i++) { const struct color_ref *ref = refs[box->start + i]; - if (use_alpha) - a += (ref->color >> 24 & 0xff) * ref->count; - r += (ref->color >> 16 & 0xff) * ref->count; - g += (ref->color >> 8 & 0xff) * ref->count; - b += (ref->color & 0xff) * ref->count; + r += (ref->color >> 16 & 0xff) * ref->count; + g += (ref->color >> 8 & 0xff) * ref->count; + b += (ref->color & 0xff) * ref->count; div += ref->count; } - if (use_alpha) - a = a / div; r = r / div; g = g / div; b = b / div; - if (use_alpha) - return a<<24 | r<<16 | g<<8 | b; - return 0xffU<<24 | r<<16 | g<<8 | b; } @@ -244,8 +220,8 @@ static void split_box(PaletteGenContext *s, struct range_box *box, int n) av_assert0(box->len >= 1); av_assert0(new_box->len >= 1); - box->color = get_avg_color(s->refs, box, s->use_alpha); - new_box->color = get_avg_color(s->refs, new_box, s->use_alpha); + box->color = get_avg_color(s->refs, box); + new_box->color = get_avg_color(s->refs, new_box); box->variance = -1; new_box->variance = -1; } @@ -275,7 +251,7 @@ static void write_palette(AVFilterContext *ctx, AVFrame *out) pal += pal_linesize; } - if (s->reserve_transparent && !s->use_alpha) { + if (s->reserve_transparent) { av_assert0(s->nb_boxes < 256); pal[out->width - pal_linesize - 1] = AV_RB32(&s->transparency_color) >> 8; } @@ -343,49 +319,40 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) box = &s->boxes[box_id]; box->len = s->nb_refs; box->sorted_by = -1; - box->color = get_avg_color(s->refs, box, s->use_alpha); + box->color = get_avg_color(s->refs, box); box->variance = -1; s->nb_boxes = 1; while (box && box->len > 1) { - int i, ar, rr, gr, br, longest; + int i, rr, gr, br, longest; uint64_t median, box_weight = 0; /* compute the box weight (sum all the weights of the colors in the * range) and its boundings */ - uint8_t min[4] = {0xff, 0xff, 0xff, 0xff}; - uint8_t max[4] = {0x00, 0x00, 0x00, 0x00}; + 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 a = rgb >> 24 & 0xff, r = rgb >> 16 & 0xff, g = rgb >> 8 & 0xff, b = rgb & 0xff; - min[0] = FFMIN(a, min[0]); max[0] = FFMAX(a, max[0]); - min[1] = FFMIN(r, min[1]); max[1] = FFMAX(r, max[1]); - min[2] = FFMIN(g, min[2]); max[2] = FFMAX(g, max[2]); - min[3] = FFMIN(b, min[3]); max[3] = FFMAX(b, max[3]); + 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 */ - ar = max[0] - min[0]; - rr = max[1] - min[1]; - gr = max[2] - min[2]; - br = max[3] - min[3]; - longest = 2; // pick green by default (the color the eye is the most sensitive to) - if (s->use_alpha) { - if (ar >= rr && ar >= br && ar >= gr) longest = 0; - if (br >= rr && br >= gr && br >= ar) longest = 3; - if (rr >= gr && rr >= br && rr >= ar) longest = 1; - if (gr >= rr && gr >= br && gr >= ar) longest = 2; // prefer green again - } else { - if (br >= rr && br >= gr) longest = 3; - if (rr >= gr && rr >= br) longest = 1; - if (gr >= rr && gr >= br) longest = 2; // prefer green again - } - - ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" ranges:[%2x %2x %2x %2x] sort by %c (already sorted:%c) ", + 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) ", box_id, box->start, box->start + box->len - 1, box->len, box_weight, - ar, rr, gr, br, "argb"[longest], box->sorted_by == longest ? 'y' : 'n'); + rr, gr, br, "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) { @@ -427,27 +394,22 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) * It keeps the NBITS least significant bit of each component to make it * "random" even if the scene doesn't have much different colors. */ -static inline unsigned color_hash(uint32_t color, int use_alpha) +static inline unsigned color_hash(uint32_t color) { const uint8_t r = color >> 16 & ((1<> 8 & ((1<> 24 & ((1 << NBITS) - 1); - return a << (NBITS * 3) | r << (NBITS * 2) | g << NBITS | b; - } - return r << (NBITS * 2) | g << NBITS | b; } /** * Locate the color in the hash table and increment its counter. */ -static int color_inc(struct hist_node *hist, uint32_t color, int use_alpha) +static int color_inc(struct hist_node *hist, uint32_t color) { int i; - const unsigned hash = color_hash(color, use_alpha); + const unsigned hash = color_hash(color); struct hist_node *node = &hist[hash]; struct color_ref *e; @@ -472,7 +434,7 @@ static int color_inc(struct hist_node *hist, uint32_t color, int use_alpha) * Update histogram when pixels differ from previous frame. */ static int update_histogram_diff(struct hist_node *hist, - const AVFrame *f1, const AVFrame *f2, int use_alpha) + const AVFrame *f1, const AVFrame *f2) { int x, y, ret, nb_diff_colors = 0; @@ -483,7 +445,7 @@ static int update_histogram_diff(struct hist_node *hist, for (x = 0; x < f1->width; x++) { if (p[x] == q[x]) continue; - ret = color_inc(hist, p[x], use_alpha); + ret = color_inc(hist, p[x]); if (ret < 0) return ret; nb_diff_colors += ret; @@ -495,7 +457,7 @@ static int update_histogram_diff(struct hist_node *hist, /** * Simple histogram of the frame. */ -static int update_histogram_frame(struct hist_node *hist, const AVFrame *f, int use_alpha) +static int update_histogram_frame(struct hist_node *hist, const AVFrame *f) { int x, y, ret, nb_diff_colors = 0; @@ -503,7 +465,7 @@ static int update_histogram_frame(struct hist_node *hist, const AVFrame *f, int const uint32_t *p = (const uint32_t *)(f->data[0] + y*f->linesize[0]); for (x = 0; x < f->width; x++) { - ret = color_inc(hist, p[x], use_alpha); + ret = color_inc(hist, p[x]); if (ret < 0) return ret; nb_diff_colors += ret; @@ -519,8 +481,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; PaletteGenContext *s = ctx->priv; - int ret = s->prev_frame ? update_histogram_diff(s->histogram, s->prev_frame, in, s->use_alpha) - : update_histogram_frame(s->histogram, in, s->use_alpha); + int ret = s->prev_frame ? update_histogram_diff(s->histogram, s->prev_frame, in) + : update_histogram_frame(s->histogram, in); if (ret > 0) s->nb_refs += ret; @@ -579,16 +541,6 @@ static int config_output(AVFilterLink *outlink) return 0; } -static int init(AVFilterContext *ctx) -{ - PaletteGenContext* s = ctx->priv; - - if (s->use_alpha && s->reserve_transparent) - s->reserve_transparent = 0; - - return 0; -} - static av_cold void uninit(AVFilterContext *ctx) { int i; @@ -621,7 +573,6 @@ const AVFilter ff_vf_palettegen = { .name = "palettegen", .description = NULL_IF_CONFIG_SMALL("Find the optimal palette for a given stream."), .priv_size = sizeof(PaletteGenContext), - .init = init, .uninit = uninit, FILTER_INPUTS(palettegen_inputs), FILTER_OUTPUTS(palettegen_outputs), diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index a6b5d5a5fa..cb18329bb7 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "libavutil/qsort.h" #include "avfilter.h" +#include "filters.h" #include "framesync.h" #include "internal.h" @@ -63,7 +64,7 @@ struct color_node { }; #define NBITS 5 -#define CACHE_SIZE (1<<(4*NBITS)) +#define CACHE_SIZE (1<<(3*NBITS)) struct cached_color { uint32_t color; @@ -88,7 +89,6 @@ typedef struct PaletteUseContext { uint32_t palette[AVPALETTE_COUNT]; int transparency_index; /* index in the palette of transparency. -1 if there is no transparency in the palette. */ int trans_thresh; - int use_alpha; int palette_loaded; int dither; int new; @@ -108,7 +108,7 @@ typedef struct PaletteUseContext { } PaletteUseContext; #define OFFSET(x) offsetof(PaletteUseContext, x) -#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption paletteuse_options[] = { { "dither", "select dithering mode", OFFSET(dither), AV_OPT_TYPE_INT, {.i64=DITHERING_SIERRA2_4A}, 0, NB_DITHERING-1, FLAGS, "dithering_mode" }, { "bayer", "ordered 8x8 bayer dithering (deterministic)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_BAYER}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" }, @@ -121,7 +121,6 @@ static const AVOption paletteuse_options[] = { { "rectangle", "process smallest different rectangle", 0, AV_OPT_TYPE_CONST, {.i64=DIFF_MODE_RECTANGLE}, INT_MIN, INT_MAX, FLAGS, "diff_mode" }, { "new", "take new palette for each output frame", OFFSET(new), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "alpha_threshold", "set the alpha threshold for transparency", OFFSET(trans_thresh), AV_OPT_TYPE_INT, {.i64=128}, 0, 255, FLAGS }, - { "use_alpha", "use alpha channel for mapping", OFFSET(use_alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, /* following are the debug options, not part of the official API */ { "debug_kdtree", "save Graphviz graph of the kdtree in specified file", OFFSET(dot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, @@ -163,41 +162,37 @@ static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, | av_clip_uint8((px & 0xff) + ((eb * scale) / (1<use_alpha) - return da*da + dr*dr + dg*dg + db*db; - - if (c1[0] < s->trans_thresh && c2[0] < s->trans_thresh) { + if (c1[0] < trans_thresh && c2[0] < trans_thresh) { return 0; - } else if (c1[0] >= s->trans_thresh && c2[0] >= s->trans_thresh) { + } else if (c1[0] >= trans_thresh && c2[0] >= trans_thresh) { return dr*dr + dg*dg + db*db; } else { return 255*255 + 255*255 + 255*255; } } -static av_always_inline uint8_t colormap_nearest_bruteforce(const PaletteUseContext *s, const uint8_t *argb) +static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint8_t *argb, const int trans_thresh) { int i, pal_id = -1, min_dist = INT_MAX; for (i = 0; i < AVPALETTE_COUNT; i++) { - const uint32_t c = s->palette[i]; + const uint32_t c = palette[i]; - if (s->use_alpha || c >> 24 >= s->trans_thresh) { // ignore transparent entry + if (c >> 24 >= trans_thresh) { // ignore transparent entry const uint8_t palargb[] = { - s->palette[i]>>24 & 0xff, - s->palette[i]>>16 & 0xff, - s->palette[i]>> 8 & 0xff, - s->palette[i] & 0xff, + palette[i]>>24 & 0xff, + palette[i]>>16 & 0xff, + palette[i]>> 8 & 0xff, + palette[i] & 0xff, }; - const int d = diff(palargb, argb, s); + const int d = diff(palargb, argb, trans_thresh); if (d < min_dist) { pal_id = i; min_dist = d; @@ -213,17 +208,17 @@ struct nearest_color { int dist_sqd; }; -static void colormap_nearest_node(const PaletteUseContext *s, - const struct color_node *map, +static void colormap_nearest_node(const struct color_node *map, const int node_pos, const uint8_t *target, + const int trans_thresh, struct nearest_color *nearest) { const struct color_node *kd = map + node_pos; - const int split = kd->split; + const int s = kd->split; int dx, nearer_kd_id, further_kd_id; const uint8_t *current = kd->val; - const int current_to_target = diff(target, current, s); + const int current_to_target = diff(target, current, trans_thresh); if (current_to_target < nearest->dist_sqd) { nearest->node_pos = node_pos; @@ -231,23 +226,23 @@ static void colormap_nearest_node(const PaletteUseContext *s, } if (kd->left_id != -1 || kd->right_id != -1) { - dx = target[split] - current[split]; + dx = target[s] - current[s]; if (dx <= 0) nearer_kd_id = kd->left_id, further_kd_id = kd->right_id; else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id; if (nearer_kd_id != -1) - colormap_nearest_node(s, map, nearer_kd_id, target, nearest); + colormap_nearest_node(map, nearer_kd_id, target, trans_thresh, nearest); if (further_kd_id != -1 && dx*dx < nearest->dist_sqd) - colormap_nearest_node(s, map, further_kd_id, target, nearest); + colormap_nearest_node(map, further_kd_id, target, trans_thresh, nearest); } } -static av_always_inline uint8_t colormap_nearest_recursive(const PaletteUseContext *s, const struct color_node *node, const uint8_t *rgb) +static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t *rgb, const int trans_thresh) { struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1}; - colormap_nearest_node(s, node, 0, rgb, &res); + colormap_nearest_node(node, 0, rgb, trans_thresh, &res); return node[res.node_pos].palette_id; } @@ -256,7 +251,7 @@ struct stack_node { int dx2; }; -static av_always_inline uint8_t colormap_nearest_iterative(const PaletteUseContext *s, const struct color_node *root, const uint8_t *target) +static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint8_t *target, const int trans_thresh) { int pos = 0, best_node_id = -1, best_dist = INT_MAX, cur_color_id = 0; struct stack_node nodes[16]; @@ -266,7 +261,7 @@ static av_always_inline uint8_t colormap_nearest_iterative(const PaletteUseConte const struct color_node *kd = &root[cur_color_id]; const uint8_t *current = kd->val; - const int current_to_target = diff(target, current, s); + const int current_to_target = diff(target, current, trans_thresh); /* Compare current color node to the target and update our best node if * it's actually better. */ @@ -328,10 +323,10 @@ end: return root[best_node_id].palette_id; } -#define COLORMAP_NEAREST(s, search, root, target) \ - search == COLOR_SEARCH_NNS_ITERATIVE ? colormap_nearest_iterative(s, root, target) : \ - search == COLOR_SEARCH_NNS_RECURSIVE ? colormap_nearest_recursive(s, root, target) : \ - colormap_nearest_bruteforce(s, target) +#define COLORMAP_NEAREST(search, palette, root, target, trans_thresh) \ + search == COLOR_SEARCH_NNS_ITERATIVE ? colormap_nearest_iterative(root, target, trans_thresh) : \ + search == COLOR_SEARCH_NNS_RECURSIVE ? colormap_nearest_recursive(root, target, trans_thresh) : \ + colormap_nearest_bruteforce(palette, target, trans_thresh) /** * Check if the requested color is in the cache already. If not, find it in the @@ -368,13 +363,13 @@ static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, if (!e) return AVERROR(ENOMEM); e->color = color; - e->pal_entry = COLORMAP_NEAREST(s, search_method, s->map, argb_elts); + e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, argb_elts, s->trans_thresh); return e->pal_entry; } static av_always_inline int get_dst_color_err(PaletteUseContext *s, - uint32_t c, int *ea, int *er, int *eg, int *eb, + uint32_t c, int *er, int *eg, int *eb, const enum color_search_method search_method) { const uint8_t a = c >> 24 & 0xff; @@ -387,9 +382,8 @@ static av_always_inline int get_dst_color_err(PaletteUseContext *s, return dstx; dstc = s->palette[dstx]; if (dstx == s->transparency_index) { - *ea =*er = *eg = *eb = 0; + *er = *eg = *eb = 0; } else { - *ea = (int)a - (int)(dstc >> 24 & 0xff); *er = (int)r - (int)(dstc >> 16 & 0xff); *eg = (int)g - (int)(dstc >> 8 & 0xff); *eb = (int)b - (int)(dstc & 0xff); @@ -413,7 +407,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram for (y = y_start; y < h; y++) { for (x = x_start; x < w; x++) { - int ea, er, eg, eb; + int er, eg, eb; if (dither == DITHERING_BAYER) { const int d = s->ordered_dither[(y & 7)<<3 | (x & 7)]; @@ -433,7 +427,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_HECKBERT) { const int right = x < w - 1, down = y < h - 1; - const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -445,7 +439,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_FLOYD_STEINBERG) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -459,7 +453,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; const int right2 = x < w - 2, left2 = x > x_start + 1; - const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -478,7 +472,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2_4A) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -561,7 +555,8 @@ static int disp_tree(const struct color_node *node, const char *fname) return 0; } -static int debug_accuracy(const PaletteUseContext *s) +static int debug_accuracy(const struct color_node *node, const uint32_t *palette, const int trans_thresh, + const enum color_search_method search_method) { int r, g, b, ret = 0; @@ -569,26 +564,19 @@ static int debug_accuracy(const PaletteUseContext *s) for (g = 0; g < 256; g++) { for (b = 0; b < 256; b++) { const uint8_t argb[] = {0xff, r, g, b}; - const int r1 = COLORMAP_NEAREST(s, s->color_search_method, s->map, argb); - const int r2 = colormap_nearest_bruteforce(s, argb); + const int r1 = COLORMAP_NEAREST(search_method, palette, node, argb, trans_thresh); + const int r2 = colormap_nearest_bruteforce(palette, argb, trans_thresh); if (r1 != r2) { - const uint32_t c1 = s->palette[r1]; - const uint32_t c2 = s->palette[r2]; - const uint8_t a1 = s->use_alpha ? c1>>24 & 0xff : 0xff; - const uint8_t a2 = s->use_alpha ? c2>>24 & 0xff : 0xff; - const uint8_t palargb1[] = { a1, c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; - const uint8_t palargb2[] = { a2, c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; - const int d1 = diff(palargb1, argb, s); - const int d2 = diff(palargb2, argb, s); + const uint32_t c1 = palette[r1]; + const uint32_t c2 = palette[r2]; + const uint8_t palargb1[] = { 0xff, c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; + const uint8_t palargb2[] = { 0xff, c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; + const int d1 = diff(palargb1, argb, trans_thresh); + const int d2 = diff(palargb2, argb, trans_thresh); if (d1 != d2) { - if (s->use_alpha) - av_log(NULL, AV_LOG_ERROR, - "/!\\ %02X%02X%02X: %d ! %d (%08"PRIX32" ! %08"PRIX32") / dist: %d ! %d\n", - r, g, b, r1, r2, c1, c2, d1, d2); - else - av_log(NULL, AV_LOG_ERROR, - "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", - r, g, b, r1, r2, c1 & 0xffffff, c2 & 0xffffff, d1, d2); + av_log(NULL, AV_LOG_ERROR, + "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", + r, g, b, r1, r2, c1 & 0xffffff, c2 & 0xffffff, d1, d2); ret = 1; } } @@ -604,8 +592,8 @@ struct color { }; struct color_rect { - uint8_t min[4]; - uint8_t max[4]; + uint8_t min[3]; + uint8_t max[3]; }; typedef int (*cmp_func)(const void *, const void *); @@ -626,47 +614,43 @@ DECLARE_CMP_FUNC(b, 3) static const cmp_func cmp_funcs[] = {cmp_a, cmp_r, cmp_g, cmp_b}; -static int get_next_color(const uint8_t *color_used, const PaletteUseContext *s, +static int get_next_color(const uint8_t *color_used, const uint32_t *palette, + const int trans_thresh, int *component, const struct color_rect *box) { - int wa, wr, wg, wb; + int wr, wg, wb; int i, longest = 0; unsigned nb_color = 0; struct color_rect ranges; struct color tmp_pal[256]; cmp_func cmpf; - ranges.min[0] = ranges.min[1] = ranges.min[2] = ranges.min[3]= 0xff; - ranges.max[0] = ranges.max[1] = ranges.max[2] = ranges.max[3]= 0x00; + ranges.min[0] = ranges.min[1] = ranges.min[2] = 0xff; + ranges.max[0] = ranges.max[1] = ranges.max[2] = 0x00; for (i = 0; i < AVPALETTE_COUNT; i++) { - const uint32_t c = s->palette[i]; + const uint32_t c = palette[i]; const uint8_t a = c >> 24 & 0xff; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; - if (!s->use_alpha && a < s->trans_thresh) { + if (a < trans_thresh) { continue; } - if (color_used[i] || (a != 0xff && !s->use_alpha) || - r < box->min[1] || g < box->min[2] || b < box->min[3] || - r > box->max[1] || g > box->max[2] || b > box->max[3]) + if (color_used[i] || (a != 0xff) || + r < box->min[0] || g < box->min[1] || b < box->min[2] || + r > box->max[0] || g > box->max[1] || b > box->max[2]) continue; - if (s->use_alpha && (a < box->min[0] || a > box->max[0])) - continue; - - if (a < ranges.min[0]) ranges.min[0] = a; - if (r < ranges.min[1]) ranges.min[1] = r; - if (g < ranges.min[2]) ranges.min[2] = g; - if (b < ranges.min[3]) ranges.min[3] = b; + if (r < ranges.min[0]) ranges.min[0] = r; + if (g < ranges.min[1]) ranges.min[1] = g; + if (b < ranges.min[2]) ranges.min[2] = b; - if (a > ranges.max[0]) ranges.max[0] = a; - if (r > ranges.max[1]) ranges.max[1] = r; - if (g > ranges.max[2]) ranges.max[2] = g; - if (b > ranges.max[3]) ranges.max[3] = b; + if (r > ranges.max[0]) ranges.max[0] = r; + if (g > ranges.max[1]) ranges.max[1] = g; + if (b > ranges.max[2]) ranges.max[2] = b; tmp_pal[nb_color].value = c; tmp_pal[nb_color].pal_id = i; @@ -678,22 +662,12 @@ static int get_next_color(const uint8_t *color_used, const PaletteUseContext *s, return -1; /* define longest axis that will be the split component */ - wa = ranges.max[0] - ranges.min[0]; - wr = ranges.max[1] - ranges.min[1]; - wg = ranges.max[2] - ranges.min[2]; - wb = ranges.max[3] - ranges.min[3]; - - if (s->use_alpha) { - if (wa >= wr && wa >= wb && wa >= wg) longest = 0; - if (wr >= wg && wr >= wb && wr >= wa) longest = 1; - if (wg >= wr && wg >= wb && wg >= wa) longest = 2; - if (wb >= wr && wb >= wg && wb >= wa) longest = 3; - } else { - if (wr >= wg && wr >= wb) longest = 1; - if (wg >= wr && wg >= wb) longest = 2; - if (wb >= wr && wb >= wg) longest = 3; - } - + wr = ranges.max[0] - ranges.min[0]; + wg = ranges.max[1] - ranges.min[1]; + wb = ranges.max[2] - ranges.min[2]; + if (wr >= wg && wr >= wb) longest = 1; + if (wg >= wr && wg >= wb) longest = 2; + if (wb >= wr && wb >= wg) longest = 3; cmpf = cmp_funcs[longest]; *component = longest; @@ -706,7 +680,8 @@ static int get_next_color(const uint8_t *color_used, const PaletteUseContext *s, static int colormap_insert(struct color_node *map, uint8_t *color_used, int *nb_used, - const PaletteUseContext *s, + const uint32_t *palette, + const int trans_thresh, const struct color_rect *box) { uint32_t c; @@ -714,14 +689,14 @@ static int colormap_insert(struct color_node *map, int node_left_id = -1, node_right_id = -1; struct color_node *node; struct color_rect box1, box2; - const int pal_id = get_next_color(color_used, s, &component, box); + const int pal_id = get_next_color(color_used, palette, trans_thresh, &component, box); if (pal_id < 0) return -1; /* create new node with that color */ cur_id = (*nb_used)++; - c = s->palette[pal_id]; + c = palette[pal_id]; node = &map[cur_id]; node->split = component; node->palette_id = pal_id; @@ -734,13 +709,13 @@ static int colormap_insert(struct color_node *map, /* get the two boxes this node creates */ box1 = box2 = *box; - box1.max[component] = node->val[component]; - box2.min[component] = FFMIN(node->val[component] + 1, 255); + box1.max[component-1] = node->val[component]; + box2.min[component-1] = FFMIN(node->val[component] + 1, 255); - node_left_id = colormap_insert(map, color_used, nb_used, s, &box1); + node_left_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box1); - if (box2.min[component] <= box2.max[component]) - node_right_id = colormap_insert(map, color_used, nb_used, s, &box2); + if (box2.min[component-1] <= box2.max[component-1]) + node_right_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box2); node->left_id = node_left_id; node->right_id = node_right_id; @@ -755,13 +730,6 @@ static int cmp_pal_entry(const void *a, const void *b) return c1 - c2; } -static int cmp_pal_entry_alpha(const void *a, const void *b) -{ - const int c1 = *(const uint32_t *)a; - const int c2 = *(const uint32_t *)b; - return c1 - c2; -} - static void load_colormap(PaletteUseContext *s) { int i, nb_used = 0; @@ -769,13 +737,12 @@ static void load_colormap(PaletteUseContext *s) uint32_t last_color = 0; struct color_rect box; - if (!s->use_alpha && s->transparency_index >= 0) { + if (s->transparency_index >= 0) { FFSWAP(uint32_t, s->palette[s->transparency_index], s->palette[255]); } /* disable transparent colors and dups */ - qsort(s->palette, AVPALETTE_COUNT-(s->transparency_index >= 0), sizeof(*s->palette), - s->use_alpha ? cmp_pal_entry_alpha : cmp_pal_entry); + qsort(s->palette, AVPALETTE_COUNT-(s->transparency_index >= 0), sizeof(*s->palette), cmp_pal_entry); for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = s->palette[i]; @@ -784,22 +751,22 @@ static void load_colormap(PaletteUseContext *s) continue; } last_color = c; - if (!s->use_alpha && c >> 24 < s->trans_thresh) { + if (c >> 24 < s->trans_thresh) { color_used[i] = 1; // ignore transparent color(s) continue; } } - box.min[0] = box.min[1] = box.min[2] = box.min[3] = 0x00; - box.max[0] = box.max[1] = box.max[2] = box.max[3] = 0xff; + box.min[0] = box.min[1] = box.min[2] = 0x00; + box.max[0] = box.max[1] = box.max[2] = 0xff; - colormap_insert(s->map, color_used, &nb_used, s, &box); + colormap_insert(s->map, color_used, &nb_used, s->palette, s->trans_thresh, &box); if (s->dot_filename) disp_tree(s->map, s->dot_filename); if (s->debug_accuracy) { - if (!debug_accuracy(s)) + if (!debug_accuracy(s->map, s->palette, s->trans_thresh, s->color_search_method)) av_log(NULL, AV_LOG_INFO, "Accuracy check passed\n"); } } @@ -813,18 +780,16 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, uint8_t *src2 = in2->data[0]; const int src1_linesize = in1->linesize[0] >> 2; const int src2_linesize = in2->linesize[0]; - const float div = in1->width * in1->height * (s->use_alpha ? 4 : 3); + const float div = in1->width * in1->height * 3; unsigned mean_err = 0; for (y = 0; y < in1->height; y++) { for (x = 0; x < in1->width; x++) { const uint32_t c1 = src1[x]; const uint32_t c2 = palette[src2[x]]; - const uint8_t a1 = s->use_alpha ? c1>>24 & 0xff : 0xff; - const uint8_t a2 = s->use_alpha ? c2>>24 & 0xff : 0xff; - const uint8_t argb1[] = {a1, c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; - const uint8_t argb2[] = {a2, c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; - mean_err += diff(argb1, argb2, s); + const uint8_t argb1[] = {0xff, c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; + const uint8_t argb2[] = {0xff, c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; + mean_err += diff(argb1, argb2, s->trans_thresh); } src1 += src1_linesize; src2 += src2_linesize; @@ -1024,7 +989,7 @@ static void load_palette(PaletteUseContext *s, const AVFrame *palette_frame) for (y = 0; y < palette_frame->height; y++) { for (x = 0; x < palette_frame->width; x++) { s->palette[i] = p[x]; - if (!s->use_alpha && p[x]>>24 < s->trans_thresh) { + if (p[x]>>24 < s->trans_thresh) { s->transparency_index = i; // we are assuming at most one transparent color in palette } i++; From patchwork Sat Nov 5 15:26:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39166 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085107pzb; Sat, 5 Nov 2022 08:26:58 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6KRSRjy7QBbqsgN4yZNCPxnLdfdQvDWzHN9SHI2Ckx4NzksVi7wGB0sVxOY+ZEZWiDQSzp X-Received: by 2002:a17:906:794a:b0:7a0:72b8:2368 with SMTP id l10-20020a170906794a00b007a072b82368mr39454258ejo.601.1667662018740; Sat, 05 Nov 2022 08:26:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662018; cv=none; d=google.com; s=arc-20160816; b=ftl9kVYA+sgyiY+aaJGNvXN6iup9BLS19Peg1sGW5RCXReVcwmogr7n3pbn7VQBUc/ YK/A9gOW6TNxk9+Dnkhqkx9IdmQxMwfBgZ8mXEv4ed07akuxp7D7X7xBW4A7n4/BP6Ct iZyfj0QkF6GROmKb/H6BQNM54koLJ2ypRWSW8MJYfGhC1I24QybySocOXOk4Pizfn8/L mT9m39osmSklKXczRqa8/h0GLUuSF4C3kxGv2W3PNmFui1dSwKwz+nL3pt+a4+4H8CpS p1Qyd4NWW0Zqah/xLGyznyIHWqoK9RUsCND4+D3JHVy1meU16oqaKKQLfG0OYwYh3n9y Dtqg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=09YNz9U6+0Iwg1nt/eIE3LRQpgNkqWvF42gJLB3Bv9A=; b=znfdibE/WbvzddD0RdPZn1d+KnoP28kwWOXmS2VlZczyBkgx8hR+VSZIG4CYtzPoIo 0D3bXDYaY+SOqDxGyk1x1xPeQ5BgtAXv4ccRvsvm8RJhxKByKM7BDIdcg5hH7Mm/vOzV D3AJ1IOO3y6u1z0umFwwhxc9+5PZqOg6P+HTiDiXj9T+TfsPeO+hpjqA1h+qxvDHYqlm MeRVX+w3zOB2OukTHNSbb0xJwpiraz4NqL2BWGSY6U0ZFQbSPvc/8sOIpFAozFIeBa6J h85A1N8oEz5j7ZexDJKLI1a+l3JJv7DcPDJUrjVCy0O6ga6xnxDs/Vp777vn1ZlGmYiV dTdA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b="CF1TgX/4"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z22-20020a170906435600b0078d62ae01c1si2104507ejm.536.2022.11.05.08.26.58; Sat, 05 Nov 2022 08:26:58 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b="CF1TgX/4"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 786C568B218; Sat, 5 Nov 2022 17:26:34 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C5A7668B1F1 for ; Sat, 5 Nov 2022 17:26:27 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661980; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=z5b5eo1HsizM9HAF1iC4Tq/F0UcLxIKypZbYP34grbQ=; b=CF1TgX/4+IyHxgBlTLxl+uLKfWqUmD2J/9qr+sqibDPXvoTXjFkGtl38xdBvenRB0Va4H4 v/tXUG68oiEBN/QT8cBh9zqSlid88VH09BTM6OzA4Kc/4k2HvI5CNI84xTbJ0vqvcMYhNS ndDK/2Rjx6ykcRS442aRtuT5UyRZxvA= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id cfe2cb83; Sat, 5 Nov 2022 15:26:20 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:04 +0100 Message-Id: <20221105152617.1809282-3-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 02/15] avfilter: add palette utils X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: WdjzXqNn1qb7 These color management helpers will be shared by palettegen and paletteuse in the following commits. Note that it probably makes sense to share at least the sRGB/linear functions with other filters at some point. --- libavfilter/palette.c | 101 ++++++++++++++++++++++++++++++++++++++++++ libavfilter/palette.h | 54 ++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 libavfilter/palette.c create mode 100644 libavfilter/palette.h diff --git a/libavfilter/palette.c b/libavfilter/palette.c new file mode 100644 index 0000000000..80514c436b --- /dev/null +++ b/libavfilter/palette.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Björn Ottosson + * Copyright (c) 2022 Clément Bœsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include + +#include "libavutil/common.h" +#include "palette.h" + +/** + * Table mapping formula: + * f(x) = x < 0.04045 ? x/12.92 : ((x+.055)/(1+.055))^2.4 + * Where x is the normalized index in the table. + */ +static const float srgb2linear[256] = { + 0.000000, 0.000304, 0.000607, 0.000911, 0.001214, 0.001518, 0.001821, 0.002125, + 0.002428, 0.002732, 0.003035, 0.003347, 0.003677, 0.004025, 0.004391, 0.004777, + 0.005182, 0.005605, 0.006049, 0.006512, 0.006995, 0.007499, 0.008023, 0.008568, + 0.009134, 0.009721, 0.010330, 0.010960, 0.011612, 0.012286, 0.012983, 0.013702, + 0.014444, 0.015209, 0.015996, 0.016807, 0.017642, 0.018500, 0.019382, 0.020289, + 0.021219, 0.022174, 0.023153, 0.024158, 0.025187, 0.026241, 0.027321, 0.028426, + 0.029557, 0.030713, 0.031896, 0.033105, 0.034340, 0.035601, 0.036889, 0.038204, + 0.039546, 0.040915, 0.042311, 0.043735, 0.045186, 0.046665, 0.048172, 0.049707, + 0.051269, 0.052861, 0.054480, 0.056128, 0.057805, 0.059511, 0.061246, 0.063010, + 0.064803, 0.066626, 0.068478, 0.070360, 0.072272, 0.074214, 0.076185, 0.078187, + 0.080220, 0.082283, 0.084376, 0.086500, 0.088656, 0.090842, 0.093059, 0.095307, + 0.097587, 0.099899, 0.102242, 0.104616, 0.107023, 0.109462, 0.111932, 0.114435, + 0.116971, 0.119538, 0.122139, 0.124772, 0.127438, 0.130136, 0.132868, 0.135633, + 0.138432, 0.141263, 0.144128, 0.147027, 0.149960, 0.152926, 0.155926, 0.158961, + 0.162029, 0.165132, 0.168269, 0.171441, 0.174647, 0.177888, 0.181164, 0.184475, + 0.187821, 0.191202, 0.194618, 0.198069, 0.201556, 0.205079, 0.208637, 0.212231, + 0.215861, 0.219526, 0.223228, 0.226966, 0.230740, 0.234551, 0.238398, 0.242281, + 0.246201, 0.250158, 0.254152, 0.258183, 0.262251, 0.266356, 0.270498, 0.274677, + 0.278894, 0.283149, 0.287441, 0.291771, 0.296138, 0.300544, 0.304987, 0.309469, + 0.313989, 0.318547, 0.323143, 0.327778, 0.332452, 0.337164, 0.341914, 0.346704, + 0.351533, 0.356400, 0.361307, 0.366253, 0.371238, 0.376262, 0.381326, 0.386429, + 0.391572, 0.396755, 0.401978, 0.407240, 0.412543, 0.417885, 0.423268, 0.428690, + 0.434154, 0.439657, 0.445201, 0.450786, 0.456411, 0.462077, 0.467784, 0.473531, + 0.479320, 0.485150, 0.491021, 0.496933, 0.502886, 0.508881, 0.514918, 0.520996, + 0.527115, 0.533276, 0.539479, 0.545724, 0.552011, 0.558340, 0.564712, 0.571125, + 0.577580, 0.584078, 0.590619, 0.597202, 0.603827, 0.610496, 0.617207, 0.623960, + 0.630757, 0.637597, 0.644480, 0.651406, 0.658375, 0.665387, 0.672443, 0.679542, + 0.686685, 0.693872, 0.701102, 0.708376, 0.715694, 0.723055, 0.730461, 0.737910, + 0.745404, 0.752942, 0.760525, 0.768151, 0.775822, 0.783538, 0.791298, 0.799103, + 0.806952, 0.814847, 0.822786, 0.830770, 0.838799, 0.846873, 0.854993, 0.863157, + 0.871367, 0.879622, 0.887923, 0.896269, 0.904661, 0.913099, 0.921582, 0.930111, + 0.938686, 0.947307, 0.955973, 0.964686, 0.973445, 0.982251, 0.991102, 1.000000, +}; + +float ff_srgb_u8_to_linear_f32(uint8_t x) +{ + return srgb2linear[x]; +} + +uint8_t ff_linear_f32_to_srgb_u8(float x) +{ + const float v = x < 0.0031308f ? x * 12.92f : powf(1.055f * x, 1.f/2.4f) - 0.055f; + return av_clip_uint8(lrintf(v * 255.f)); +} + +struct Lab ff_srgb_u8_to_oklab(uint32_t srgb) +{ + const float r = srgb2linear[srgb >> 16 & 0xff]; + const float g = srgb2linear[srgb >> 8 & 0xff]; + const float b = srgb2linear[srgb & 0xff]; + + const float l = 0.4122214708f * r + 0.5363325363f * g + 0.0514459929f * b; + const float m = 0.2119034982f * r + 0.6806995451f * g + 0.1073969566f * b; + const float s = 0.0883024619f * r + 0.2817188376f * g + 0.6299787005f * b; + + const float l_ = cbrtf(l); + const float m_ = cbrtf(m); + const float s_ = cbrtf(s); + + const struct Lab ret = { + .L = 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_, + .a = 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_, + .b = 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_, + }; + + return ret; +} diff --git a/libavfilter/palette.h b/libavfilter/palette.h new file mode 100644 index 0000000000..2c1c609ba2 --- /dev/null +++ b/libavfilter/palette.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 Björn Ottosson + * Copyright (c) 2022 Clément Bœsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef AVFILTER_PALETTE_H +#define AVFILTER_PALETTE_H + +#include +#include + +#include "libavutil/attributes.h" + +struct Lab { + float L, a, b; +}; + +/** + * Map sRGB 8-bit color component to linear float value (gamma expand from + * electrical to optical value). + */ +float ff_srgb_u8_to_linear_f32(uint8_t x); + +/** + * Map a linear float value to a sRGB 8-bit color component (gamma compressed + * from optical to electrical value). + */ +uint8_t ff_linear_f32_to_srgb_u8(float x); + +/** + * sRGB (non-linear) to OkLab conversion + * @see https://bottosson.github.io/posts/oklab/ + */ +struct Lab ff_srgb_u8_to_oklab(uint32_t srgb); + +#endif /* AVFILTER_PALETTE_H */ From patchwork Sat Nov 5 15:26:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39167 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085169pzb; Sat, 5 Nov 2022 08:27:09 -0700 (PDT) X-Google-Smtp-Source: AA0mqf6b0vYt+/EKAiJBs+lz6Otn7xvEOWx1YdZ/qNC02r6l793yGwtjQ26hT+2bjDt7nWGuT6T0 X-Received: by 2002:a17:907:7faa:b0:7ad:e8e4:6ac7 with SMTP id qk42-20020a1709077faa00b007ade8e46ac7mr290087ejc.21.1667662029609; Sat, 05 Nov 2022 08:27:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662029; cv=none; d=google.com; s=arc-20160816; b=z4l+/+gCLF8nXuHEpyLYCDiChlSlhWLYQS5rtgw27mSrVMJhm0f+vCQscQLzkg2Im/ AyIwd/WVuC6GbC+uCRgKr/IxkKQuEbi8VKvFD1IdkA1qcqZjP+TpbUiMn8EOb2MXJ0bI d15pplqyVhOdnIl+TCzYtl3upiWYD6IO6+JLmLeHmO57Vxy3RZRAqH98yrnQV9qT1D/q sRLGNm6ExjPCaeV+/1NC8hXyNemT8qLfGOT4lYWIIRa39bV48O+rEZb9L/fJMFRW98Dr BiZOiGbt0h3LvGYCZxdm/302rfrl66Mrdesqu8pDWQTypg3Smil74Aii37/71Y7us8s6 3Bgw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=F7I5ONgNm4pIBug/0ubSf4W6y8gnOS9ywDspPsODoyk=; b=Y1cqU+Ob78FDL20DY7up9H4rNIROV3BWWQWzo3q4JKMMea8Wi7purYeWzKiUZPxV3/ KkLINuuHzn29vTqAplkdtCD10xQNBhhBpsCHzYik8QqK3MacVe7dR5Atj6gRAh1Yiz+B 6wrzoJbsecmCWgQFYY+48G0HvqpN74ojOKA/wAA4xy2uXxGnxrPGfBtXvFH5NNpm6KOK Ag6X6j4XCuI+UUM/JfkuQ52DXNrhg9vt+ZNWi6gqGyPRMrcC+CmSYaRMIIW93uqE94xI sMcnExy7/D2QlAlIImAM/J73Lm8ed31bmoMyJFNBVI/WHUpRzUOHZMHc4wgeUt1oRJOM OccQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=BJi8Lk3i; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hz5-20020a1709072ce500b007878c9d73a2si2542979ejc.426.2022.11.05.08.27.09; Sat, 05 Nov 2022 08:27:09 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=BJi8Lk3i; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 90B0168B1F1; Sat, 5 Nov 2022 17:26:37 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E8B3368B1F1 for ; Sat, 5 Nov 2022 17:26:30 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661980; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=h9pdBe3KUbkAZXh5/Hn4OcGopvr2f2OLyDeT3XJvQE4=; b=BJi8Lk3ivhilGoW9thsxFQU5k029gZlHfuhdAh6ZRtXPYwc6DGwqDqmlCyDNIi/1N9zQdG 30Z1WMXpD/xH6aW0uOphxleoUIrt85mpMqTe2xcENXBOEzDkOYOOIluDfPzGWTq5yxnRSi ZxuNNkkdx6ZUAfZEvcbcnhCbbNpjKiQ= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id ec590acb; Sat, 5 Nov 2022 15:26:20 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:05 +0100 Message-Id: <20221105152617.1809282-4-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 03/15] avfilter/palette{use, gen}: simplify a few alpha masks X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 6ivnAazgyGUv --- libavfilter/vf_paletteuse.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index cb18329bb7..f9d8a1cdfc 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -156,7 +156,7 @@ static int query_formats(AVFilterContext *ctx) static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift) { - return px >> 24 << 24 + return (px & 0xff000000) | av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<> 8 & 0xff) + ((eg * scale) / (1<> 24 >= trans_thresh) { // ignore transparent entry const uint8_t palargb[] = { - palette[i]>>24 & 0xff, + palette[i]>>24, palette[i]>>16 & 0xff, palette[i]>> 8 & 0xff, palette[i] & 0xff, @@ -372,7 +372,7 @@ static av_always_inline int get_dst_color_err(PaletteUseContext *s, uint32_t c, int *er, int *eg, int *eb, const enum color_search_method search_method) { - const uint8_t a = c >> 24 & 0xff; + const uint8_t a = c >> 24; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; @@ -411,7 +411,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram if (dither == DITHERING_BAYER) { const int d = s->ordered_dither[(y & 7)<<3 | (x & 7)]; - const uint8_t a8 = src[x] >> 24 & 0xff; + const uint8_t a8 = src[x] >> 24; const uint8_t r8 = src[x] >> 16 & 0xff; const uint8_t g8 = src[x] >> 8 & 0xff; const uint8_t b8 = src[x] & 0xff; @@ -483,7 +483,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 1, 2); } else { - const uint8_t a = src[x] >> 24 & 0xff; + const uint8_t a = src[x] >> 24; const uint8_t r = src[x] >> 16 & 0xff; const uint8_t g = src[x] >> 8 & 0xff; const uint8_t b = src[x] & 0xff; @@ -630,7 +630,7 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = palette[i]; - const uint8_t a = c >> 24 & 0xff; + const uint8_t a = c >> 24; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; @@ -700,7 +700,7 @@ static int colormap_insert(struct color_node *map, node = &map[cur_id]; node->split = component; node->palette_id = pal_id; - node->val[0] = c>>24 & 0xff; + node->val[0] = c>>24; node->val[1] = c>>16 & 0xff; node->val[2] = c>> 8 & 0xff; node->val[3] = c & 0xff; From patchwork Sat Nov 5 15:26:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39168 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085256pzb; Sat, 5 Nov 2022 08:27:20 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5NKiPoJ2XdhpOzz6paO+xhKXZKzmjCXexrIR1Img3AZ0z79o6PwrtZwg4At3ltOBKAy4je X-Received: by 2002:a05:6402:b2f:b0:461:701e:877a with SMTP id bo15-20020a0564020b2f00b00461701e877amr39841056edb.82.1667662039848; Sat, 05 Nov 2022 08:27:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662039; cv=none; d=google.com; s=arc-20160816; b=dGUoCVn101wbW87u3SchE6cx1Ast5ONXQnFYOgRrhYa6KVyeAcEwitvY4JCku4CMJS 92Tij0svXR3Axhx0vTj8ASCKuW8LiKJOje+rusGF6HtEHG2501aX7dVc9zqOjoK3dCOq blmz88ujR1tSG4Ow/b5QTnGTgcNfWjQjB7/S0EoYHdK0j/ENpmBl8WGg5f+8y7W8KYcP SV3rYX54eZMeon4TG+dfxBzU5bHtfsREJGyOmXS8tRH+XvA/kxPm6z4h5+IxJvW5YMeb wfw7qongKS2Mvus8ZMUV8+jxqt52Y5TbfY7ZH5Tw2lpKYFJUzMQzY6tonSCsULIP9vyY ROuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=qaJIwsELJN3uFQBq1bLacawMNqKCA5elC7LVVp1PIis=; b=NeQ33od51fGZVzQRZp1slcdkfspJrrkzI8OY9H0dKhnhfmmNPtSLD/cRHwwwCvFHCO JRTpi1ZGcDS4JR0stuQfSg24rEjT9MRjUMwiXbK553ozEMhk6zvtR5olhKVkSMzWS6Ys sl1O6LyhbyKPUV/vB2w+j5YJlxu31rc1R4pj4j/l42QrdLXQMq5lpwRvc3NvbU998HT7 1wkep0SO1jcLHcDJ1iw3/lYdzwOspFo5+fbiJT7sRtx/3qQcn4Q8ia4YbFCvxugtXJd3 IBiOqcWXiJnmcvVocPrqCXK2YkyROkx9jBlXN0NjEI7Q6PU0FGslpbp6Ih6DumB/e9Y+ PoBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=onAMQUFr; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id sc6-20020a1709078a0600b0073dced7204bsi2981156ejc.767.2022.11.05.08.27.19; Sat, 05 Nov 2022 08:27:19 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=onAMQUFr; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A79C068B326; Sat, 5 Nov 2022 17:26:38 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2B79068B1F1 for ; Sat, 5 Nov 2022 17:26:31 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661980; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Tm5vCta3NcHSHcNxV0cwRNqlv3LSwUSm1oOOnmnPVtI=; b=onAMQUFrObErUMFFkQmsiYfF1A2JsQEg0uzDjAn/8cvOWZeUIZrIt/YMJ5pZMFWC685Gcv QgV903MHynzZrrNjdBmZlJeAvJ8J3MXZVMfEW41e3PrBTJ6Hu+hpwuBD2uhJFLjRXaRkPk PICMgz/FQPhFt/MqheKejsydbDe819M= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id b720b676; Sat, 5 Nov 2022 15:26:20 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:06 +0100 Message-Id: <20221105152617.1809282-5-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 04/15] avfilter/paletteuse: switch from u8[4] to u32 for color code X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: MKGxlLJS1rTU This change simplifies the code quite a bit and make it consistent with how it's done in palettegen. --- libavfilter/vf_paletteuse.c | 98 ++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index f9d8a1cdfc..fb4016b11c 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -57,7 +57,7 @@ enum diff_mode { }; struct color_node { - uint8_t val[4]; + uint32_t val; uint8_t palette_id; int split; int left_id, right_id; @@ -162,9 +162,11 @@ static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, | av_clip_uint8((px & 0xff) + ((eb * scale) / (1<> 24, a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff}; + const uint8_t c2[] = {b >> 24, b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff}; const int dr = c1[1] - c2[1]; const int dg = c1[2] - c2[2]; const int db = c1[3] - c2[3]; @@ -178,7 +180,7 @@ static av_always_inline int diff(const uint8_t *c1, const uint8_t *c2, const int } } -static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint8_t *argb, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint32_t argb, const int trans_thresh) { int i, pal_id = -1, min_dist = INT_MAX; @@ -186,13 +188,7 @@ static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *pale const uint32_t c = palette[i]; if (c >> 24 >= trans_thresh) { // ignore transparent entry - const uint8_t palargb[] = { - palette[i]>>24, - palette[i]>>16 & 0xff, - palette[i]>> 8 & 0xff, - palette[i] & 0xff, - }; - const int d = diff(palargb, argb, trans_thresh); + const int d = diff(palette[i], argb, trans_thresh); if (d < min_dist) { pal_id = i; min_dist = d; @@ -210,14 +206,14 @@ struct nearest_color { static void colormap_nearest_node(const struct color_node *map, const int node_pos, - const uint8_t *target, + const uint32_t target, const int trans_thresh, struct nearest_color *nearest) { const struct color_node *kd = map + node_pos; - const int s = kd->split; + const int shift = (3 - kd->split) * 8; int dx, nearer_kd_id, further_kd_id; - const uint8_t *current = kd->val; + const uint32_t current = kd->val; const int current_to_target = diff(target, current, trans_thresh); if (current_to_target < nearest->dist_sqd) { @@ -226,7 +222,7 @@ static void colormap_nearest_node(const struct color_node *map, } if (kd->left_id != -1 || kd->right_id != -1) { - dx = target[s] - current[s]; + dx = (int)(target>>shift & 0xff) - (int)(current>>shift & 0xff); if (dx <= 0) nearer_kd_id = kd->left_id, further_kd_id = kd->right_id; else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id; @@ -239,7 +235,7 @@ static void colormap_nearest_node(const struct color_node *map, } } -static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t *rgb, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t rgb, const int trans_thresh) { struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1}; colormap_nearest_node(node, 0, rgb, trans_thresh, &res); @@ -251,7 +247,7 @@ struct stack_node { int dx2; }; -static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint8_t *target, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint32_t target, const int trans_thresh) { int pos = 0, best_node_id = -1, best_dist = INT_MAX, cur_color_id = 0; struct stack_node nodes[16]; @@ -260,7 +256,7 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no for (;;) { const struct color_node *kd = &root[cur_color_id]; - const uint8_t *current = kd->val; + const uint32_t current = kd->val; const int current_to_target = diff(target, current, trans_thresh); /* Compare current color node to the target and update our best node if @@ -274,8 +270,8 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no /* Check if it's not a leaf */ if (kd->left_id != -1 || kd->right_id != -1) { - const int split = kd->split; - const int dx = target[split] - current[split]; + const int shift = (3 - kd->split) * 8; + const int dx = (target>>shift & 0xff) - (current>>shift & 0xff); int nearer_kd_id, further_kd_id; /* Define which side is the most interesting. */ @@ -331,24 +327,20 @@ end: /** * Check if the requested color is in the cache already. If not, find it in the * color tree and cache it. - * Note: a, r, g, and b are the components of color, but are passed as well to avoid - * recomputing them (they are generally computed by the caller for other uses). */ static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, - uint8_t a, uint8_t r, uint8_t g, uint8_t b, const enum color_search_method search_method) { int i; - const uint8_t argb_elts[] = {a, r, g, b}; - const uint8_t rhash = r & ((1<>16) & ((1<> 8) & ((1<cache[hash]; struct cached_color *e; // first, check for transparency - if (a < s->trans_thresh && s->transparency_index >= 0) { + if (color>>24 < s->trans_thresh && s->transparency_index >= 0) { return s->transparency_index; } @@ -363,7 +355,7 @@ static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, if (!e) return AVERROR(ENOMEM); e->color = color; - e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, argb_elts, s->trans_thresh); + e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, color, s->trans_thresh); return e->pal_entry; } @@ -372,12 +364,11 @@ static av_always_inline int get_dst_color_err(PaletteUseContext *s, uint32_t c, int *er, int *eg, int *eb, const enum color_search_method search_method) { - const uint8_t a = c >> 24; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; uint32_t dstc; - const int dstx = color_get(s, c, a, r, g, b, search_method); + const int dstx = color_get(s, c, search_method); if (dstx < 0) return dstx; dstc = s->palette[dstx]; @@ -419,7 +410,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram const uint8_t g = av_clip_uint8(g8 + d); const uint8_t b = av_clip_uint8(b8 + d); const uint32_t color_new = (unsigned)(a8) << 24 | r << 16 | g << 8 | b; - const int color = color_get(s, color_new, a8, r, g, b, search_method); + const int color = color_get(s, color_new, search_method); if (color < 0) return color; @@ -483,11 +474,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 1, 2); } else { - const uint8_t a = src[x] >> 24; - const uint8_t r = src[x] >> 16 & 0xff; - const uint8_t g = src[x] >> 8 & 0xff; - const uint8_t b = src[x] & 0xff; - const int color = color_get(s, src[x], a, r, g, b, search_method); + const int color = color_get(s, src[x], search_method); if (color < 0) return color; @@ -507,20 +494,20 @@ static void disp_node(AVBPrint *buf, int depth) { const struct color_node *node = &map[node_id]; - const uint32_t fontcolor = node->val[1] > 0x50 && - node->val[2] > 0x50 && - node->val[3] > 0x50 ? 0 : 0xffffff; + const uint32_t fontcolor = (node->val>>16 & 0xff) > 0x50 && + (node->val>> 8 & 0xff) > 0x50 && + (node->val & 0xff) > 0x50 ? 0 : 0xffffff; const int rgb_comp = node->split - 1; av_bprintf(buf, "%*cnode%d [" "label=\"%c%02X%c%02X%c%02X%c\" " - "fillcolor=\"#%02x%02x%02x\" " + "fillcolor=\"#%06"PRIX32"\" " "fontcolor=\"#%06"PRIX32"\"]\n", depth*INDENT, ' ', node->palette_id, - "[ "[rgb_comp], node->val[1], - "][ "[rgb_comp], node->val[2], - " ]["[rgb_comp], node->val[3], + "[ "[rgb_comp], node->val>>16 & 0xff, + "][ "[rgb_comp], node->val>> 8 & 0xff, + " ]["[rgb_comp], node->val & 0xff, " ]"[rgb_comp], - node->val[1], node->val[2], node->val[3], + node->val & 0xffffff, fontcolor); if (parent_id != -1) av_bprintf(buf, "%*cnode%d -> node%d\n", depth*INDENT, ' ', @@ -563,16 +550,14 @@ static int debug_accuracy(const struct color_node *node, const uint32_t *palette for (r = 0; r < 256; r++) { for (g = 0; g < 256; g++) { for (b = 0; b < 256; b++) { - const uint8_t argb[] = {0xff, r, g, b}; + const uint32_t argb = 0xff000000 | r<<16 | g<<8 | b; const int r1 = COLORMAP_NEAREST(search_method, palette, node, argb, trans_thresh); const int r2 = colormap_nearest_bruteforce(palette, argb, trans_thresh); if (r1 != r2) { const uint32_t c1 = palette[r1]; const uint32_t c2 = palette[r2]; - const uint8_t palargb1[] = { 0xff, c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; - const uint8_t palargb2[] = { 0xff, c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; - const int d1 = diff(palargb1, argb, trans_thresh); - const int d2 = diff(palargb2, argb, trans_thresh); + const int d1 = diff(0xff000000 | c1, argb, trans_thresh); + const int d2 = diff(0xff000000 | c2, argb, trans_thresh); if (d1 != d2) { av_log(NULL, AV_LOG_ERROR, "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", @@ -686,6 +671,7 @@ static int colormap_insert(struct color_node *map, { uint32_t c; int component, cur_id; + uint8_t comp_value; int node_left_id = -1, node_right_id = -1; struct color_node *node; struct color_rect box1, box2; @@ -700,17 +686,15 @@ static int colormap_insert(struct color_node *map, node = &map[cur_id]; node->split = component; node->palette_id = pal_id; - node->val[0] = c>>24; - node->val[1] = c>>16 & 0xff; - node->val[2] = c>> 8 & 0xff; - node->val[3] = c & 0xff; + node->val = c; color_used[pal_id] = 1; /* get the two boxes this node creates */ box1 = box2 = *box; - box1.max[component-1] = node->val[component]; - box2.min[component-1] = FFMIN(node->val[component] + 1, 255); + comp_value = node->val >> ((3 - component) * 8) & 0xff; + box1.max[component-1] = comp_value; + box2.min[component-1] = FFMIN(comp_value + 1, 255); node_left_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box1); @@ -787,8 +771,8 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, for (x = 0; x < in1->width; x++) { const uint32_t c1 = src1[x]; const uint32_t c2 = palette[src2[x]]; - const uint8_t argb1[] = {0xff, c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; - const uint8_t argb2[] = {0xff, c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; + const uint32_t argb1 = 0xff000000 | c1; + const uint32_t argb2 = 0xff000000 | c2; mean_err += diff(argb1, argb2, s->trans_thresh); } src1 += src1_linesize; From patchwork Sat Nov 5 15:26:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39169 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085341pzb; Sat, 5 Nov 2022 08:27:30 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6EQ1QZkB1DBbEDuq07A3tV669/Rrese/UhsM79u0U87PLEruKysSjV71AqmfTI6f6tKyTR X-Received: by 2002:a17:907:75f4:b0:7ad:b868:ccf2 with SMTP id jz20-20020a17090775f400b007adb868ccf2mr36528655ejc.733.1667662049929; Sat, 05 Nov 2022 08:27:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662049; cv=none; d=google.com; s=arc-20160816; b=pXkyRELs9PMDPotsF7HelIUBSoabeUNI0XaEHPE9VqfURKWUnjZPj5NOa0sBaU2cxw AI6waLxJfCJ9mDpmPl7yqLexMQoDPlDIX2vIFGcBd0dq5i40pK2GQpXp6UiKORI/i7od gU+R8KCgL3hrHv6B/DEit7sm9fHj9rzcjzFhwh09Tl2N/1q1ZNSATHs2HLu/hHfjymJS sVvbsTF8PeefF15teY89QIImpIJynbpUQ+0j2XHQ6qD8Vb5ZwDqxd+QAIMTpDzqIJD4Y rbHXDlWbPZBnr0Q/s+DsZ0W5pmHwmWUIjo1lWMOr7vXOIcGesW9BzbolFMk0xUkCEtiE fuag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=aZVA+4t5TDnBe1HHndM6n1tVKhPzQv5uYl7LYxznJ0I=; b=eJlKYzStv/gtxhL/7M/6y/7d4Hko5N2YegrW+i0ewlCItU5I1KoGU85/0snOIKkk11 Iq+02/talF4bF4j/6SE5EhZA91Lcza741GtNGJ8zl5O+N4Mj3pb53Kwme2cLUsrIY7e8 /kXoiIMYN5X3hIlZLXsiPgeUfXkD7tcLck8rNvlpKGxcBpSILpGWbiY+vr97keF8WiUr v3r0dn5FLAab+kpFpFRqq99sZr5TMOtdLtQA3pNBFnA7eMDuAEFatILeNXy293lbs5te Sq2P7wd1qIabsXHss3vpBFoqiFO3tmVjmrnoYHKfpbl5caiOEYvdOuRi/QW3BC5pclfX eKnQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=fwNmatzg; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v14-20020a056402348e00b00456e33b69e1si3840396edc.347.2022.11.05.08.27.29; Sat, 05 Nov 2022 08:27:29 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=fwNmatzg; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 98B8068B3A7; Sat, 5 Nov 2022 17:26:39 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 045F268B25D for ; Sat, 5 Nov 2022 17:26:32 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8QK0gQRPZTlpe6b5Isfr+UBzXB0eT15rQyfJ+1Oisiw=; b=fwNmatzgIVliRyp6tTnj3nOvCIqQe8rr4wPH2yBUdKbSW1Rrbnics+X2bk1hnngqLXysdx DmOWT88knwsNwu96T2QBvzWBw0YTzPITLcRK1V6NbMtIuKPQG2yVDAzqhBT6JPdspqPDiM 3CiBewPPf3lEXqsyECQ5rvRTK8vdGBY= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id c959b920; Sat, 5 Nov 2022 15:26:20 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:07 +0100 Message-Id: <20221105152617.1809282-6-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 05/15] avfilter/paletteuse: name target color arg consistently in colormap functions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: sDKA3Skelqab --- libavfilter/vf_paletteuse.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index fb4016b11c..f43f077454 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -180,7 +180,7 @@ static av_always_inline int diff(const uint32_t a, const uint32_t b, const int t } } -static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint32_t argb, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint32_t target, const int trans_thresh) { int i, pal_id = -1, min_dist = INT_MAX; @@ -188,7 +188,7 @@ static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *pale const uint32_t c = palette[i]; if (c >> 24 >= trans_thresh) { // ignore transparent entry - const int d = diff(palette[i], argb, trans_thresh); + const int d = diff(palette[i], target, trans_thresh); if (d < min_dist) { pal_id = i; min_dist = d; @@ -235,10 +235,10 @@ static void colormap_nearest_node(const struct color_node *map, } } -static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t rgb, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t target, const int trans_thresh) { struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1}; - colormap_nearest_node(node, 0, rgb, trans_thresh, &res); + colormap_nearest_node(node, 0, target, trans_thresh, &res); return node[res.node_pos].palette_id; } From patchwork Sat Nov 5 15:26:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39170 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085421pzb; Sat, 5 Nov 2022 08:27:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7QdFLSjZdsHcB7nHGPYja7J9TwsQrincyjyhRgYN5Nfn0lGbMzGGUNDqE7/NWGBors2Gch X-Received: by 2002:a17:907:c0e:b0:7ae:1134:37c5 with SMTP id ga14-20020a1709070c0e00b007ae113437c5mr15319472ejc.648.1667662058417; Sat, 05 Nov 2022 08:27:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662058; cv=none; d=google.com; s=arc-20160816; b=Af5ThCuNQPj2lUFIkctxHE3FLN8e1x8PB+B4ZXM7U51FykveWdXCi2b8v2UnjZmMo2 4xC/6QZ75k9HJIekNk3KuZXX1x/dqCqF1+eZsn/ypkhoInz6+9nbpbMuXTJld+IA5oxT JuQKAI7/mVSWAu/ARjhRPUK1QRWUzlNbMAu+clBR0IKaNjYWWg4gX1iIkesl4D47DgNM 9Rb4oYCd2PM5zrBt4UUrKV6Gt4dBF216de5LvBtYvAj9x0y5msIVkjOpTC9Pd3hdv5fs TdvdI/Tto8+HTJ/dngNXB5anoNjg5Hzm2qf1BZ5b/qgIM0tGQa/3CblrwItVJyjyZIJq KY9Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=iaUkVoeFlYLUbRuHPZmJWY3abbzBx0f1DJ7t6YhUL8A=; b=iJdYuMpDhH14oh8RFHa3im3887dmyUYdqJsggBmL2OTdLOZTvyAft/ZoO51b6WnmQm YrW26sqfJgNcdFFejMNqSPTu0UMbxqVVfChsazmqeGQp41djLMOW4/TSXs0iwSM5Ipa3 jVAEIlkaHyZswE7RBQx2GWYtlw5uAiOWoN4gU67EmwylRXg9lqJkuBXtfOm6gRE3vFCB DhfzHzrkNTXUitGoPCN7sFU/P+OZ8b1kimfTA42jr9ECecEL7AX12NPI45bIZ5OJlnGA mRm2feF1eoioxWVxZjQnkcefkgLzxWMBI1BxdYV7Tq0TKqlARbY7zaXNWU1tT2hq5ZHL Me9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=RBsuO6y0; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hb13-20020a170907160d00b007707f83375bsi2798261ejc.945.2022.11.05.08.27.38; Sat, 05 Nov 2022 08:27:38 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=RBsuO6y0; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BD86868B59B; Sat, 5 Nov 2022 17:26:42 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DBEFE68B32D for ; Sat, 5 Nov 2022 17:26:35 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D4PDdhEnXAEyPvTekJZOpB54XHjADLiSKJctDu5YJys=; b=RBsuO6y08qO9FKjwRVoOaIBgfyIym4227q4RXHOhn6XMTFNq/bSqANqBNJTxwFOfKjdkPz yWWbFn2F9607cnMiDuPo2FMRXsQRw7yldVyGTxT5WnSaMwAzCN7E8AsVh6rCTyMAoVGH0p /xT5jtQ9EKeF0Sb3sIZjF7QKoiZP6jE= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id bcb4c9a5; Sat, 5 Nov 2022 15:26:21 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:08 +0100 Message-Id: <20221105152617.1809282-7-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 06/15] avfilter/paletteuse: remove unused alpha split dimension X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: jeg3f6DIxUx8 The equalities in the w{r,g,b} range checks make sure longest is never 0. Even if the alpha ended up being selected in get_next_color() it would cause underread memory accesses in its caller (colormap_insert). --- libavfilter/vf_paletteuse.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index f43f077454..8954a02524 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -211,7 +211,7 @@ static void colormap_nearest_node(const struct color_node *map, struct nearest_color *nearest) { const struct color_node *kd = map + node_pos; - const int shift = (3 - kd->split) * 8; + const int shift = (2 - kd->split) * 8; int dx, nearer_kd_id, further_kd_id; const uint32_t current = kd->val; const int current_to_target = diff(target, current, trans_thresh); @@ -270,7 +270,7 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no /* Check if it's not a leaf */ if (kd->left_id != -1 || kd->right_id != -1) { - const int shift = (3 - kd->split) * 8; + const int shift = (2 - kd->split) * 8; const int dx = (target>>shift & 0xff) - (current>>shift & 0xff); int nearer_kd_id, further_kd_id; @@ -497,7 +497,7 @@ static void disp_node(AVBPrint *buf, const uint32_t fontcolor = (node->val>>16 & 0xff) > 0x50 && (node->val>> 8 & 0xff) > 0x50 && (node->val & 0xff) > 0x50 ? 0 : 0xffffff; - const int rgb_comp = node->split - 1; + const int rgb_comp = node->split; av_bprintf(buf, "%*cnode%d [" "label=\"%c%02X%c%02X%c%02X%c\" " "fillcolor=\"#%06"PRIX32"\" " @@ -588,16 +588,15 @@ static int cmp_##name(const void *pa, const void *pb) \ { \ const struct color *a = pa; \ const struct color *b = pb; \ - return (int)(a->value >> (8 * (3 - (pos))) & 0xff) \ - - (int)(b->value >> (8 * (3 - (pos))) & 0xff); \ + return (int)(a->value >> (8 * (2 - (pos))) & 0xff) \ + - (int)(b->value >> (8 * (2 - (pos))) & 0xff); \ } -DECLARE_CMP_FUNC(a, 0) -DECLARE_CMP_FUNC(r, 1) -DECLARE_CMP_FUNC(g, 2) -DECLARE_CMP_FUNC(b, 3) +DECLARE_CMP_FUNC(r, 0) +DECLARE_CMP_FUNC(g, 1) +DECLARE_CMP_FUNC(b, 2) -static const cmp_func cmp_funcs[] = {cmp_a, cmp_r, cmp_g, cmp_b}; +static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; static int get_next_color(const uint8_t *color_used, const uint32_t *palette, const int trans_thresh, @@ -650,9 +649,9 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, wr = ranges.max[0] - ranges.min[0]; wg = ranges.max[1] - ranges.min[1]; wb = ranges.max[2] - ranges.min[2]; - if (wr >= wg && wr >= wb) longest = 1; - if (wg >= wr && wg >= wb) longest = 2; - if (wb >= wr && wb >= wg) longest = 3; + if (wr >= wg && wr >= wb) longest = 0; + if (wg >= wr && wg >= wb) longest = 1; + if (wb >= wr && wb >= wg) longest = 2; cmpf = cmp_funcs[longest]; *component = longest; @@ -692,13 +691,13 @@ static int colormap_insert(struct color_node *map, /* get the two boxes this node creates */ box1 = box2 = *box; - comp_value = node->val >> ((3 - component) * 8) & 0xff; - box1.max[component-1] = comp_value; - box2.min[component-1] = FFMIN(comp_value + 1, 255); + comp_value = node->val >> ((2 - component) * 8) & 0xff; + box1.max[component] = comp_value; + box2.min[component] = FFMIN(comp_value + 1, 255); node_left_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box1); - if (box2.min[component-1] <= box2.max[component-1]) + if (box2.min[component] <= box2.max[component]) node_right_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box2); node->left_id = node_left_id; From patchwork Sat Nov 5 15:26:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39172 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085592pzb; Sat, 5 Nov 2022 08:27:56 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5BgILNtNZ3sjv/dE5RWAlXC2bCYrTSsSXGbXIuhxYBLF6R81NR5t7NnlGMlPN5WxpHMlvp X-Received: by 2002:a05:6402:3709:b0:459:279e:fdc6 with SMTP id ek9-20020a056402370900b00459279efdc6mr41555374edb.338.1667662075954; Sat, 05 Nov 2022 08:27:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662075; cv=none; d=google.com; s=arc-20160816; b=SLIbcCXLKp+yDhCaf7j3vBHiuKwaGR0w/AueiDnCQfNTrTzZ/5daXYY81Oa7ruGxlJ vbJYTFlaou1p3G9jvLCYg9Ac34gGN6fBFyPY5ZyxLx6dhJ8XMRZMGflV0PcWYzSoObQ7 118VO0b/vvdGdwnlwDLFqug1zUzIom4oQSCZRhu514U2z8QHHGgOB+YBd+qcoUzSUspZ b3eUg+PHUTbmvGJJq7fEuovdcXsglysbijvEQIJ4DH9TfoLPFCU7bOCjmHs+anlqX8g8 vhvAHqDYwOG7j0VZD1VKAGS8NyV0ZprBLQe/dvXufEAZI9A0A+ZP/mFZ75cN5KUmaWZx SdNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=wWNTufZFPwywqizFT9ouuGbxeq16KEPqwK1Tl863erc=; b=A28HnMb2oImHXv3wmbM75ZvXca/Si3Jc2jwY8GJqJmR2ySn55ZMk2ixmvNNe7kHfnN g3Ngca72RiSFxoCk92HEWMHC3Q5X0Ke09y5/Cn5WGeb60Gy8mkfk4Hu5oEp7Liaze9UM 64rRHASQ2vtaQRKFzUQjJy3hp2/O7/yORj3Komu2o+yWEg8Cvt+S7+WWKIrBjx+1X3PD J+5d5lZo4Veauul7icwhSbFS8sFqu9SwpazEdUGJd8gbCFXs7cmUUyrrk9Dk00jilwNV MssztC9M0EQbio4fUK8KBhPG51jD1nTmToqoHfy/80GMk+0NIeopa7ZmAtxYTK47pBZK hUuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=azlZHgGF; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id os18-20020a170906af7200b0076fa1e1274bsi1917894ejb.202.2022.11.05.08.27.55; Sat, 05 Nov 2022 08:27:55 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=azlZHgGF; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9D28268B32D; Sat, 5 Nov 2022 17:26:44 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1E42268B32D for ; Sat, 5 Nov 2022 17:26:36 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c7OwYE6lMuhoHTl5ROrJBOC2gRDuIjrJ0RQb7FOcTgQ=; b=azlZHgGFD5kaTIa7QRvB0Q2WX55xqUB1u6EfFjwq45uVJDYxWoF7NLzTbL2f5nfYHRg0+Z S0nMRzi8QnP9gYOvIXoJ4qeNpEDw0tLfZkaM9zungY246MeQaAHahpf3poMe3uh/27TfTA SDl0Kw8PTx08vQU0/Co9vpIPQZS/qtI= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id 3b46bb7a; Sat, 5 Nov 2022 15:26:21 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:09 +0100 Message-Id: <20221105152617.1809282-8-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 07/15] avfilter/paletteuse: remove redundant alpha condition X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: h3iWTrEPv8uY This is redundant with a != 0xff below. --- libavfilter/vf_paletteuse.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 8954a02524..0861a70a0b 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -599,7 +599,6 @@ DECLARE_CMP_FUNC(b, 2) static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; static int get_next_color(const uint8_t *color_used, const uint32_t *palette, - const int trans_thresh, int *component, const struct color_rect *box) { int wr, wg, wb; @@ -619,10 +618,6 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; - if (a < trans_thresh) { - continue; - } - if (color_used[i] || (a != 0xff) || r < box->min[0] || g < box->min[1] || b < box->min[2] || r > box->max[0] || g > box->max[1] || b > box->max[2]) @@ -674,7 +669,7 @@ static int colormap_insert(struct color_node *map, int node_left_id = -1, node_right_id = -1; struct color_node *node; struct color_rect box1, box2; - const int pal_id = get_next_color(color_used, palette, trans_thresh, &component, box); + const int pal_id = get_next_color(color_used, palette, &component, box); if (pal_id < 0) return -1; From patchwork Sat Nov 5 15:26:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39175 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085901pzb; Sat, 5 Nov 2022 08:28:24 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5ny1zA9ddbaOxygY7d+/W18GH8blpCbEsmg0P1E4R2oKReRApQnNlWSSHwoxKtKNPXwm/w X-Received: by 2002:a17:906:8475:b0:7ad:c04:d3cf with SMTP id hx21-20020a170906847500b007ad0c04d3cfmr38208957ejc.463.1667662104402; Sat, 05 Nov 2022 08:28:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662104; cv=none; d=google.com; s=arc-20160816; b=rZ+GT0fZNHWPij9G3YwRfMpSx5xwtETgY8SWqstyr/xxSlG4rYJTXgrQVtpv1xG1vw dPjotEJ8JMJ+vwcSgAAS9rVjqB7OKbdek3PQ+bupoLLMnuhZo7xdsE6zLpt6c4Lnqu6R 3np8JmkRmctGToCBF8C9sVVa2MtwBbsvZHbBEbmZv2z6XR19JHHm3UE0ER8mLEcf2t6T ChjmsoV/vfSIzcskZLohjWUd+SEi1decQuvQXEjFNpcS5akAeH1I/wytOcs5RAA4P/aD iWvtrVzK59E/aW7mof6OXZFU+Mc3npiaFgNMm2S9TuoHJBYxf2BfhevlklXhz3XX1pSy I1Dw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=rLP5mbGnDioPrlN1q4bZc3+Wk7uIiDSIScMnBSlz1Wg=; b=izW3QTbMWevbwFItY8070SdNz8VvOMPjZwIPvn0opGHd7lLoWuT4a44wzKxhrPUgJw kUsxizPsWc9o5696HxTEW7HN6tWr8Jh2UCioyn0NfChiLkdBg7ZAiUOTUEJVGbW8yzny X6sBD20YVWdyVhjclnK/AjxPjubZwjCIRFujTSO5cXNg9VhVXMiVpSdFc3WHLc9aS+iS aXVaQPFs2zf79QlA9LQjra8j96IubQaW1SBqZt9eNay6+XyRQLayuQ1Ub001broD5Hc4 RiassR10tSmRfX+t0gHv4qb+rkiE6u4VNF6ZBXRTt4Su1+/m5PsH9M81AFg7gsSHY4WB RmmA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b="qSA/qe8c"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id go19-20020a1709070d9300b0078d4b9e68cbsi2494488ejc.1002.2022.11.05.08.28.23; Sat, 05 Nov 2022 08:28:24 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b="qSA/qe8c"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8466068B743; Sat, 5 Nov 2022 17:26:47 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6108B68B32D for ; Sat, 5 Nov 2022 17:26:36 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=93AuEKjTGKiXs30tWmHcfGHCau9IYgOKyHabEh876uA=; b=qSA/qe8cCBqENKCiOr53O84GdbMCdjhpm0fx6+spUF1Pj3kCasOIpMvYdrisRtWXRAq0pl eqLEb9mXb2vxN5LL0fbS2r7jG6nGTYqzV2A1++Nyu2duG4PHdjs1nF1oBArKFreo/RSGAX vqoCnbpXMVxPLFdu3nP5wAbtaw4e6BM= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id e3e70788; Sat, 5 Nov 2022 15:26:21 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:10 +0100 Message-Id: <20221105152617.1809282-9-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 08/15] avfilter/paletteuse: switch to a perceptual model X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8SE+uWvbZOnD Now the selection of the color is based on a distance built around human perception of color instead of the unreliable sRGB triplet one. --- libavfilter/Makefile | 2 +- libavfilter/vf_paletteuse.c | 196 ++++++++++---------- tests/ref/fate/filter-paletteuse-bayer | 142 +++++++------- tests/ref/fate/filter-paletteuse-bayer0 | 142 +++++++------- tests/ref/fate/filter-paletteuse-nodither | 142 +++++++------- tests/ref/fate/filter-paletteuse-sierra2_4a | 142 +++++++------- 6 files changed, 387 insertions(+), 379 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ace0e60ba1..e6b6d59d2d 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -402,7 +402,7 @@ OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PAD_OPENCL_FILTER) += vf_pad_opencl.o opencl.o opencl/pad.o OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o -OBJS-$(CONFIG_PALETTEUSE_FILTER) += vf_paletteuse.o framesync.o +OBJS-$(CONFIG_PALETTEUSE_FILTER) += vf_paletteuse.o framesync.o palette.o OBJS-$(CONFIG_PERMS_FILTER) += f_perms.o OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o OBJS-$(CONFIG_PHASE_FILTER) += vf_phase.o diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 0861a70a0b..7c64a63722 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -23,6 +23,8 @@ * Use a palette to downsample an input video stream. */ +#include + #include "libavutil/bprint.h" #include "libavutil/file_open.h" #include "libavutil/internal.h" @@ -32,6 +34,7 @@ #include "filters.h" #include "framesync.h" #include "internal.h" +#include "palette.h" enum dithering_mode { DITHERING_NONE, @@ -56,8 +59,13 @@ enum diff_mode { NB_DIFF_MODE }; +struct color_info { + uint32_t srgb; + float lab[3]; +}; + struct color_node { - uint32_t val; + struct color_info c; uint8_t palette_id; int split; int left_id, right_id; @@ -103,7 +111,7 @@ typedef struct PaletteUseContext { char *dot_filename; int color_search_method; int calc_mean_err; - uint64_t total_mean_err; + double total_mean_err; int debug_accuracy; } PaletteUseContext; @@ -162,33 +170,41 @@ static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, | av_clip_uint8((px & 0xff) + ((eb * scale) / (1<> 24, a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff}; - const uint8_t c2[] = {b >> 24, b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff}; - const int dr = c1[1] - c2[1]; - const int dg = c1[2] - c2[2]; - const int db = c1[3] - c2[3]; - - if (c1[0] < trans_thresh && c2[0] < trans_thresh) { + const uint8_t alpha_a = a->srgb >> 24; + const uint8_t alpha_b = b->srgb >> 24; + + if (alpha_a < trans_thresh && alpha_b < trans_thresh) { return 0; - } else if (c1[0] >= trans_thresh && c2[0] >= trans_thresh) { - return dr*dr + dg*dg + db*db; + } else if (alpha_a >= trans_thresh && alpha_b >= trans_thresh) { + const float dL = a->lab[0] - b->lab[0]; + const float da = a->lab[1] - b->lab[1]; + const float db = a->lab[2] - b->lab[2]; + return dL*dL + da*da + db*db; } else { - return 255*255 + 255*255 + 255*255; + return 2.f; /* above the oklab max diff */ } } -static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint32_t target, const int trans_thresh) +static struct color_info get_color_from_srgb(uint32_t srgb) +{ + const struct Lab lab = ff_srgb_u8_to_oklab(srgb); + struct color_info ret = {.srgb=srgb, .lab={lab.L, lab.a, lab.b}}; + return ret; +} + +static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const struct color_info *target, const int trans_thresh) { - int i, pal_id = -1, min_dist = INT_MAX; + int i, pal_id = -1; + float min_dist = FLT_MAX; for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = palette[i]; if (c >> 24 >= trans_thresh) { // ignore transparent entry - const int d = diff(palette[i], target, trans_thresh); + const struct color_info pal_color = get_color_from_srgb(palette[i]); + const float d = diff(&pal_color, target, trans_thresh); if (d < min_dist) { pal_id = i; min_dist = d; @@ -206,14 +222,13 @@ struct nearest_color { static void colormap_nearest_node(const struct color_node *map, const int node_pos, - const uint32_t target, + const struct color_info *target, const int trans_thresh, struct nearest_color *nearest) { const struct color_node *kd = map + node_pos; - const int shift = (2 - kd->split) * 8; - int dx, nearer_kd_id, further_kd_id; - const uint32_t current = kd->val; + int nearer_kd_id, further_kd_id; + const struct color_info *current = &kd->c; const int current_to_target = diff(target, current, trans_thresh); if (current_to_target < nearest->dist_sqd) { @@ -222,7 +237,7 @@ static void colormap_nearest_node(const struct color_node *map, } if (kd->left_id != -1 || kd->right_id != -1) { - dx = (int)(target>>shift & 0xff) - (int)(current>>shift & 0xff); + const float dx = target->lab[kd->split] - current->lab[kd->split]; if (dx <= 0) nearer_kd_id = kd->left_id, further_kd_id = kd->right_id; else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id; @@ -235,7 +250,7 @@ static void colormap_nearest_node(const struct color_node *map, } } -static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t target, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const struct color_info *target, const int trans_thresh) { struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1}; colormap_nearest_node(node, 0, target, trans_thresh, &res); @@ -247,17 +262,18 @@ struct stack_node { int dx2; }; -static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint32_t target, const int trans_thresh) +static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const struct color_info *target, const int trans_thresh) { - int pos = 0, best_node_id = -1, best_dist = INT_MAX, cur_color_id = 0; + int pos = 0, best_node_id = -1, cur_color_id = 0; + float best_dist = FLT_MAX; struct stack_node nodes[16]; struct stack_node *node = &nodes[0]; for (;;) { const struct color_node *kd = &root[cur_color_id]; - const uint32_t current = kd->val; - const int current_to_target = diff(target, current, trans_thresh); + const struct color_info *current = &kd->c; + const float current_to_target = diff(target, current, trans_thresh); /* Compare current color node to the target and update our best node if * it's actually better. */ @@ -270,8 +286,7 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no /* Check if it's not a leaf */ if (kd->left_id != -1 || kd->right_id != -1) { - const int shift = (2 - kd->split) * 8; - const int dx = (target>>shift & 0xff) - (current>>shift & 0xff); + const float dx = target->lab[kd->split] - current->lab[kd->split]; int nearer_kd_id, further_kd_id; /* Define which side is the most interesting. */ @@ -332,6 +347,7 @@ static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, const enum color_search_method search_method) { int i; + struct color_info clrinfo; const uint8_t rhash = (color>>16) & ((1<> 8) & ((1<color = color; - e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, color, s->trans_thresh); + clrinfo = get_color_from_srgb(color); + e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, &clrinfo, s->trans_thresh); return e->pal_entry; } @@ -494,20 +511,18 @@ static void disp_node(AVBPrint *buf, int depth) { const struct color_node *node = &map[node_id]; - const uint32_t fontcolor = (node->val>>16 & 0xff) > 0x50 && - (node->val>> 8 & 0xff) > 0x50 && - (node->val & 0xff) > 0x50 ? 0 : 0xffffff; - const int rgb_comp = node->split; + const uint32_t fontcolor = node->c.lab[0] > 0.5 ? 0 : 0xffffff; + const int lab_comp = node->split; av_bprintf(buf, "%*cnode%d [" - "label=\"%c%02X%c%02X%c%02X%c\" " + "label=\"%c%.3f%c%.3f%c%.3f%c\" " "fillcolor=\"#%06"PRIX32"\" " "fontcolor=\"#%06"PRIX32"\"]\n", depth*INDENT, ' ', node->palette_id, - "[ "[rgb_comp], node->val>>16 & 0xff, - "][ "[rgb_comp], node->val>> 8 & 0xff, - " ]["[rgb_comp], node->val & 0xff, - " ]"[rgb_comp], - node->val & 0xffffff, + "[ "[lab_comp], node->c.lab[0], + "][ "[lab_comp], node->c.lab[1], + " ]["[lab_comp], node->c.lab[2], + " ]"[lab_comp], + node->c.srgb & 0xffffff, fontcolor); if (parent_id != -1) av_bprintf(buf, "%*cnode%d -> node%d\n", depth*INDENT, ' ', @@ -550,18 +565,18 @@ static int debug_accuracy(const struct color_node *node, const uint32_t *palette for (r = 0; r < 256; r++) { for (g = 0; g < 256; g++) { for (b = 0; b < 256; b++) { - const uint32_t argb = 0xff000000 | r<<16 | g<<8 | b; - const int r1 = COLORMAP_NEAREST(search_method, palette, node, argb, trans_thresh); - const int r2 = colormap_nearest_bruteforce(palette, argb, trans_thresh); + const struct color_info target = get_color_from_srgb(0xff000000 | r<<16 | g<<8 | b); + const int r1 = COLORMAP_NEAREST(search_method, palette, node, &target, trans_thresh); + const int r2 = colormap_nearest_bruteforce(palette, &target, trans_thresh); if (r1 != r2) { - const uint32_t c1 = palette[r1]; - const uint32_t c2 = palette[r2]; - const int d1 = diff(0xff000000 | c1, argb, trans_thresh); - const int d2 = diff(0xff000000 | c2, argb, trans_thresh); - if (d1 != d2) { + const struct color_info pal_c1 = get_color_from_srgb(0xff000000 | palette[r1]); + const struct color_info pal_c2 = get_color_from_srgb(0xff000000 | palette[r2]); + const float d1 = diff(&pal_c1, &target, trans_thresh); + const float d2 = diff(&pal_c2, &target, trans_thresh); + if (fabsf(d1 - d2) > 0.0001) { av_log(NULL, AV_LOG_ERROR, - "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", - r, g, b, r1, r2, c1 & 0xffffff, c2 & 0xffffff, d1, d2); + "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %g ! %g\n", + r, g, b, r1, r2, pal_c1.srgb & 0xffffff, pal_c2.srgb & 0xffffff, d1, d2); ret = 1; } } @@ -572,66 +587,63 @@ static int debug_accuracy(const struct color_node *node, const uint32_t *palette } struct color { - uint32_t value; + struct Lab value; uint8_t pal_id; }; struct color_rect { - uint8_t min[3]; - uint8_t max[3]; + float min[3]; + float max[3]; }; typedef int (*cmp_func)(const void *, const void *); -#define DECLARE_CMP_FUNC(name, pos) \ +#define DECLARE_CMP_FUNC(name) \ static int cmp_##name(const void *pa, const void *pb) \ { \ const struct color *a = pa; \ const struct color *b = pb; \ - return (int)(a->value >> (8 * (2 - (pos))) & 0xff) \ - - (int)(b->value >> (8 * (2 - (pos))) & 0xff); \ + return FFDIFFSIGN(a->value.name, b->value.name); \ } -DECLARE_CMP_FUNC(r, 0) -DECLARE_CMP_FUNC(g, 1) -DECLARE_CMP_FUNC(b, 2) +DECLARE_CMP_FUNC(L) +DECLARE_CMP_FUNC(a) +DECLARE_CMP_FUNC(b) -static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; +static const cmp_func cmp_funcs[] = {cmp_L, cmp_a, cmp_b}; static int get_next_color(const uint8_t *color_used, const uint32_t *palette, int *component, const struct color_rect *box) { - int wr, wg, wb; + float wL, wa, wb; int i, longest = 0; unsigned nb_color = 0; struct color_rect ranges; struct color tmp_pal[256]; cmp_func cmpf; - ranges.min[0] = ranges.min[1] = ranges.min[2] = 0xff; - ranges.max[0] = ranges.max[1] = ranges.max[2] = 0x00; + ranges.min[0] = ranges.min[1] = ranges.min[2] = FLT_MAX; + ranges.max[0] = ranges.max[1] = ranges.max[2] = -FLT_MAX; for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = palette[i]; const uint8_t a = c >> 24; - const uint8_t r = c >> 16 & 0xff; - const uint8_t g = c >> 8 & 0xff; - const uint8_t b = c & 0xff; + const struct Lab lab = ff_srgb_u8_to_oklab(c); if (color_used[i] || (a != 0xff) || - r < box->min[0] || g < box->min[1] || b < box->min[2] || - r > box->max[0] || g > box->max[1] || b > box->max[2]) + lab.L < box->min[0] || lab.a < box->min[1] || lab.b < box->min[2] || + lab.L > box->max[0] || lab.a > box->max[1] || lab.b > box->max[2]) continue; - if (r < ranges.min[0]) ranges.min[0] = r; - if (g < ranges.min[1]) ranges.min[1] = g; - if (b < ranges.min[2]) ranges.min[2] = b; + if (lab.L < ranges.min[0]) ranges.min[0] = lab.L; + if (lab.a < ranges.min[1]) ranges.min[1] = lab.a; + if (lab.b < ranges.min[2]) ranges.min[2] = lab.b; - if (r > ranges.max[0]) ranges.max[0] = r; - if (g > ranges.max[1]) ranges.max[1] = g; - if (b > ranges.max[2]) ranges.max[2] = b; + if (lab.L > ranges.max[0]) ranges.max[0] = lab.L; + if (lab.a > ranges.max[1]) ranges.max[1] = lab.a; + if (lab.b > ranges.max[2]) ranges.max[2] = lab.b; - tmp_pal[nb_color].value = c; + tmp_pal[nb_color].value = lab; tmp_pal[nb_color].pal_id = i; nb_color++; @@ -641,12 +653,12 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, return -1; /* define longest axis that will be the split component */ - wr = ranges.max[0] - ranges.min[0]; - wg = ranges.max[1] - ranges.min[1]; + wL = ranges.max[0] - ranges.min[0]; + wa = ranges.max[1] - ranges.min[1]; wb = ranges.max[2] - ranges.min[2]; - if (wr >= wg && wr >= wb) longest = 0; - if (wg >= wr && wg >= wb) longest = 1; - if (wb >= wr && wb >= wg) longest = 2; + if (wb >= wL && wb >= wa) longest = 2; + if (wa >= wL && wa >= wb) longest = 1; + if (wL >= wa && wL >= wb) longest = 0; cmpf = cmp_funcs[longest]; *component = longest; @@ -663,9 +675,8 @@ static int colormap_insert(struct color_node *map, const int trans_thresh, const struct color_rect *box) { - uint32_t c; int component, cur_id; - uint8_t comp_value; + float comp_value; int node_left_id = -1, node_right_id = -1; struct color_node *node; struct color_rect box1, box2; @@ -676,19 +687,18 @@ static int colormap_insert(struct color_node *map, /* create new node with that color */ cur_id = (*nb_used)++; - c = palette[pal_id]; node = &map[cur_id]; node->split = component; node->palette_id = pal_id; - node->val = c; + node->c = get_color_from_srgb(palette[pal_id]); color_used[pal_id] = 1; /* get the two boxes this node creates */ box1 = box2 = *box; - comp_value = node->val >> ((2 - component) * 8) & 0xff; + comp_value = node->c.lab[component]; box1.max[component] = comp_value; - box2.min[component] = FFMIN(comp_value + 1, 255); + box2.min[component] = comp_value + FLT_EPSILON; node_left_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box1); @@ -735,8 +745,8 @@ static void load_colormap(PaletteUseContext *s) } } - box.min[0] = box.min[1] = box.min[2] = 0x00; - box.max[0] = box.max[1] = box.max[2] = 0xff; + box.min[0] = box.min[1] = box.min[2] = -FLT_MAX; + box.max[0] = box.max[1] = box.max[2] = FLT_MAX; colormap_insert(s->map, color_used, &nb_used, s->palette, s->trans_thresh, &box); @@ -759,15 +769,13 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, const int src1_linesize = in1->linesize[0] >> 2; const int src2_linesize = in2->linesize[0]; const float div = in1->width * in1->height * 3; - unsigned mean_err = 0; + float mean_err = 0.f; for (y = 0; y < in1->height; y++) { for (x = 0; x < in1->width; x++) { - const uint32_t c1 = src1[x]; - const uint32_t c2 = palette[src2[x]]; - const uint32_t argb1 = 0xff000000 | c1; - const uint32_t argb2 = 0xff000000 | c2; - mean_err += diff(argb1, argb2, s->trans_thresh); + const struct color_info c1 = get_color_from_srgb(0xff000000 | src1[x]); + const struct color_info c2 = get_color_from_srgb(0xff000000 | palette[src2[x]]); + mean_err += diff(&c1, &c2, s->trans_thresh); } src1 += src1_linesize; src2 += src2_linesize; diff --git a/tests/ref/fate/filter-paletteuse-bayer b/tests/ref/fate/filter-paletteuse-bayer index 5ca0115053..00c3a07229 100644 --- a/tests/ref/fate/filter-paletteuse-bayer +++ b/tests/ref/fate/filter-paletteuse-bayer @@ -3,74 +3,74 @@ #codec_id 0: rawvideo #dimensions 0: 320x180 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0x7b259d08 -0, 1, 1, 1, 230400, 0xf04095e0 -0, 2, 2, 1, 230400, 0x84d49cd5 -0, 3, 3, 1, 230400, 0xd7a29aaf -0, 4, 4, 1, 230400, 0x9047947c -0, 5, 5, 1, 230400, 0xfeb990e7 -0, 6, 6, 1, 230400, 0x51ee9295 -0, 7, 7, 1, 230400, 0x66fd4833 -0, 8, 8, 1, 230400, 0x4c0948f0 -0, 9, 9, 1, 230400, 0x632b4776 -0, 10, 10, 1, 230400, 0x7a3c87e2 -0, 11, 11, 1, 230400, 0x4a9286ba -0, 12, 12, 1, 230400, 0x54dc8649 -0, 13, 13, 1, 230400, 0x92628944 -0, 14, 14, 1, 230400, 0x80f9899f -0, 15, 15, 1, 230400, 0x5cd78bd8 -0, 16, 16, 1, 230400, 0x4b4ca390 -0, 17, 17, 1, 230400, 0x82cca153 -0, 18, 18, 1, 230400, 0x65f1a2d0 -0, 19, 19, 1, 230400, 0x7df6ae4c -0, 20, 20, 1, 230400, 0x909baccc -0, 21, 21, 1, 230400, 0x1892ac65 -0, 22, 22, 1, 230400, 0x3247bb32 -0, 23, 23, 1, 230400, 0x592fbbe5 -0, 24, 24, 1, 230400, 0x189db9d5 -0, 25, 25, 1, 230400, 0x1a38b8da -0, 26, 26, 1, 230400, 0xccd6bd07 -0, 27, 27, 1, 230400, 0xd4a2bc53 -0, 28, 28, 1, 230400, 0x9ce3bb4e -0, 29, 29, 1, 230400, 0x5ffdc4db -0, 30, 30, 1, 230400, 0xc885c7c9 -0, 31, 31, 1, 230400, 0xe27b9d33 -0, 32, 32, 1, 230400, 0xac03a256 -0, 33, 33, 1, 230400, 0xa2c73929 -0, 34, 34, 1, 230400, 0x33793b73 -0, 35, 35, 1, 230400, 0x1e400add -0, 36, 36, 1, 230400, 0x98e50c6e -0, 37, 37, 1, 230400, 0x68ed226d -0, 38, 38, 1, 230400, 0x569e23cb -0, 39, 39, 1, 230400, 0x82bf3fc0 -0, 40, 40, 1, 230400, 0x2b202e86 -0, 41, 41, 1, 230400, 0x7acd2dee -0, 42, 42, 1, 230400, 0xfe872e42 -0, 43, 43, 1, 230400, 0x026c12e5 -0, 44, 44, 1, 230400, 0x81561399 -0, 45, 45, 1, 230400, 0xa08c13b6 -0, 46, 46, 1, 230400, 0x89e712f5 -0, 47, 47, 1, 230400, 0x569011ac -0, 48, 48, 1, 230400, 0xd4691112 -0, 49, 49, 1, 230400, 0x2e50165a -0, 50, 50, 1, 230400, 0x0a1215b6 -0, 51, 51, 1, 230400, 0x3c5316e3 -0, 52, 52, 1, 230400, 0x079c1393 -0, 53, 53, 1, 230400, 0x39ca1c48 -0, 54, 54, 1, 230400, 0xe27f199c -0, 55, 55, 1, 230400, 0x10ab1bab -0, 56, 56, 1, 230400, 0xeab017c3 -0, 57, 57, 1, 230400, 0x5f701f77 -0, 58, 58, 1, 230400, 0x01371d7d -0, 59, 59, 1, 230400, 0x22751e99 -0, 60, 60, 1, 230400, 0xaee91a97 -0, 61, 61, 1, 230400, 0x27b41f32 -0, 62, 62, 1, 230400, 0x4ff32bb1 -0, 63, 63, 1, 230400, 0x86e02864 -0, 64, 64, 1, 230400, 0x5eb52b3e -0, 65, 65, 1, 230400, 0xd9252ba8 -0, 66, 66, 1, 230400, 0x72232d9b -0, 67, 67, 1, 230400, 0x599a206f -0, 68, 68, 1, 230400, 0x4d2c1ca5 -0, 69, 69, 1, 230400, 0x9166293b -0, 70, 70, 1, 230400, 0x00992453 +0, 0, 0, 1, 230400, 0xb10296af +0, 1, 1, 1, 230400, 0x46299027 +0, 2, 2, 1, 230400, 0xe0209504 +0, 3, 3, 1, 230400, 0xfe8e93a0 +0, 4, 4, 1, 230400, 0x3ec88da3 +0, 5, 5, 1, 230400, 0x06918aaa +0, 6, 6, 1, 230400, 0x215a8ba4 +0, 7, 7, 1, 230400, 0x74614048 +0, 8, 8, 1, 230400, 0xe46a409e +0, 9, 9, 1, 230400, 0x20834060 +0, 10, 10, 1, 230400, 0x29258036 +0, 11, 11, 1, 230400, 0x16207f8b +0, 12, 12, 1, 230400, 0x90dc7e61 +0, 13, 13, 1, 230400, 0x59937f90 +0, 14, 14, 1, 230400, 0x6a487fe8 +0, 15, 15, 1, 230400, 0x73e98214 +0, 16, 16, 1, 230400, 0x48119a78 +0, 17, 17, 1, 230400, 0x999899df +0, 18, 18, 1, 230400, 0x0d7f9b24 +0, 19, 19, 1, 230400, 0xc581a5b7 +0, 20, 20, 1, 230400, 0xaf1ea56f +0, 21, 21, 1, 230400, 0xe010a52c +0, 22, 22, 1, 230400, 0x8eacb3ab +0, 23, 23, 1, 230400, 0x9e60b383 +0, 24, 24, 1, 230400, 0x69aeb25b +0, 25, 25, 1, 230400, 0x1febb1e1 +0, 26, 26, 1, 230400, 0x5d65b4e0 +0, 27, 27, 1, 230400, 0x79ecb43f +0, 28, 28, 1, 230400, 0x3c3eb35a +0, 29, 29, 1, 230400, 0xb96cc086 +0, 30, 30, 1, 230400, 0x07b0c1ba +0, 31, 31, 1, 230400, 0xe3c798ae +0, 32, 32, 1, 230400, 0xf7389e03 +0, 33, 33, 1, 230400, 0x63222e23 +0, 34, 34, 1, 230400, 0xbe063030 +0, 35, 35, 1, 230400, 0x2819fdf3 +0, 36, 36, 1, 230400, 0x7e0bfef1 +0, 37, 37, 1, 230400, 0xee321a8b +0, 38, 38, 1, 230400, 0x5fce1a96 +0, 39, 39, 1, 230400, 0x530a35a4 +0, 40, 40, 1, 230400, 0xa5ce2647 +0, 41, 41, 1, 230400, 0x969a25d4 +0, 42, 42, 1, 230400, 0x4f012620 +0, 43, 43, 1, 230400, 0x50bc0870 +0, 44, 44, 1, 230400, 0xc6de08a6 +0, 45, 45, 1, 230400, 0xe08b092e +0, 46, 46, 1, 230400, 0x9a6a08d7 +0, 47, 47, 1, 230400, 0x788d074c +0, 48, 48, 1, 230400, 0x08124376 +0, 49, 49, 1, 230400, 0xcb3748ed +0, 50, 50, 1, 230400, 0x33e747f1 +0, 51, 51, 1, 230400, 0x9a2f4994 +0, 52, 52, 1, 230400, 0x501246e6 +0, 53, 53, 1, 230400, 0x11644de9 +0, 54, 54, 1, 230400, 0xef294aca +0, 55, 55, 1, 230400, 0x3ade4cb3 +0, 56, 56, 1, 230400, 0x56954a34 +0, 57, 57, 1, 230400, 0x513e4feb +0, 58, 58, 1, 230400, 0x828f4ea6 +0, 59, 59, 1, 230400, 0x76b04fc7 +0, 60, 60, 1, 230400, 0x67434c78 +0, 61, 61, 1, 230400, 0xf05250fd +0, 62, 62, 1, 230400, 0xf4cd5ac5 +0, 63, 63, 1, 230400, 0x4e4056d9 +0, 64, 64, 1, 230400, 0x6af258fa +0, 65, 65, 1, 230400, 0xa4525a55 +0, 66, 66, 1, 230400, 0xf3c15c01 +0, 67, 67, 1, 230400, 0x407553ae +0, 68, 68, 1, 230400, 0x913e5009 +0, 69, 69, 1, 230400, 0x7fe95b6b +0, 70, 70, 1, 230400, 0x24cb57fe diff --git a/tests/ref/fate/filter-paletteuse-bayer0 b/tests/ref/fate/filter-paletteuse-bayer0 index 85b3832f19..b7b80257d6 100644 --- a/tests/ref/fate/filter-paletteuse-bayer0 +++ b/tests/ref/fate/filter-paletteuse-bayer0 @@ -3,74 +3,74 @@ #codec_id 0: rawvideo #dimensions 0: 320x180 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0xfb6042d2 -0, 1, 1, 1, 230400, 0x1c193c09 -0, 2, 2, 1, 230400, 0x183442f8 -0, 3, 3, 1, 230400, 0xa9634084 -0, 4, 4, 1, 230400, 0x90df3d2f -0, 5, 5, 1, 230400, 0x59d7389f -0, 6, 6, 1, 230400, 0xb9bd3a30 -0, 7, 7, 1, 230400, 0x9874ee38 -0, 8, 8, 1, 230400, 0xf661f01f -0, 9, 9, 1, 230400, 0xacbcedbd -0, 10, 10, 1, 230400, 0x05f02d59 -0, 11, 11, 1, 230400, 0xc54c2cc8 -0, 12, 12, 1, 230400, 0x19c92d61 -0, 13, 13, 1, 230400, 0x14902fb2 -0, 14, 14, 1, 230400, 0x99b62fb6 -0, 15, 15, 1, 230400, 0x3fc63293 -0, 16, 16, 1, 230400, 0x1eed4b38 -0, 17, 17, 1, 230400, 0xe9d747e0 -0, 18, 18, 1, 230400, 0x9825496f -0, 19, 19, 1, 230400, 0x94625411 -0, 20, 20, 1, 230400, 0xed7052a3 -0, 21, 21, 1, 230400, 0x80d552dc -0, 22, 22, 1, 230400, 0x89b360bb -0, 23, 23, 1, 230400, 0xee9a616a -0, 24, 24, 1, 230400, 0x30bb5f86 -0, 25, 25, 1, 230400, 0x5ec15eae -0, 26, 26, 1, 230400, 0x0956633e -0, 27, 27, 1, 230400, 0x72df62fa -0, 28, 28, 1, 230400, 0xbafd61d0 -0, 29, 29, 1, 230400, 0x393f81f3 -0, 30, 30, 1, 230400, 0xba6a848c -0, 31, 31, 1, 230400, 0x502ba0d9 -0, 32, 32, 1, 230400, 0xc81ba71d -0, 33, 33, 1, 230400, 0x54cdf270 -0, 34, 34, 1, 230400, 0xe951f3e2 -0, 35, 35, 1, 230400, 0xbf15baa1 -0, 36, 36, 1, 230400, 0xbf96bb12 -0, 37, 37, 1, 230400, 0xcdd5cafe -0, 38, 38, 1, 230400, 0x97b1cbb4 -0, 39, 39, 1, 230400, 0x955ae28f -0, 40, 40, 1, 230400, 0x6a8dd28f -0, 41, 41, 1, 230400, 0x8f02d268 -0, 42, 42, 1, 230400, 0x3075d269 -0, 43, 43, 1, 230400, 0x29e8b910 -0, 44, 44, 1, 230400, 0xb35ab888 -0, 45, 45, 1, 230400, 0xc3afb942 -0, 46, 46, 1, 230400, 0xeba8b860 -0, 47, 47, 1, 230400, 0x5de8b7ab -0, 48, 48, 1, 230400, 0x90233679 -0, 49, 49, 1, 230400, 0x5fbc3abb -0, 50, 50, 1, 230400, 0xeaa73b87 -0, 51, 51, 1, 230400, 0xbd0a3c4b -0, 52, 52, 1, 230400, 0xeddb39ba -0, 53, 53, 1, 230400, 0x269d4131 -0, 54, 54, 1, 230400, 0xae3e3e8c -0, 55, 55, 1, 230400, 0x65f54056 -0, 56, 56, 1, 230400, 0xf2173c5b -0, 57, 57, 1, 230400, 0xbd714477 -0, 58, 58, 1, 230400, 0xb60c42ed -0, 59, 59, 1, 230400, 0x8def43a5 -0, 60, 60, 1, 230400, 0xe6a73f05 -0, 61, 61, 1, 230400, 0xedfe4430 -0, 62, 62, 1, 230400, 0x76c5505a -0, 63, 63, 1, 230400, 0xf48d4d04 -0, 64, 64, 1, 230400, 0xa49950b5 -0, 65, 65, 1, 230400, 0xc64d51d8 -0, 66, 66, 1, 230400, 0xa08253ec -0, 67, 67, 1, 230400, 0xd6ef4609 -0, 68, 68, 1, 230400, 0x27a241e7 -0, 69, 69, 1, 230400, 0xe5f74b4a -0, 70, 70, 1, 230400, 0xb0194751 +0, 0, 0, 1, 230400, 0x01fe2d8a +0, 1, 1, 1, 230400, 0x6f4627f6 +0, 2, 2, 1, 230400, 0xce492cae +0, 3, 3, 1, 230400, 0x95bf2b0e +0, 4, 4, 1, 230400, 0x4d212758 +0, 5, 5, 1, 230400, 0xfddd244c +0, 6, 6, 1, 230400, 0x2bdc258d +0, 7, 7, 1, 230400, 0x98bedba9 +0, 8, 8, 1, 230400, 0x1708dd0a +0, 9, 9, 1, 230400, 0xff3ddc41 +0, 10, 10, 1, 230400, 0xed4318e1 +0, 11, 11, 1, 230400, 0xb38718ac +0, 12, 12, 1, 230400, 0x0789190e +0, 13, 13, 1, 230400, 0x5f271ae5 +0, 14, 14, 1, 230400, 0x76651b29 +0, 15, 15, 1, 230400, 0x6c301d7c +0, 16, 16, 1, 230400, 0xb62d3725 +0, 17, 17, 1, 230400, 0x54dc33c3 +0, 18, 18, 1, 230400, 0xa9ee3569 +0, 19, 19, 1, 230400, 0xf6d23cec +0, 20, 20, 1, 230400, 0xdcad3c8a +0, 21, 21, 1, 230400, 0x00363bf2 +0, 22, 22, 1, 230400, 0xd12d4957 +0, 23, 23, 1, 230400, 0xab8c49a6 +0, 24, 24, 1, 230400, 0x1ad84813 +0, 25, 25, 1, 230400, 0xabd9478b +0, 26, 26, 1, 230400, 0x12e14baf +0, 27, 27, 1, 230400, 0x9ee14ae0 +0, 28, 28, 1, 230400, 0xd12449c8 +0, 29, 29, 1, 230400, 0x0e2a6b56 +0, 30, 30, 1, 230400, 0xe8576d6f +0, 31, 31, 1, 230400, 0x37d98437 +0, 32, 32, 1, 230400, 0xb289885b +0, 33, 33, 1, 230400, 0x0089d63d +0, 34, 34, 1, 230400, 0x0014d741 +0, 35, 35, 1, 230400, 0x5a7fa00f +0, 36, 36, 1, 230400, 0x7b6fa0fe +0, 37, 37, 1, 230400, 0xf282b3cf +0, 38, 38, 1, 230400, 0xc677b478 +0, 39, 39, 1, 230400, 0x8baec95a +0, 40, 40, 1, 230400, 0x6983b858 +0, 41, 41, 1, 230400, 0x465eb79e +0, 42, 42, 1, 230400, 0x5e30b848 +0, 43, 43, 1, 230400, 0x910e9ed3 +0, 44, 44, 1, 230400, 0x5f3e9f2d +0, 45, 45, 1, 230400, 0xccf39fbf +0, 46, 46, 1, 230400, 0x781a9f7d +0, 47, 47, 1, 230400, 0x59e49e00 +0, 48, 48, 1, 230400, 0xe7c97e5b +0, 49, 49, 1, 230400, 0xda7e838b +0, 50, 50, 1, 230400, 0x34088343 +0, 51, 51, 1, 230400, 0x731b844c +0, 52, 52, 1, 230400, 0x8e1581fc +0, 53, 53, 1, 230400, 0x51d888c0 +0, 54, 54, 1, 230400, 0x461185dd +0, 55, 55, 1, 230400, 0xc933880d +0, 56, 56, 1, 230400, 0xb9c28413 +0, 57, 57, 1, 230400, 0x33f08cbc +0, 58, 58, 1, 230400, 0x02688a80 +0, 59, 59, 1, 230400, 0x424c8b6a +0, 60, 60, 1, 230400, 0xf1288742 +0, 61, 61, 1, 230400, 0x4780898b +0, 62, 62, 1, 230400, 0xfbd59439 +0, 63, 63, 1, 230400, 0x770d9032 +0, 64, 64, 1, 230400, 0x53b99251 +0, 65, 65, 1, 230400, 0x8de79376 +0, 66, 66, 1, 230400, 0x292a95c3 +0, 67, 67, 1, 230400, 0x60dc8b46 +0, 68, 68, 1, 230400, 0xeb4288ca +0, 69, 69, 1, 230400, 0xb9da9475 +0, 70, 70, 1, 230400, 0xc524912c diff --git a/tests/ref/fate/filter-paletteuse-nodither b/tests/ref/fate/filter-paletteuse-nodither index a2e61c3690..2e49c90642 100644 --- a/tests/ref/fate/filter-paletteuse-nodither +++ b/tests/ref/fate/filter-paletteuse-nodither @@ -3,74 +3,74 @@ #codec_id 0: rawvideo #dimensions 0: 320x180 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0x690560cb -0, 1, 1, 1, 230400, 0x197a5a54 -0, 2, 2, 1, 230400, 0x665961db -0, 3, 3, 1, 230400, 0xce0b5fa8 -0, 4, 4, 1, 230400, 0xa40e5cb0 -0, 5, 5, 1, 230400, 0xa5aa58da -0, 6, 6, 1, 230400, 0x8e0259bb -0, 7, 7, 1, 230400, 0x476d0dba -0, 8, 8, 1, 230400, 0xfb1b0e8c -0, 9, 9, 1, 230400, 0x50f60d3b -0, 10, 10, 1, 230400, 0x12cd4bab -0, 11, 11, 1, 230400, 0x4c274b13 -0, 12, 12, 1, 230400, 0xea494b0a -0, 13, 13, 1, 230400, 0x118c4cc1 -0, 14, 14, 1, 230400, 0xd4224db7 -0, 15, 15, 1, 230400, 0xc3014f88 -0, 16, 16, 1, 230400, 0xe07a6838 -0, 17, 17, 1, 230400, 0x1b97659a -0, 18, 18, 1, 230400, 0xf104670c -0, 19, 19, 1, 230400, 0x7b63733d -0, 20, 20, 1, 230400, 0x2c237200 -0, 21, 21, 1, 230400, 0x775d7248 -0, 22, 22, 1, 230400, 0xcaee7f9e -0, 23, 23, 1, 230400, 0x4e4680a1 -0, 24, 24, 1, 230400, 0x21fb7e53 -0, 25, 25, 1, 230400, 0xf0297db6 -0, 26, 26, 1, 230400, 0x79a9829d -0, 27, 27, 1, 230400, 0x8ccb80f7 -0, 28, 28, 1, 230400, 0xf4dd807f -0, 29, 29, 1, 230400, 0xb6cc8696 -0, 30, 30, 1, 230400, 0x6c8a8917 -0, 31, 31, 1, 230400, 0x9e08615a -0, 32, 32, 1, 230400, 0xc098685b -0, 33, 33, 1, 230400, 0x5c09e710 -0, 34, 34, 1, 230400, 0xe4c4e9be -0, 35, 35, 1, 230400, 0xac59c150 -0, 36, 36, 1, 230400, 0x6045c272 -0, 37, 37, 1, 230400, 0xf71ee6dc -0, 38, 38, 1, 230400, 0xc82ce6f6 -0, 39, 39, 1, 230400, 0xb7ed039a -0, 40, 40, 1, 230400, 0xda93f241 -0, 41, 41, 1, 230400, 0x194bf23b -0, 42, 42, 1, 230400, 0xe7e6f2e2 -0, 43, 43, 1, 230400, 0xe479d834 -0, 44, 44, 1, 230400, 0xefdfd87e -0, 45, 45, 1, 230400, 0xec66d8c0 -0, 46, 46, 1, 230400, 0x3a6bd81b -0, 47, 47, 1, 230400, 0xb5d1d700 -0, 48, 48, 1, 230400, 0x3bc69e8b -0, 49, 49, 1, 230400, 0x723fa455 -0, 50, 50, 1, 230400, 0x7c49a392 -0, 51, 51, 1, 230400, 0x272ea4b7 -0, 52, 52, 1, 230400, 0xebdda081 -0, 53, 53, 1, 230400, 0xfd26ab99 -0, 54, 54, 1, 230400, 0xfa02a891 -0, 55, 55, 1, 230400, 0xda2caa7f -0, 56, 56, 1, 230400, 0x2360a611 -0, 57, 57, 1, 230400, 0xaa3baefd -0, 58, 58, 1, 230400, 0x0961ad5c -0, 59, 59, 1, 230400, 0x48d2ae47 -0, 60, 60, 1, 230400, 0x20eda81b -0, 61, 61, 1, 230400, 0x8821adbb -0, 62, 62, 1, 230400, 0x1150b810 -0, 63, 63, 1, 230400, 0x08dab596 -0, 64, 64, 1, 230400, 0x4731b7a5 -0, 65, 65, 1, 230400, 0xf382b87e -0, 66, 66, 1, 230400, 0xdba7bac2 -0, 67, 67, 1, 230400, 0xf569acf9 -0, 68, 68, 1, 230400, 0x22d8a95d -0, 69, 69, 1, 230400, 0xed0bb4fb -0, 70, 70, 1, 230400, 0x2dccb218 +0, 0, 0, 1, 230400, 0xda3668c3 +0, 1, 1, 1, 230400, 0xe38c63c9 +0, 2, 2, 1, 230400, 0xc3e56916 +0, 3, 3, 1, 230400, 0x8ce566f1 +0, 4, 4, 1, 230400, 0x99b2640a +0, 5, 5, 1, 230400, 0xa5066135 +0, 6, 6, 1, 230400, 0x35616241 +0, 7, 7, 1, 230400, 0x745a16de +0, 8, 8, 1, 230400, 0x53af17d6 +0, 9, 9, 1, 230400, 0x566416cb +0, 10, 10, 1, 230400, 0x8244546a +0, 11, 11, 1, 230400, 0x214353d6 +0, 12, 12, 1, 230400, 0xdf925444 +0, 13, 13, 1, 230400, 0xc248565a +0, 14, 14, 1, 230400, 0x2fa85718 +0, 15, 15, 1, 230400, 0x520b5943 +0, 16, 16, 1, 230400, 0xc4cf70cb +0, 17, 17, 1, 230400, 0x3a6270db +0, 18, 18, 1, 230400, 0xf7bd71e3 +0, 19, 19, 1, 230400, 0x12807d95 +0, 20, 20, 1, 230400, 0x332f7c3f +0, 21, 21, 1, 230400, 0xcf4c7c0f +0, 22, 22, 1, 230400, 0x911f8a0e +0, 23, 23, 1, 230400, 0x3e228a70 +0, 24, 24, 1, 230400, 0x61c988ac +0, 25, 25, 1, 230400, 0xb0858866 +0, 26, 26, 1, 230400, 0x57de8c17 +0, 27, 27, 1, 230400, 0x4bfc8ac8 +0, 28, 28, 1, 230400, 0x74a489e5 +0, 29, 29, 1, 230400, 0xdb5490df +0, 30, 30, 1, 230400, 0x776292cf +0, 31, 31, 1, 230400, 0xae486ba1 +0, 32, 32, 1, 230400, 0x6e3f707d +0, 33, 33, 1, 230400, 0x263bfbca +0, 34, 34, 1, 230400, 0xe1d7fdc4 +0, 35, 35, 1, 230400, 0xdc58c970 +0, 36, 36, 1, 230400, 0x74d4cb3c +0, 37, 37, 1, 230400, 0x18d9ec35 +0, 38, 38, 1, 230400, 0x3760ec21 +0, 39, 39, 1, 230400, 0xc4fe0800 +0, 40, 40, 1, 230400, 0xa455f91a +0, 41, 41, 1, 230400, 0xce4bf7e4 +0, 42, 42, 1, 230400, 0xeafef8f9 +0, 43, 43, 1, 230400, 0x4ab1df5d +0, 44, 44, 1, 230400, 0x97d6df79 +0, 45, 45, 1, 230400, 0x1b64e00c +0, 46, 46, 1, 230400, 0x5f33df02 +0, 47, 47, 1, 230400, 0x1badde2f +0, 48, 48, 1, 230400, 0xac7fba78 +0, 49, 49, 1, 230400, 0xe945bf9c +0, 50, 50, 1, 230400, 0x8ce6bed7 +0, 51, 51, 1, 230400, 0x209abff6 +0, 52, 52, 1, 230400, 0x229dbcb3 +0, 53, 53, 1, 230400, 0xb3ccc5f7 +0, 54, 54, 1, 230400, 0x9d9dc246 +0, 55, 55, 1, 230400, 0x8bbec364 +0, 56, 56, 1, 230400, 0x3699c05f +0, 57, 57, 1, 230400, 0x37b7c94b +0, 58, 58, 1, 230400, 0x7c91c7e8 +0, 59, 59, 1, 230400, 0xc7dfc81c +0, 60, 60, 1, 230400, 0x3d6dc2b3 +0, 61, 61, 1, 230400, 0x1a80c7d8 +0, 62, 62, 1, 230400, 0xabced0e4 +0, 63, 63, 1, 230400, 0x922fcdfd +0, 64, 64, 1, 230400, 0x251ad0b1 +0, 65, 65, 1, 230400, 0xde2cd0df +0, 66, 66, 1, 230400, 0x74d2d3f4 +0, 67, 67, 1, 230400, 0x0bb5c9c1 +0, 68, 68, 1, 230400, 0x312dc634 +0, 69, 69, 1, 230400, 0x499bd13c +0, 70, 70, 1, 230400, 0x8ec5cf57 diff --git a/tests/ref/fate/filter-paletteuse-sierra2_4a b/tests/ref/fate/filter-paletteuse-sierra2_4a index d257820a32..e654a5c8f3 100644 --- a/tests/ref/fate/filter-paletteuse-sierra2_4a +++ b/tests/ref/fate/filter-paletteuse-sierra2_4a @@ -3,74 +3,74 @@ #codec_id 0: rawvideo #dimensions 0: 320x180 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0xa4f85758 -0, 1, 1, 1, 230400, 0xbe83505c -0, 2, 2, 1, 230400, 0x0a09584e -0, 3, 3, 1, 230400, 0xd2065629 -0, 4, 4, 1, 230400, 0x11eb5319 -0, 5, 5, 1, 230400, 0x61024f4c -0, 6, 6, 1, 230400, 0xd5384faa -0, 7, 7, 1, 230400, 0xdeae0343 -0, 8, 8, 1, 230400, 0xcb640541 -0, 9, 9, 1, 230400, 0xea2602c3 -0, 10, 10, 1, 230400, 0xa7974293 -0, 11, 11, 1, 230400, 0x67cd4287 -0, 12, 12, 1, 230400, 0x83fa437a -0, 13, 13, 1, 230400, 0x852b42bf -0, 14, 14, 1, 230400, 0x6d2d434c -0, 15, 15, 1, 230400, 0x20c44629 -0, 16, 16, 1, 230400, 0xf2a35f57 -0, 17, 17, 1, 230400, 0x232959ec -0, 18, 18, 1, 230400, 0x1f8e5c48 -0, 19, 19, 1, 230400, 0x88dc69bd -0, 20, 20, 1, 230400, 0x4b6866f3 -0, 21, 21, 1, 230400, 0xe8f966dc -0, 22, 22, 1, 230400, 0xe0877466 -0, 23, 23, 1, 230400, 0x8799748c -0, 24, 24, 1, 230400, 0xcab871bc -0, 25, 25, 1, 230400, 0x2e0372b4 -0, 26, 26, 1, 230400, 0x15fb77d5 -0, 27, 27, 1, 230400, 0xbadf75fc -0, 28, 28, 1, 230400, 0xa4977626 -0, 29, 29, 1, 230400, 0x5b987943 -0, 30, 30, 1, 230400, 0x9ed57c09 -0, 31, 31, 1, 230400, 0x565d5105 -0, 32, 32, 1, 230400, 0x901b5a07 -0, 33, 33, 1, 230400, 0x8dc4e9a8 -0, 34, 34, 1, 230400, 0x0b9cee1c -0, 35, 35, 1, 230400, 0x2bcdbe37 -0, 36, 36, 1, 230400, 0xf3e2bf71 -0, 37, 37, 1, 230400, 0xb718da67 -0, 38, 38, 1, 230400, 0x8f59da64 -0, 39, 39, 1, 230400, 0x8812f9aa -0, 40, 40, 1, 230400, 0xe0dae6a3 -0, 41, 41, 1, 230400, 0xd2c7e5b7 -0, 42, 42, 1, 230400, 0xea2ae5d2 -0, 43, 43, 1, 230400, 0x2d66ca25 -0, 44, 44, 1, 230400, 0xf0d3cac6 -0, 45, 45, 1, 230400, 0xb9acccac -0, 46, 46, 1, 230400, 0x8523ca4a -0, 47, 47, 1, 230400, 0x92b9c9ef -0, 48, 48, 1, 230400, 0x0a88946e -0, 49, 49, 1, 230400, 0xe33699b8 -0, 50, 50, 1, 230400, 0x5e7b9917 -0, 51, 51, 1, 230400, 0xdac99998 -0, 52, 52, 1, 230400, 0xb5c995fc -0, 53, 53, 1, 230400, 0x908b9f50 -0, 54, 54, 1, 230400, 0x60d59ced -0, 55, 55, 1, 230400, 0x212e9f55 -0, 56, 56, 1, 230400, 0x95e69b2a -0, 57, 57, 1, 230400, 0x6c38a34a -0, 58, 58, 1, 230400, 0xeb32a103 -0, 59, 59, 1, 230400, 0x0131a1b7 -0, 60, 60, 1, 230400, 0xd59b9c4e -0, 61, 61, 1, 230400, 0x2fc0a13f -0, 62, 62, 1, 230400, 0x7a40adf9 -0, 63, 63, 1, 230400, 0x5cdbab2f -0, 64, 64, 1, 230400, 0xcdc0ada8 -0, 65, 65, 1, 230400, 0x2f5faf32 -0, 66, 66, 1, 230400, 0xd463b224 -0, 67, 67, 1, 230400, 0xe337a2d5 -0, 68, 68, 1, 230400, 0xe775a0c1 -0, 69, 69, 1, 230400, 0x726aab49 -0, 70, 70, 1, 230400, 0x74dda81e +0, 0, 0, 1, 230400, 0x020e46e2 +0, 1, 1, 1, 230400, 0x2e5b3ece +0, 2, 2, 1, 230400, 0xc2a8456d +0, 3, 3, 1, 230400, 0xd91341d5 +0, 4, 4, 1, 230400, 0xf46a3f61 +0, 5, 5, 1, 230400, 0x9ef53c6e +0, 6, 6, 1, 230400, 0xe5803ec3 +0, 7, 7, 1, 230400, 0xb6f6f233 +0, 8, 8, 1, 230400, 0x2f84f2af +0, 9, 9, 1, 230400, 0x690bf214 +0, 10, 10, 1, 230400, 0x358531c8 +0, 11, 11, 1, 230400, 0x5f8a3093 +0, 12, 12, 1, 230400, 0x1a17321d +0, 13, 13, 1, 230400, 0xf088328d +0, 14, 14, 1, 230400, 0x5e2731fe +0, 15, 15, 1, 230400, 0x17e03504 +0, 16, 16, 1, 230400, 0x2fad4ec8 +0, 17, 17, 1, 230400, 0x6a514ce8 +0, 18, 18, 1, 230400, 0x213c4e3e +0, 19, 19, 1, 230400, 0x520c59b2 +0, 20, 20, 1, 230400, 0x853a583a +0, 21, 21, 1, 230400, 0xdb1456a9 +0, 22, 22, 1, 230400, 0xfe0863eb +0, 23, 23, 1, 230400, 0x57906589 +0, 24, 24, 1, 230400, 0xeb5063f3 +0, 25, 25, 1, 230400, 0x4a1f6338 +0, 26, 26, 1, 230400, 0x46ff6867 +0, 27, 27, 1, 230400, 0x59e2666e +0, 28, 28, 1, 230400, 0x8f22656f +0, 29, 29, 1, 230400, 0x1079673d +0, 30, 30, 1, 230400, 0xbe566ad0 +0, 31, 31, 1, 230400, 0xb5454233 +0, 32, 32, 1, 230400, 0x241a48c2 +0, 33, 33, 1, 230400, 0x16dddaf2 +0, 34, 34, 1, 230400, 0xb2addfae +0, 35, 35, 1, 230400, 0x78ccaeda +0, 36, 36, 1, 230400, 0x3e27ad31 +0, 37, 37, 1, 230400, 0x7384c6b3 +0, 38, 38, 1, 230400, 0xea3ac6a5 +0, 39, 39, 1, 230400, 0x651be84a +0, 40, 40, 1, 230400, 0x46a6d505 +0, 41, 41, 1, 230400, 0xbe48d2fb +0, 42, 42, 1, 230400, 0x6addd4c8 +0, 43, 43, 1, 230400, 0xc6a6b808 +0, 44, 44, 1, 230400, 0xb909b874 +0, 45, 45, 1, 230400, 0xf915b8e8 +0, 46, 46, 1, 230400, 0x467fb903 +0, 47, 47, 1, 230400, 0x7865b875 +0, 48, 48, 1, 230400, 0x1125af18 +0, 49, 49, 1, 230400, 0xf390b5ef +0, 50, 50, 1, 230400, 0xbc76b349 +0, 51, 51, 1, 230400, 0x8426b721 +0, 52, 52, 1, 230400, 0x5b67b444 +0, 53, 53, 1, 230400, 0x4388bb8b +0, 54, 54, 1, 230400, 0xdb06b95d +0, 55, 55, 1, 230400, 0xc192bc26 +0, 56, 56, 1, 230400, 0x2b62b745 +0, 57, 57, 1, 230400, 0x7e3ec04f +0, 58, 58, 1, 230400, 0x4954bdec +0, 59, 59, 1, 230400, 0x988bbe84 +0, 60, 60, 1, 230400, 0xeb6bba83 +0, 61, 61, 1, 230400, 0x5610c02c +0, 62, 62, 1, 230400, 0x7d76cac6 +0, 63, 63, 1, 230400, 0xcfa4c72d +0, 64, 64, 1, 230400, 0x9c7cc904 +0, 65, 65, 1, 230400, 0xdda0c95a +0, 66, 66, 1, 230400, 0xe9c0cc0f +0, 67, 67, 1, 230400, 0x45abbf0d +0, 68, 68, 1, 230400, 0x4a6eb99f +0, 69, 69, 1, 230400, 0x7337c806 +0, 70, 70, 1, 230400, 0xf143c589 From patchwork Sat Nov 5 15:26:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39177 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a05:6a11:561f:b0:33d:fc04:f431 with SMTP id rr31csp1406445pxb; Sat, 5 Nov 2022 08:28:55 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5+qn+472lFZ4CA0JTNBJtnhauhIHOD5krwnKLGwrOA48i2OEQbnm6EX1wDebbQ6SCt0eyv X-Received: by 2002:a05:6402:f24:b0:461:7c77:98c4 with SMTP id i36-20020a0564020f2400b004617c7798c4mr39788526eda.80.1667662135412; Sat, 05 Nov 2022 08:28:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662135; cv=none; d=google.com; s=arc-20160816; b=Hktg3KsL3NztWX9F9BnhDZc06CLkSawNswdHGnHvxqODbXi3ZAZBypcY1KNsfC7mSn dgEeSkKK1c5YbLI/2GbZtiunoFzcj4zxc+oE5NDgrL9lxvUXAkZSB3Zs2P0xXIDI9Dmj JlpId9OUQAk01w7RHwafml1l96XBm6Zst+82wUQU55OL9m/NIPAIjZP8JYnb1STC/c/B jpNlP0Ots9NW6mWPA0h5IrGf61FzL+l5HGn1+OyOE9cFXk5CwrzPryqOVH9H5JFdzQXY fq4waWakSPZK+7MIfTDjhWlJs0CtvbBqCrbsba2mEA0d3K+uSbDAY79z+PjUonlocZK2 qQ2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=7Ig9Fhm7cMuiC8OE10hgE9xuX17x9MJMdxyAvrWEvDc=; b=jyigd+/DRfHkDZdlu/1QqOy5A3h10XjcZaVd4ovaQRg+eU835m2anz+dErUjzzwMSY uknOnOYBNTfxLr9ngjK6ez/1TlXiTQG2fJYMexWXPu+4LHfho03MG/m3MsT6DUtwyYQw 1MBXFKFCwsbwjjzArrtvxOoSoGOedNXlxb76QyddWVsggX+ryomtUWnKAjuHACTKF6/m rarjUKxqj+s/brBeqoFGykXOYYjcW6jFxj2jnJJOUb5kEj1HTCslOKGXCgFfc0YEDU3i xdZMu7pla3o3x9Ghz8D1I4nT61Mt0uYydHEAam6KcrPEGn0q476mD5hG7r2/xVoiHgYS EAKQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=BNaGSENi; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id tc7-20020a1709078d0700b00779c6c57dbfsi2463092ejc.556.2022.11.05.08.28.55; Sat, 05 Nov 2022 08:28:55 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=BNaGSENi; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 021DC68B925; Sat, 5 Nov 2022 17:26:51 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2CDB668B49D for ; Sat, 5 Nov 2022 17:26:38 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xzq+/W+OdRJgfYr6HKIN0fpOk11RD2qajjnTW9l8EXo=; b=BNaGSENilyaqpQbeD1KS/a5Wchjyjdz5iL7glsV6dy3EWUrRU+HmkQgKq2YvVdn5+hpj+t c/p5XBjHkmWhSbK1WcxjR/Ok1Mwzhw5aHlYfzsK9mra8h80UJGGc6AM8xUOEtJITtFlooU JG1VrF7JGGE3rqlub61T8aVWNTbpzpQ= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id be936ecb; Sat, 5 Nov 2022 15:26:22 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:11 +0100 Message-Id: <20221105152617.1809282-10-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 09/15] avfilter/palettegen: average color in linear space X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: EEbiptLD1s+M Content-Length: 2837 sRGB colors are gamma encoded, averaging them naively is incorrect. --- libavfilter/vf_palettegen.c | 18 ++++++++++-------- tests/ref/fate/filter-palettegen-1 | 2 +- tests/ref/fate/filter-palettegen-2 | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index d335ef91e6..00bc323d17 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -30,6 +30,7 @@ #include "libavutil/intreadwrite.h" #include "avfilter.h" #include "internal.h" +#include "palette.h" /* Reference a color and how much it's used */ struct color_ref { @@ -186,21 +187,22 @@ static int get_next_box_id_to_split(PaletteGenContext *s) static uint32_t get_avg_color(struct color_ref * const *refs, const struct range_box *box) { - int i; + int i, r, g, b; const int n = box->len; - uint64_t r = 0, g = 0, b = 0, div = 0; + uint64_t div = 0; + double rf = 0.0, gf = 0.0, bf = 0.0; for (i = 0; i < n; i++) { const struct color_ref *ref = refs[box->start + i]; - r += (ref->color >> 16 & 0xff) * ref->count; - g += (ref->color >> 8 & 0xff) * ref->count; - b += (ref->color & 0xff) * ref->count; + rf += ff_srgb_u8_to_linear_f32(ref->color >> 16 & 0xff) * ref->count; + gf += ff_srgb_u8_to_linear_f32(ref->color >> 8 & 0xff) * ref->count; + bf += ff_srgb_u8_to_linear_f32(ref->color & 0xff) * ref->count; div += ref->count; } - r = r / div; - g = g / div; - b = b / div; + r = ff_linear_f32_to_srgb_u8(rf / div); + g = ff_linear_f32_to_srgb_u8(gf / div); + b = ff_linear_f32_to_srgb_u8(bf / div); return 0xffU<<24 | r<<16 | g<<8 | b; } diff --git a/tests/ref/fate/filter-palettegen-1 b/tests/ref/fate/filter-palettegen-1 index bebfd24e19..df3b714ebb 100644 --- a/tests/ref/fate/filter-palettegen-1 +++ b/tests/ref/fate/filter-palettegen-1 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0x3395ef5a +0, 0, 0, 1, 1024, 0x69ec37aa diff --git a/tests/ref/fate/filter-palettegen-2 b/tests/ref/fate/filter-palettegen-2 index 9abec0fe8e..08320a8359 100644 --- a/tests/ref/fate/filter-palettegen-2 +++ b/tests/ref/fate/filter-palettegen-2 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0x23e072c8 +0, 0, 0, 1, 1024, 0x76078b2e From patchwork Sat Nov 5 15:26:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39171 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085491pzb; Sat, 5 Nov 2022 08:27:47 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5pxwltJVyjlSpqrVw1EeZ/bkrgyyXS0UV1eiNf1rGY2n5cdjJnXI0Nnpkb2RhBdllVxELn X-Received: by 2002:a17:906:8a47:b0:7a3:86dd:d33b with SMTP id gx7-20020a1709068a4700b007a386ddd33bmr40074076ejc.67.1667662067407; Sat, 05 Nov 2022 08:27:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662067; cv=none; d=google.com; s=arc-20160816; b=MkuqslJkT0s3Pf+uv0KoW9fvaeJ56AigznljQBFPV9oNIgqo9tHSVqP46M7aeeC91Z kxzBY7vlpbTS+DIL6EMjmDnxOvrKjIjhEzsOFFLmCyv6amtFQa4AAs2ZXNpcTNFNQ1rv eA7tyGUBfR+eS1yVUK3RPrQOqs9z8Yph40a8HgIDM/S2WenBy2shnT4V2dVsQlJDnDGs 4DuSnHXtRGc6f+wo0R1FaVK51gX0LDvlePJj/Fy1ZgamxKR8IpXVYUQGZcfm6NkDJ6mk ZldD59PFPZ29ccczDVtu8/eqcISZvjRbVU4bqWqNgCVIDyD+oVk5UfTZ+g/0+ySxqfI4 Qd6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=Je5S4FHw0mmdxJ0L2EIt08ozNmDoSzsSyDCU7qUawsQ=; b=mz3pIXvtLxmg8YW6yWJ9hUd3cMmwtgkYBYbb26g0AMfqp0Hc2plIZmU2rl0owa3MJw yRyvLAUNvhLS/t956YujYTaot6GZcO4e8KxgrCbErgHSziZi4ym1b7tceQ326b42UrJG K2pIGhMs9NlTiD/piYnJgtv79UkGRskUVxf+4q/2JjAW9+HHERFewuPT3qkcGSNjDfF4 XYqU1HIxerxylDCOcpe08Ln7u4RZoEJxr1q3p5U8UBTjLZ+8cPyoSN+4UiuO5GAUY/C5 QA9y2zBnMEvXoU4grMk+zWPec9GznZ12/cuUPx664VKJ0wwmP7FKsdggnzeqZN39tkWd kHOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=l66VAmlT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o7-20020a17090608c700b00730aa841c5bsi1878381eje.964.2022.11.05.08.27.46; Sat, 05 Nov 2022 08:27:47 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=l66VAmlT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AB55F68B3E7; Sat, 5 Nov 2022 17:26:43 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 24EC768B3E0 for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1JLpbEYvTNppxpJXLXniUM699Kk7plGGItR7SCcxX60=; b=l66VAmlTEll3UXrlsrfQKuPax0NVVAvwDgcNCcauHz/cK6AAYVKMNok+knpf+y2jOQLOcL 5+CxwNrx1sjvf2APvIG5pzRudNqq53VLDUi5LOsqclh/CSERrSFI2l9ZquheinMvUgJUU8 TOTA4u0qqIaRCcmmG2cehQuKn6Do+j4= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id 4e4ed742; Sat, 5 Nov 2022 15:26:22 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:12 +0100 Message-Id: <20221105152617.1809282-11-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 10/15] avfilter/palettegen: move box variance computation in a dedicated function X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: SgQdnNL77TWz --- libavfilter/vf_palettegen.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 00bc323d17..2b412cdb55 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -144,12 +144,23 @@ 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_variance(PaletteGenContext *s, struct range_box *box) +{ + int64_t variance = 0; + + for (int i = 0; i < box->len; i++) { + const struct color_ref *ref = s->refs[box->start + i]; + variance += diff(ref->color, box->color) * ref->count; + } + box->variance = variance; +} + /** * Find the next box to split: pick the one with the highest variance */ static int get_next_box_id_to_split(PaletteGenContext *s) { - int box_id, i, best_box_id = -1; + int box_id, best_box_id = -1; int64_t max_variance = -1; if (s->nb_boxes == s->max_colors - s->reserve_transparent) @@ -159,16 +170,8 @@ static int get_next_box_id_to_split(PaletteGenContext *s) struct range_box *box = &s->boxes[box_id]; if (s->boxes[box_id].len >= 2) { - - if (box->variance == -1) { - int64_t variance = 0; - - for (i = 0; i < box->len; i++) { - const struct color_ref *ref = s->refs[box->start + i]; - variance += diff(ref->color, box->color) * ref->count; - } - box->variance = variance; - } + if (box->variance == -1) + compute_box_variance(s, box); if (box->variance > max_variance) { best_box_id = box_id; max_variance = box->variance; From patchwork Sat Nov 5 15:26:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39174 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085795pzb; Sat, 5 Nov 2022 08:28:14 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4tkwKni68LGTDizXUq+xYFhRBBGtBdZ2DYdfyDlq5z4bcHbvmUV3wupoNbGq2GTsc1QOjt X-Received: by 2002:a05:6402:5187:b0:461:ac01:7512 with SMTP id q7-20020a056402518700b00461ac017512mr40644760edd.327.1667662094189; Sat, 05 Nov 2022 08:28:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662094; cv=none; d=google.com; s=arc-20160816; b=b1uLw5+tA3V2CeAtXdoR7yrPPirhoPiEvC10gvxlNEPTzeREsCkEkc9sqEzmSbWSIX uubnxqkvdc80jui8Cfw5cFwyPYaoElgp1qFOJNFqzzZ3bX3ae2UllB4bc5fiKPcFkFTb rP+nfoTq3RY3uwop1JftMpWU8eKQ8lGUjcbtZbTUmFwlCZT/gmqHCfqns4Ds5F167afe 3f3TjStnZpPZkKQrxp8ID+sPOUujg6osmo/K8doNnwphaaV6fBy+OjBfCaW546+dbLLl mkwmmNcfuEIUXzwBXT1igpIoc6rPmqgoSTrP0vnhRQ7Q+vB87eaEcb7kmcM6VUgkWkxF XTqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=plOhObQPp3XbCXdA4wXh1rbNxeGCvnN7LSsVrd+HisU=; b=zLIHjU3SilJQfwnSjzTkAv+HZMHxsZ8TEoxphUSPKgWpcmas0VN8/I+hEmD97ORMQZ JUbMgBXmb/REb8xjT3FeUWaZ2Ea+qbsYvOC+NCR1NaCCgRfTshrWRlF8V8yxAo+8ga+8 DqX8kspgCnyFLYuyHdMN6Ci6N07FOXW3v+orQMqqxuwx82XtoaCHAbsW5TA1miEfNhJA +BNP6ftGB+BqroZfKGli21SRzc6iqznsjw55R6s/Wy6l5XVa6/FiqejWbPjlGPsl71JT t4XcFer3DVJnoXxeimliT3DrWSqLejxNeJEOHVx9aobN8Ov85rf2LTbZRy+MVLbRoEPS EIKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=X6x1gqUj; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b8-20020a056402278800b0045928479b71si3731361ede.405.2022.11.05.08.28.13; Sat, 05 Nov 2022 08:28:14 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=X6x1gqUj; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 873E468B663; Sat, 5 Nov 2022 17:26:46 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4DD5A68B3E7 for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=n1OyaAQq87iiEE2XLvuqG94Vopy9hh+rhmOfKdxlAxA=; b=X6x1gqUjSpI3mCUa1Qp42jvBG7NMSNswP7OxudmHsE3wqdv4iiDeK56W15Q9ou/kQLohl1 YSXDHry4WCOjcWVgtnvhNd3wduR0Cl+mK6j/06ZyPl/REIfLjdaK1q/GFb8bNSTNUPEcLr oC9zk5yPTyBcGiQ22NfVVMoXzKFTY7M= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id 66408e5d; Sat, 5 Nov 2022 15:26:22 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:13 +0100 Message-Id: <20221105152617.1809282-12-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 11/15] avfilter/palettegen: comment on the unnormalized variance X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: P10qLMo01PzD --- libavfilter/vf_palettegen.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 2b412cdb55..b8e4463539 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -152,6 +152,24 @@ static void compute_box_variance(PaletteGenContext *s, struct range_box *box) const struct color_ref *ref = s->refs[box->start + i]; variance += diff(ref->color, box->color) * ref->count; } + /* + * The variance is computed as a Mean Squared Error of the distance of the + * current color to the box color average, with an important difference: + * the final sum is not normalized using the total weight of the box (the + * sum of the ref->count). + * + * One may expect that in order to compare the variance of the boxes + * between each others a normalization makes sense. Unfortunately, the + * normalization has the side effect of taking the "size" of the box out of + * the equation. In practice, this has a tendency to cause dramatic banding + * effects (in particular without dithering). Typically a scene where the + * sky is omnipresent may get much less colors assigned than its + * surroundings. + * + * Not normalizing causes a bias towards boxes with many colors, but that's + * exactly what we want. The downside is that vivid/accent colors found in + * small quantities tend to disappear. + */ box->variance = variance; } From patchwork Sat Nov 5 15:26:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39173 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085686pzb; Sat, 5 Nov 2022 08:28:04 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7HwGPQ6g8jQ8sX1DJhAqBHwr3wnC7Qqqf6JsNeuagy/UIxCBaglOdyAWU0DTRT4h5Aerrg X-Received: by 2002:a17:907:7e95:b0:78d:e9cf:82c7 with SMTP id qb21-20020a1709077e9500b0078de9cf82c7mr41006250ejc.724.1667662084682; Sat, 05 Nov 2022 08:28:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662084; cv=none; d=google.com; s=arc-20160816; b=gWHI1dDOastW/uRP8w9CKTX8gL35PRv1BNkpZlotPJHu9kAMCbqwrE8KDpGAVR0n/Q ObLQxpoBQHDYzS8F89c1K5hM6Y/xgdYXEM/mCDatPKW98iNYR1Z4ke7VfqR9tr1QSWtx oe3ob4+7CwCJhvWWe0RnCJSWmNBWvPGqf99F3SAj8ozjFaJIB0NquV0X4exVz2ZYKndl X79UvcMQNM4gty9Q3q8hNJANVl+k+seKcvtZZy8JZafSZtEywnxIM5FhTaiEhlkH0szm /zDRjNDCg6rKEO50XIHFXMNRfZYqzZ/Ryo+GtMIu4E3TDsTL1m6tzrpt/s8X+XXarAMv oygw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=96vTgnOkEmt8PbF8i664h8QiEshtakrBEwUqkL8HSSQ=; b=yzaYM4IeUhSX9ZsQzzZNf4AKZ6Z9IjjuJ967bGYK9oDzXe+D7rRSXybTAA1oA9MuBu RKWScjh8bC53n+lksX2S5ErmV2oEcP8j3Q8zDDEJZh8UFRsP/76EIWg7MYMj+5JOnK5W VwS5YethBo3xoCeOovl+gsOiNsWFIwKwcz3K0s3iVeJA4XGdCCfytvYAgkSF9kiZGwP4 W8e0u+mDt65VZ9E093WqzFvk1mECcYOH6FZ+l2piW7i3BbABJQlGoc1sP6YlfjF2bpOF IibBbYldljL35MzYFg1EHjBLDq5hsXzZYj/xhp+W3XREgP3XOYeivrmkz17b98Xsphay ihkQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=PO8TAcsW; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k24-20020aa7d2d8000000b004646bcdd9f9si2470879edr.486.2022.11.05.08.28.04; Sat, 05 Nov 2022 08:28:04 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=PO8TAcsW; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9084F68B371; Sat, 5 Nov 2022 17:26:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 506FF68B469 for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QN0jTJzp3X7b8KCMHO0OIGFUbzN9O4j4GCOluwq6RvQ=; b=PO8TAcsW8HmrBiEGZESSwykJ/7XSHLBvhNLmlydIEgN48U4VXr+9ZI0VtIhVx0gYXcmNsy GRWujYQTR7NMRLa89OagzG74uFJtDyD59iijGh+54R2Rt1LS9JwTBo8M6Zy7VBaIiOm47N BNZ4zr0v5CnT6NQnVm2RKUdcIxVqRzM= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id f512bc37; Sat, 5 Nov 2022 15:26:22 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:14 +0100 Message-Id: <20221105152617.1809282-13-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 12/15] avfilter/palettegen: base split decision on a perceptual model X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8Cu/Rg7CCG02 Similar to the change in paletteuse, we rely on a perceptual model to decide how and where to split the box. --- libavfilter/Makefile | 2 +- libavfilter/vf_palettegen.c | 79 ++++++++++++++++-------------- tests/ref/fate/filter-palettegen-1 | 2 +- tests/ref/fate/filter-palettegen-2 | 2 +- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index e6b6d59d2d..0a31b76c6a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -401,7 +401,7 @@ OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.o vul OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PAD_OPENCL_FILTER) += vf_pad_opencl.o opencl.o opencl/pad.o -OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o +OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o palette.o OBJS-$(CONFIG_PALETTEUSE_FILTER) += vf_paletteuse.o framesync.o palette.o OBJS-$(CONFIG_PERMS_FILTER) += f_perms.o OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index b8e4463539..4c2bcba7f7 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -23,6 +23,8 @@ * Generate one palette for a whole video stream. */ +#include + #include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -35,13 +37,14 @@ /* Reference a color and how much it's used */ struct color_ref { uint32_t color; + struct Lab lab; uint64_t count; }; /* Store a range of colors */ struct range_box { uint32_t color; // average color - int64_t variance; // overall variance of the box (how much the colors are spread) + double variance; // overall variance of the box (how much the colors are spread) int start; // index in PaletteGenContext->refs int len; // number of referenced colors int sorted_by; // whether range of colors is sorted by red (0), green (1) or blue (2) @@ -109,20 +112,19 @@ static int query_formats(AVFilterContext *ctx) typedef int (*cmp_func)(const void *, const void *); -#define DECLARE_CMP_FUNC(name, pos) \ +#define DECLARE_CMP_FUNC(name) \ static int cmp_##name(const void *pa, const void *pb) \ { \ const struct color_ref * const *a = pa; \ const struct color_ref * const *b = pb; \ - return (int)((*a)->color >> (8 * (2 - (pos))) & 0xff) \ - - (int)((*b)->color >> (8 * (2 - (pos))) & 0xff); \ + return FFDIFFSIGN((*a)->lab.name, (*b)->lab.name); \ } -DECLARE_CMP_FUNC(r, 0) -DECLARE_CMP_FUNC(g, 1) -DECLARE_CMP_FUNC(b, 2) +DECLARE_CMP_FUNC(L) +DECLARE_CMP_FUNC(a) +DECLARE_CMP_FUNC(b) -static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; +static const cmp_func cmp_funcs[] = {cmp_L, cmp_a, cmp_b}; /** * Simple color comparison for sorting the final palette @@ -134,19 +136,19 @@ static int cmp_color(const void *a, const void *b) return FFDIFFSIGN(box1->color , box2->color); } -static av_always_inline int diff(const uint32_t a, const uint32_t b) +static av_always_inline float diff(const uint32_t a, const uint32_t b) { - const uint8_t c1[] = {a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff}; - const uint8_t c2[] = {b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff}; - const int dr = c1[0] - c2[0]; - const int dg = c1[1] - c2[1]; - const int db = c1[2] - c2[2]; - return dr*dr + dg*dg + db*db; + const struct Lab lab0 = ff_srgb_u8_to_oklab(a); + const struct Lab lab1 = ff_srgb_u8_to_oklab(b); + const float dL = lab0.L - lab1.L; + const float da = lab0.a - lab1.a; + const float db = lab0.b - lab1.b; + return dL*dL + da*da + db*db; } static void compute_box_variance(PaletteGenContext *s, struct range_box *box) { - int64_t variance = 0; + double variance = 0.0; for (int i = 0; i < box->len; i++) { const struct color_ref *ref = s->refs[box->start + i]; @@ -179,7 +181,7 @@ static void compute_box_variance(PaletteGenContext *s, struct range_box *box) static int get_next_box_id_to_split(PaletteGenContext *s) { int box_id, best_box_id = -1; - int64_t max_variance = -1; + double max_variance = -1.0; if (s->nb_boxes == s->max_colors - s->reserve_transparent) return -1; @@ -188,14 +190,14 @@ static int get_next_box_id_to_split(PaletteGenContext *s) struct range_box *box = &s->boxes[box_id]; if (s->boxes[box_id].len >= 2) { - if (box->variance == -1) + if (box->variance == -1.0) compute_box_variance(s, box); if (box->variance > max_variance) { best_box_id = box_id; max_variance = box->variance; } } else { - box->variance = -1; + box->variance = -1.0; } } return best_box_id; @@ -245,8 +247,8 @@ static void split_box(PaletteGenContext *s, struct range_box *box, int n) box->color = get_avg_color(s->refs, box); new_box->color = get_avg_color(s->refs, new_box); - box->variance = -1; - new_box->variance = -1; + box->variance = -1.0; + new_box->variance = -1.0; } /** @@ -343,39 +345,39 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) box->len = s->nb_refs; box->sorted_by = -1; box->color = get_avg_color(s->refs, box); - box->variance = -1; + box->variance = -1.0; s->nb_boxes = 1; while (box && box->len > 1) { - int i, rr, gr, br, longest; + int i, longest; + double Lr, ar, br; uint64_t median, box_weight = 0; /* 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}; + float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}; + float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; 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]); + const struct Lab lab = ref->lab; + min[0] = FFMIN(lab.L, min[0]), max[0] = FFMAX(lab.L, max[0]); + min[1] = FFMIN(lab.a, min[1]), max[1] = FFMAX(lab.a, max[1]); + min[2] = FFMIN(lab.b, min[2]), max[2] = FFMAX(lab.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]; + Lr = max[0] - min[0]; + ar = 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 + longest = 0; + if (br >= Lr && br >= ar) longest = 2; + if (ar >= Lr && ar >= br) longest = 1; + if (Lr >= ar && Lr >= br) longest = 0; - 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" ranges:[%.3f %.3f %.3f] 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'); + Lr, ar, br, "Lab"[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) { @@ -449,6 +451,7 @@ static int color_inc(struct hist_node *hist, uint32_t color) if (!e) return AVERROR(ENOMEM); e->color = color; + e->lab = ff_srgb_u8_to_oklab(color); e->count = 1; return 1; } diff --git a/tests/ref/fate/filter-palettegen-1 b/tests/ref/fate/filter-palettegen-1 index df3b714ebb..7b7ce98b76 100644 --- a/tests/ref/fate/filter-palettegen-1 +++ b/tests/ref/fate/filter-palettegen-1 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0x69ec37aa +0, 0, 0, 1, 1024, 0xf1fb64c1 diff --git a/tests/ref/fate/filter-palettegen-2 b/tests/ref/fate/filter-palettegen-2 index 08320a8359..b856a79273 100644 --- a/tests/ref/fate/filter-palettegen-2 +++ b/tests/ref/fate/filter-palettegen-2 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0x76078b2e +0, 0, 0, 1, 1024, 0xe84a671a From patchwork Sat Nov 5 15:26:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39176 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1085996pzb; Sat, 5 Nov 2022 08:28:33 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6EngKjriBl+Wo9wlSgxbbjj4CAmMlqsy9gfZlTYMS3KQu/T+ExQtLBn45QXE8UtFCyEjR4 X-Received: by 2002:a17:907:a067:b0:7a7:dc5e:eb2d with SMTP id ia7-20020a170907a06700b007a7dc5eeb2dmr40561074ejc.121.1667662113104; Sat, 05 Nov 2022 08:28:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662113; cv=none; d=google.com; s=arc-20160816; b=imeFZLh2iMGmHz7ryFCxOnBCJI/TdFjYOszlJmcI29BLOV5nAZbNkwy4tY7iUyI02/ ob7xizgMW3FcXtD6XIM89BMxzgrwZQZRV9YC8RbzM5MFLzm3Gu4zkQgU7vukhP6Ohso4 t5Bg7XolgFGiqddCZTnGlJ92Tbda3hcCO6592bDS9SmKQ+aoPBP31QE+EzRFFE6yOxbw Z0j4/pov4DeQDBmuehOlHNVMEgWH50g21+5Nljk7Cwa6mqQ1iueF+yWXyzEwRU0HaAgA xuQ077s2dP3chMB1O1r3u6h0R0niqGk+PqPQHOouJ07BOmBr9j36ta/RNj8HCANffXnd vnNQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=1OGgb8mThABwEImI6g3/dzoChvohydhgNohxRVrvaU8=; b=dcnzsVxKdH1MUqc9j2OjzzWeuiWp0d38DPaSI8iY4N/jHZDHbxD/xu8qUFv8VYUlfP Q+DSh/6JvY6WofNBXETmg1TjdeGq+hNEv88pEOM20ZoMpTUk1BhtxH7amhUcOVb/UOkb q73GLwniAflb4M2FcDOdr63AObPmywi2yHY6Hh+x0itSKF1TZuw4lgTYZxRX2wCUCWXO XnYzacSeVzGZ8tuNSDQ4hk+o0TUypHHYPgfvU7akUh+p55K1VaI+HI58SQFsWYcmqtUE qCl/N7YhIq9mjR0+TnnmW7XpCA98zx4g2wuBRkWIcPBG2Osh3gDwoiXHogbYoNNTVODr apmw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=RgzT+JT2; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dm20-20020a170907949400b00782ff2649a7si2811554ejc.346.2022.11.05.08.28.32; Sat, 05 Nov 2022 08:28:33 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=RgzT+JT2; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 77DA668B7F5; Sat, 5 Nov 2022 17:26:48 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 79D4D68B259 for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LnKLbzk+vBnDYFl2ImkRKFHFAFJ5wkfWkEZmq9hHnQk=; b=RgzT+JT2NeRtNlGOM8DBfj/cprt+MlzkRzrnVt8JP3/wsSjgiqnBmoxmtgElPL2F1uYW4j a+nbHV52wkoTxcW3N1K3Qdks5eVSH86jH2z7wk5+jJrbC6wu4WpcdeFsZYOHmraL2MeJ8M 0GRD0G/GgydVct++5h2/K9Vv6qtwe9Q= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id 279a3559; Sat, 5 Nov 2022 15:26:23 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:15 +0100 Message-Id: <20221105152617.1809282-14-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 13/15] avfilter/palettegen: use variance per-axis instead of the range X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8YyHYN92RRZI The split decision is now based on the per-axis variance instead of how wide they are. --- libavfilter/vf_palettegen.c | 61 ++++++++++++++++-------------- tests/ref/fate/filter-palettegen-1 | 2 +- tests/ref/fate/filter-palettegen-2 | 2 +- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 4c2bcba7f7..2976012512 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -45,6 +45,7 @@ struct color_ref { struct range_box { uint32_t color; // average color double variance; // overall variance of the box (how much the colors are spread) + double axis_variance[3]; // axis specific variance int start; // index in PaletteGenContext->refs int len; // number of referenced colors int sorted_by; // whether range of colors is sorted by red (0), green (1) or blue (2) @@ -136,24 +137,29 @@ static int cmp_color(const void *a, const void *b) return FFDIFFSIGN(box1->color , box2->color); } -static av_always_inline float diff(const uint32_t a, const uint32_t b) -{ - const struct Lab lab0 = ff_srgb_u8_to_oklab(a); - const struct Lab lab1 = ff_srgb_u8_to_oklab(b); - const float dL = lab0.L - lab1.L; - const float da = lab0.a - lab1.a; - const float db = lab0.b - lab1.b; - return dL*dL + da*da + db*db; -} - static void compute_box_variance(PaletteGenContext *s, struct range_box *box) { double variance = 0.0; for (int i = 0; i < box->len; i++) { const struct color_ref *ref = s->refs[box->start + i]; - variance += diff(ref->color, box->color) * ref->count; + const struct Lab lab0 = ff_srgb_u8_to_oklab(ref->color); + const struct Lab lab1 = ff_srgb_u8_to_oklab(box->color); + const float dL = lab0.L - lab1.L; + const float da = lab0.a - lab1.a; + const float db = lab0.b - lab1.b; + + variance += (dL*dL + da*da + db*db) * ref->count; + + /* + * No need to normalize the per-axis variances since they are compared + * only locally within the box and thus share the same weight. + */ + box->axis_variance[0] += dL*dL * ref->count; + box->axis_variance[1] += da*da * ref->count; + box->axis_variance[2] += db*db * ref->count; } + /* * The variance is computed as a Mean Squared Error of the distance of the * current color to the box color average, with an important difference: @@ -198,6 +204,7 @@ static int get_next_box_id_to_split(PaletteGenContext *s) } } else { box->variance = -1.0; + memset(box->axis_variance, 0, sizeof(box->axis_variance)); } } return best_box_id; @@ -249,6 +256,8 @@ static void split_box(PaletteGenContext *s, struct range_box *box, int n) new_box->color = get_avg_color(s->refs, new_box); box->variance = -1.0; new_box->variance = -1.0; + memset(box->axis_variance, 0, sizeof(box->axis_variance)); + memset(new_box->axis_variance, 0, sizeof(new_box->axis_variance)); } /** @@ -346,38 +355,34 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) box->sorted_by = -1; box->color = get_avg_color(s->refs, box); box->variance = -1.0; + memset(box->axis_variance, 0, sizeof(box->axis_variance)); + compute_box_variance(s, box); s->nb_boxes = 1; while (box && box->len > 1) { int i, longest; - double Lr, ar, br; + double Lv, av, bv; uint64_t median, box_weight = 0; /* compute the box weight (sum all the weights of the colors in the - * range) and its boundings */ - float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}; - float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; + * range) */ for (i = box->start; i < box->start + box->len; i++) { const struct color_ref *ref = s->refs[i]; - const struct Lab lab = ref->lab; - min[0] = FFMIN(lab.L, min[0]), max[0] = FFMAX(lab.L, max[0]); - min[1] = FFMIN(lab.a, min[1]), max[1] = FFMAX(lab.a, max[1]); - min[2] = FFMIN(lab.b, min[2]), max[2] = FFMAX(lab.b, max[2]); box_weight += ref->count; } - /* define the axis to sort by according to the widest range of colors */ - Lr = max[0] - min[0]; - ar = max[1] - min[1]; - br = max[2] - min[2]; + /* pick the axis with the biggest variance */ + Lv = box->axis_variance[0]; + av = box->axis_variance[1]; + bv = box->axis_variance[2]; longest = 0; - if (br >= Lr && br >= ar) longest = 2; - if (ar >= Lr && ar >= br) longest = 1; - if (Lr >= ar && Lr >= br) longest = 0; + if (bv >= Lv && bv >= av) longest = 2; + if (av >= Lv && av >= bv) longest = 1; + if (Lv >= av && Lv >= bv) longest = 0; - ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" ranges:[%.3f %.3f %.3f] sort by %c (already sorted:%c) ", + ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" var:[%.3f %.3f %.3f] sort by %c (already sorted:%c) ", box_id, box->start, box->start + box->len - 1, box->len, box_weight, - Lr, ar, br, "Lab"[longest], box->sorted_by == longest ? 'y':'n'); + Lv, av, bv, "Lab"[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) { diff --git a/tests/ref/fate/filter-palettegen-1 b/tests/ref/fate/filter-palettegen-1 index 7b7ce98b76..35730a659f 100644 --- a/tests/ref/fate/filter-palettegen-1 +++ b/tests/ref/fate/filter-palettegen-1 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0xf1fb64c1 +0, 0, 0, 1, 1024, 0xd8fd2c22 diff --git a/tests/ref/fate/filter-palettegen-2 b/tests/ref/fate/filter-palettegen-2 index b856a79273..548902fed0 100644 --- a/tests/ref/fate/filter-palettegen-2 +++ b/tests/ref/fate/filter-palettegen-2 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x16 #sar 0: 1/1 -0, 0, 0, 1, 1024, 0xe84a671a +0, 0, 0, 1, 1024, 0xd1f29072 From patchwork Sat Nov 5 15:26:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39178 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a05:6a11:561f:b0:33d:fc04:f431 with SMTP id rr31csp1406317pxb; Sat, 5 Nov 2022 08:28:39 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5FtYxr3kLCLYXLVE057AoKiRFL2YFuSNaXVxx1MSm2huQFos1grAGi1fgiNI8P9cKZf72e X-Received: by 2002:a17:907:7e9b:b0:7ad:c003:78a3 with SMTP id qb27-20020a1709077e9b00b007adc00378a3mr35587366ejc.342.1667662119611; Sat, 05 Nov 2022 08:28:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662119; cv=none; d=google.com; s=arc-20160816; b=XOQ0Jv/sz3FQMDa54e+ciEmwVK44Z7bPOW+K2jD9xWU/NZAl9I88+gQi57aEKqztVJ zJD/mEjpO6XLcya8p6b8GHVc0VlHlpUn8secsE//pvKS3emsBSWY+haqVA0vg9uQGgg9 sN4t4buV+Tdja/C+L74abJC6s1yni53Nf+9OjA+bIFtm5JP/MRWqPFhIVlwNjVEejEc+ lPJyqL1Si6iQz0Myq3AbPAdDQMiFsnheGsBoj5Onh91mw1vLU28Hei4bHsAKDQ+b/nO4 lArlB3BC6Hldj/3U19CAhJDEk0s3NzOqe5FSWAJZDeqH8ScphyKQ2aJth6lxrBZOLo2a Q5NA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=S7YfoCMtWV8o/H4zW+ecBwOFzjSR/ZJIjx4hz/vcJ4I=; b=ew+sJK6l1r00/2j5nSSJ1qcFleVND0sZ8SWK3MXTAxG/1LWlhdCWNoyrVBifZR5QZP mCD1La4HM/iAvrHrAxGP8Ju4yMEL29kBpR6OUbn7fEkT2JIaIbKQU7FGtx6V9TEbOXag P6h2ORQnC3J4A5v7QtNK+CEu+bFqrykWwZw7Rgup3Mxz/n7jtqxFTs17gxJda1m0pAOc kY3Z/KNcm3e6va4WKzHQdnAvA+n5VkBiFUSCEnNneX+aOvyUfp1d3z//OPOY9kniXkTG V/iQfE9nMBQQKPvbCB2C6HboKc8iSTIsdoIN2prSjUNSmA4gz9aqYUg6CKQV3ZsYnmOH 5e9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=YL9HY+oq; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hz5-20020a1709072ce500b0078c9dd279b6si2524646ejc.345.2022.11.05.08.28.39; Sat, 05 Nov 2022 08:28:39 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=YL9HY+oq; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2A3AA68B83A; Sat, 5 Nov 2022 17:26:49 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 824A868B4BB for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NwZfvrBilWpFfUhEOzve9x5SFeWbMCPVdq3yWFen5uQ=; b=YL9HY+oqFkzdFBxLJ35LzISYPBfiPIQl5RjG4ORbwbY+QwQs3m7MpKqqVPOFktkL5pZjLV UxOCspvif+Jy5mrflG3qnQhtfUIHA2bqPcxO1YfoqMaZZpbsM1ZZwBwCzRqA80XlqkKeAj UJ7BbvG54Eh9P5EliEunZirLTW+DZLw= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id f925775e; Sat, 5 Nov 2022 15:26:23 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:16 +0100 Message-Id: <20221105152617.1809282-15-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 14/15] avfilter/palettegen: rename longest to split_axis X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 7exgHcgpV7FT Content-Length: 2370 The split heuristic is not based on the length property of the axis anymore. --- libavfilter/vf_palettegen.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 2976012512..9d537f8f37 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -360,7 +360,7 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) s->nb_boxes = 1; while (box && box->len > 1) { - int i, longest; + int i, split_axis; double Lv, av, bv; uint64_t median, box_weight = 0; @@ -375,20 +375,20 @@ static AVFrame *get_palette_frame(AVFilterContext *ctx) Lv = box->axis_variance[0]; av = box->axis_variance[1]; bv = box->axis_variance[2]; - longest = 0; - if (bv >= Lv && bv >= av) longest = 2; - if (av >= Lv && av >= bv) longest = 1; - if (Lv >= av && Lv >= bv) longest = 0; + split_axis = 0; + if (bv >= Lv && bv >= av) split_axis = 2; + if (av >= Lv && av >= bv) split_axis = 1; + if (Lv >= av && Lv >= bv) split_axis = 0; ff_dlog(ctx, "box #%02X [%6d..%-6d] (%6d) w:%-6"PRIu64" var:[%.3f %.3f %.3f] sort by %c (already sorted:%c) ", box_id, box->start, box->start + box->len - 1, box->len, box_weight, - Lv, av, bv, "Lab"[longest], box->sorted_by == longest ? 'y':'n'); + Lv, av, bv, "Lab"[split_axis], box->sorted_by == split_axis ? 'y':'n'); - /* sort the range by its longest axis if it's not already sorted */ - if (box->sorted_by != longest) { - cmp_func cmpf = cmp_funcs[longest]; + /* sort the range by its split axis if it's not already sorted */ + if (box->sorted_by != split_axis) { + cmp_func cmpf = cmp_funcs[split_axis]; AV_QSORT(&s->refs[box->start], box->len, const struct color_ref *, cmpf); - box->sorted_by = longest; + box->sorted_by = split_axis; } /* locate the median where to split */ From patchwork Sat Nov 5 15:26:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 39179 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a05:6a11:561f:b0:33d:fc04:f431 with SMTP id rr31csp1406416pxb; Sat, 5 Nov 2022 08:28:50 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6LUOuFyOX1kQu73b1O6urWqOeJYfQdwcv0TNhwf1mNoh2khRI3hBuYauXnJCjZWPqxqxXP X-Received: by 2002:a05:6402:34cd:b0:462:5382:c3a9 with SMTP id w13-20020a05640234cd00b004625382c3a9mr41205555edc.298.1667662130182; Sat, 05 Nov 2022 08:28:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667662130; cv=none; d=google.com; s=arc-20160816; b=03faCbhqWYZ31vlMSimW/pIz8jwy7hSflAuc8ZRfsA2TR0n7AZkQCyDEGGyPX/W689 QNk5efjUci3JFwhh7WkJ4ybB6fcQ5BVIlWchT0VOA0AQFTGR3ZYVlS9SK7x0soEkTX14 V2xtGrHkdciM5astSDCUIRX1aTytF4u5CA+mSY1dIIfQvbdbwdNsspvjLTZ/PioF+hpv xBWWeRsZaKNoCtTEFzysQv6fCcIpobn3Z6gTv+Rryd7RtPlTAyHJbOboZt+NanaoAWGB yFEzzaCPnzUAeuXOkgauAnfy2zJlrt2V8WdC9WVaixFFSVXNZPSCwCK8YXCE9j8uZkTY KHhw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=t2MYWYMmLp2QtpZk+DIAJDduI62/ui7x+d7KPMpZocc=; b=WdHuK3XKjzTNI/Uesyg0fPPPR/Oml++wg0uobw/pCibHoHp7LENebhcqaMm9+gmB0e HVF0SEpkt2gta0FJu7HB5Kr0xW+UEg72+KtQpqSQC/6LFKC4+3KwfERf28YZVSWProOA HDCCeprBwe95blwj4lBC2dwbdvCW4HPZAzqO1fSGdmGGJUpF4RIO3qbXbKql1R6Tpz+M WhzgqOSk3SQEObWf6RThMF9e+wpTTccXpYp8zoU0ztX15s7uS6viEIvBBfEn7izJTOqf onale7Snb+6ygaPg1aHUF8l2OEyWo4ZuXx3jqzNeXHU/JxmoO3ag0Rnh2RWd6hoSPe+K W6tw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=Hz1kFaPN; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id sg32-20020a170907a42000b0078d9d69ae0dsi2589757ejc.877.2022.11.05.08.28.49; Sat, 05 Nov 2022 08:28:50 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@pkh.me header.s=selector1 header.b=Hz1kFaPN; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=pkh.me Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 841A668B8D0; Sat, 5 Nov 2022 17:26:50 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ssq0.pkh.me (laubervilliers-656-1-228-164.w92-154.abo.wanadoo.fr [92.154.28.164]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9E02368B3E7 for ; Sat, 5 Nov 2022 17:26:41 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pkh.me; s=selector1; t=1667661983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=h2aQGHq7uKGTUKgO2SfvD44YwBauHUNj3gV8PDkrlFA=; b=Hz1kFaPNvTRg8tmGztqSZ63vTUms7mKe9ZtFNVPPDu257Pw79g8TcjSLkWY+Xj1adLE2Nu CntoOtMazEJJBfmvDUrPMccKWqe1XoSu0gEZzUOp7kOOA9ZhjEdkyxs1AuX7Ca8RKNzMxP aEblqxDZ1kd9iorxN4AR/yIW7xz5tPU= Received: from localhost (ssq0.pkh.me [local]) by ssq0.pkh.me (OpenSMTPD) with ESMTPA id ed1a7a8b; Sat, 5 Nov 2022 15:26:23 +0000 (UTC) From: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Nov 2022 16:26:17 +0100 Message-Id: <20221105152617.1809282-16-u@pkh.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221105152617.1809282-1-u@pkh.me> References: <20221105152617.1809282-1-u@pkh.me> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 15/15] avfilter/palette{use, gen}: update Copyright after recent changes X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: R5mbyoLvGEe8 Content-Length: 1366 --- libavfilter/vf_palettegen.c | 1 + libavfilter/vf_paletteuse.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 9d537f8f37..cba44d1fbf 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Stupeflix + * Copyright (c) 2022 Clément Bœsch * * This file is part of FFmpeg. * diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 7c64a63722..e2b02612ca 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Stupeflix + * Copyright (c) 2022 Clément Bœsch * * This file is part of FFmpeg. *