diff mbox series

[FFmpeg-devel,3/4] avfilter/paletteuse: add atkinson dithering

Message ID 20221230113455.2632289-4-u@pkh.me
State Accepted
Commit 68275043a06c532dc573957884186e26637d6c40
Headers show
Series [FFmpeg-devel,1/4] avfilter/paletteuse: add sierra3 dithering | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Clément Bœsch Dec. 30, 2022, 11:34 a.m. UTC
Atkinson according to
https://bisqwit.iki.fi/jutut/kuvat/ordered_dither/error_diffusion.txt:

        *   1   1    / 8
    1   1   1
        1
---
 doc/filters.texi            |  2 ++
 libavfilter/vf_paletteuse.c | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)
diff mbox series

Patch

diff --git a/doc/filters.texi b/doc/filters.texi
index 16a8dde4f3..2672ae6ee7 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -18520,6 +18520,8 @@  Frankie Sierra dithering v2 "Lite" (error diffusion)
 Frankie Sierra dithering v3 (error diffusion)
 @item burkes
 Burkes dithering (error diffusion)
+@item atkinson
+Atkinson dithering by Bill Atkinson at Apple Computer (error diffusion)
 @end table
 
 Default is @var{sierra2_4a}.
diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c
index 3c3b6b3ef8..252ad746f0 100644
--- a/libavfilter/vf_paletteuse.c
+++ b/libavfilter/vf_paletteuse.c
@@ -44,6 +44,7 @@  enum dithering_mode {
     DITHERING_SIERRA2_4A,
     DITHERING_SIERRA3,
     DITHERING_BURKES,
+    DITHERING_ATKINSON,
     NB_DITHERING
 };
 
@@ -117,6 +118,7 @@  static const AVOption paletteuse_options[] = {
         { "sierra2_4a",      "Frankie Sierra dithering v2 \"Lite\" (error diffusion)",                 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_SIERRA2_4A},      INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
         { "sierra3",         "Frankie Sierra dithering v3 (error diffusion)",                          0, AV_OPT_TYPE_CONST, {.i64=DITHERING_SIERRA3},         INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
         { "burkes",          "Burkes dithering (error diffusion)",                                     0, AV_OPT_TYPE_CONST, {.i64=DITHERING_BURKES},          INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
+        { "atkinson",        "Atkinson dithering by Bill Atkinson at Apple Computer (error diffusion)",0, AV_OPT_TYPE_CONST, {.i64=DITHERING_ATKINSON},        INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
     { "bayer_scale", "set scale for bayer dithering", OFFSET(bayer_scale), AV_OPT_TYPE_INT, {.i64=2}, 0, 5, FLAGS },
     { "diff_mode",   "set frame difference mode",     OFFSET(diff_mode),   AV_OPT_TYPE_INT, {.i64=DIFF_MODE_NONE}, 0, NB_DIFF_MODE-1, FLAGS, "diff_mode" },
         { "rectangle", "process smallest different rectangle", 0, AV_OPT_TYPE_CONST, {.i64=DIFF_MODE_RECTANGLE}, INT_MIN, INT_MAX, FLAGS, "diff_mode" },
@@ -418,6 +420,25 @@  static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram
                     if (right2) src[src_linesize   + x + 2] = dither_color(src[src_linesize   + x + 2], er, eg, eb, 2, 5);
                 }
 
+            } else if (dither == DITHERING_ATKINSON) {
+                const int right  = x < w - 1, down  = y < h - 1, left = x > x_start;
+                const int right2 = x < w - 2, down2 = y < h - 2;
+                const int color = get_dst_color_err(s, src[x], &er, &eg, &eb);
+
+                if (color < 0)
+                    return color;
+                dst[x] = color;
+
+                if (right)     src[                 x + 1] = dither_color(src[                 x + 1], er, eg, eb, 1, 3);
+                if (right2)    src[                 x + 2] = dither_color(src[                 x + 2], er, eg, eb, 1, 3);
+
+                if (down) {
+                    if (left)  src[src_linesize   + x - 1] = dither_color(src[src_linesize   + x - 1], er, eg, eb, 1, 3);
+                    if (1)     src[src_linesize   + x    ] = dither_color(src[src_linesize   + x    ], er, eg, eb, 1, 3);
+                    if (right) src[src_linesize   + x + 1] = dither_color(src[src_linesize   + x + 1], er, eg, eb, 1, 3);
+                    if (down2) src[src_linesize*2 + x    ] = dither_color(src[src_linesize*2 + x    ], er, eg, eb, 1, 3);
+                }
+
             } else {
                 const int color = color_get(s, src[x]);
 
@@ -894,6 +915,7 @@  DEFINE_SET_FRAME(sierra2,         DITHERING_SIERRA2)
 DEFINE_SET_FRAME(sierra2_4a,      DITHERING_SIERRA2_4A)
 DEFINE_SET_FRAME(sierra3,         DITHERING_SIERRA3)
 DEFINE_SET_FRAME(burkes,          DITHERING_BURKES)
+DEFINE_SET_FRAME(atkinson,        DITHERING_ATKINSON)
 
 static const set_frame_func set_frame_lut[NB_DITHERING] = {
     set_frame_none,
@@ -904,6 +926,7 @@  static const set_frame_func set_frame_lut[NB_DITHERING] = {
     set_frame_sierra2_4a,
     set_frame_sierra3,
     set_frame_burkes,
+    set_frame_atkinson,
 };
 
 static int dither_value(int p)