diff mbox series

[FFmpeg-devel,09/15] avfilter/palettegen: average color in linear space

Message ID 20221105152617.1809282-10-u@pkh.me
State New
Headers show
Series [FFmpeg-devel,01/15] Revert "avfilter/vf_palette(gen|use): support palettes with alpha" | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Clément Bœsch Nov. 5, 2022, 3:26 p.m. UTC
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(-)

Comments

Clément Bœsch Nov. 5, 2022, 6:50 p.m. UTC | #1
On Sat, Nov 05, 2022 at 04:39:26PM +0100, Paul B Mahol wrote:
> On 11/5/22, Clément Bœsch <u@pkh.me> wrote:
> > 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(-)
> >
> 
> Compared speed of processing of before and after?

Definitely slower:

Before:

  palettegen:
    Time (mean ± σ):      2.700 s ±  0.022 s    [User: 2.926 s, System: 0.080 s]
    Range (min … max):    2.674 s …  2.736 s    10 runs
  
  paletteuse:
    Time (mean ± σ):      2.315 s ±  0.036 s    [User: 2.566 s, System: 0.089 s]
    Range (min … max):    2.281 s …  2.400 s    10 runs

After:

  palettegen:
    Time (mean ± σ):      3.839 s ±  0.030 s    [User: 4.076 s, System: 0.070 s]
    Range (min … max):    3.788 s …  3.894 s    10 runs
  
  paletteuse:
    Time (mean ± σ):      2.850 s ±  0.040 s    [User: 3.094 s, System: 0.110 s]
    Range (min … max):    2.805 s …  2.954 s    10 runs
diff mbox series

Patch

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