[FFmpeg-devel] [PATCH 2/7] Fix for dithering.
Bjorn Roche
bjorn at giphy.com
Mon Oct 2 20:24:34 EEST 2017
From: Bjorn Roche <bjorn at xowave.com>
---
libavfilter/vf_paletteuse.c | 52 ++++++++++++++++-----------------------------
1 file changed, 18 insertions(+), 34 deletions(-)
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;
--
2.14.1
More information about the ffmpeg-devel
mailing list