[FFmpeg-devel,2/7] Fix for dithering.

Submitted by Bjorn Roche on Oct. 2, 2017, 5:24 p.m.

Details

Message ID 20171002172439.65628-3-bjorn@giphy.com
State New
Headers show

Commit Message

Bjorn Roche Oct. 2, 2017, 5:24 p.m.
From: Bjorn Roche <bjorn@xowave.com>

---
 libavfilter/vf_paletteuse.c | 52 ++++++++++++++++-----------------------------
 1 file changed, 18 insertions(+), 34 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c
index e62503c8ea..abee1b3735 100644
--- a/libavfilter/vf_paletteuse.c
+++ b/libavfilter/vf_paletteuse.c
@@ -158,12 +158,13 @@  static int query_formats(AVFilterContext *ctx)
 
 static av_always_inline int dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift)
 {
-    return av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<<shift))) << 16
+    return (px & 0xff000000)
+         | av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<<shift))) << 16
          | av_clip_uint8((px >>  8 & 0xff) + ((eg * scale) / (1<<shift))) <<  8
          | av_clip_uint8((px       & 0xff) + ((eb * scale) / (1<<shift)));
 }
 
-static av_always_inline int diffAlpha(const uint8_t *c1, const uint8_t *c2)
+static av_always_inline int diff(const uint8_t *c1, const uint8_t *c2)
 {
     // XXX: try L*a*b with CIE76 (dL*dL + da*da + db*db)
     const static int max_diff = 255*255 + 255*255 + 255*255;
@@ -176,15 +177,6 @@  static av_always_inline int diffAlpha(const uint8_t *c1, const uint8_t *c2)
     return ( c1[0] == 0 && c2[0] == 0 ) ? 0 : ( (c1[0] == c2[0]) ? (dr*dr + dg*dg + db*db) : (max_diff) ) ;
 }
 
-// static av_always_inline int diff3(const uint8_t *c1, const uint8_t *c2)
-// {
-//     // XXX: try L*a*b with CIE76 (dL*dL + da*da + db*db)
-//     const int dr = c1[1] - c2[1];
-//     const int dg = c1[2] - c2[2];
-//     const int db = c1[3] - c2[3];
-//     return dr*dr + dg*dg + db*db;
-// }
-
 static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint8_t *rgb)
 {
     printf( "colormap_nearest_bruteforce\n" );
@@ -200,7 +192,7 @@  static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *pale
                 palette[i]>> 8 & 0xff,
                 palette[i]     & 0xff,
             };
-            const int d = diffAlpha(palargb, rgb);
+            const int d = diff(palargb, rgb);
             if (d < min_dist) {
                 pal_id = i;
                 min_dist = d;
@@ -211,7 +203,7 @@  static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *pale
 }
 
 /* Recursive form, simpler but a bit slower. Kept for reference. */
-/* may not work with transparency */
+/* has not been updated for transparency */
 struct nearest_color {
     int node_pos;
     int dist_sqd;
@@ -224,10 +216,10 @@  static void colormap_nearest_node(const struct color_node *map,
 {
     printf( "colormap_nearest_node\n" );
     const struct color_node *kd = map + node_pos;
-    const int s = kd->split; //FIXME: spliut is one more than it was before
+    const int s = kd->split;
     int dx, nearer_kd_id, further_kd_id;
     const uint8_t *current = kd->val;
-    const int current_to_target = diffAlpha(target, current);
+    const int current_to_target = diff(target, current);
 
     if (current_to_target < nearest->dist_sqd) {
         nearest->node_pos = node_pos;
@@ -272,7 +264,7 @@  static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no
 
         const struct color_node *kd = &root[cur_color_id];
         const uint8_t *current = kd->val;
-        const int current_to_target = diffAlpha(target, current);
+        const int current_to_target = diff(target, current);
 
         printf( "%d-%d-%d-%d, %d, %d-%d-%d-%d\n", target[0], target[1], target[2], target[3], current_to_target, current[0], current[1], current[2], current[3] );
 
@@ -360,7 +352,7 @@  static av_always_inline int color_get(struct cache_node *cache, uint32_t argb,
                                       const enum color_search_method search_method)
 {
     printf("color_get\n");
-    //int i;
+    int i;
     const uint8_t argb_elts[] = {a, r, g, b};
     const uint8_t rhash = r & ((1<<NBITS)-1);
     const uint8_t ghash = g & ((1<<NBITS)-1);
@@ -378,19 +370,18 @@  static av_always_inline int color_get(struct cache_node *cache, uint32_t argb,
     }
     printf( "opaque %d %d %d %d\n", a, r, g, b );
 
-    // FIXME
-    // for (i = 0; i < node->nb_entries; i++) {
-    //     e = &node->entries[i];
-    //     if (e->color == rgb)
-    //         return e->pal_entry;
-    // }
+    for (i = 0; i < node->nb_entries; i++) {
+        e = &node->entries[i];
+        if (e->color == argb)
+            return e->pal_entry;
+    }
 
     e = av_dynarray2_add((void**)&node->entries, &node->nb_entries,
                          sizeof(*node->entries), NULL);
     if (!e)
         return AVERROR(ENOMEM);
     e->color = argb;
-    // FIXME
+
     e->pal_entry = COLORMAP_NEAREST(search_method, palette, map, argb_elts);
     return e->pal_entry;
 }
@@ -438,13 +429,6 @@  static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram
         for (x = x_start; x < w; x++) {
             int er, eg, eb;
 
-            // const uint8_t asss = src[x] >> 24 & 0xff;
-            // const uint8_t rsss = src[x] >> 16 & 0xff;
-            // const uint8_t gsss = src[x] >>  8 & 0xff;
-            // const uint8_t bsss = src[x]       & 0xff;
-
-            //printf( "converted %d: %d %d %d %d\n", src[x], asss, rsss, gsss, bsss );
-
             if (dither == DITHERING_BAYER) {
                 printf( "bayer\n" );
                 const int d = s->ordered_dither[(y & 7)<<3 | (x & 7)];
@@ -623,8 +607,8 @@  static int debug_accuracy(const struct color_node *node, const uint32_t *palette
                     const uint32_t c2 = palette[r2];
                     const uint8_t palrgb1[] = { c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff };
                     const uint8_t palrgb2[] = { c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff };
-                    const int d1 = diffAlpha(palrgb1, rgb);
-                    const int d2 = diffAlpha(palrgb2, rgb);
+                    const int d1 = diff(palrgb1, rgb);
+                    const int d2 = diff(palrgb2, rgb);
                     if (d1 != d2) {
                         av_log(NULL, AV_LOG_ERROR,
                                "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n",
@@ -838,7 +822,7 @@  static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1,
             const uint32_t c2 = palette[src2[x]];
             const uint8_t rgb1[] = {c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff};
             const uint8_t rgb2[] = {c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff};
-            mean_err += diffAlpha(rgb1, rgb2);
+            mean_err += diff(rgb1, rgb2);
         }
         src1 += src1_linesize;
         src2 += src2_linesize;