On 03/27/2018 07:45 PM, Bill Spitzak wrote:
> Quick look at the patch and it seems like this will work, though it is a
> random dither. You might get much better compression of .png with a
> patterned dither. I've also had good luck with pseudo-error-diffusion.
> You keep in static memory an accumulated error (per color, but not
> really depending on the location of the pixel) and that is the threshold
> for the random number. This produces a bit more patterning than a
> straight random generator. You might also try it with no random number
> generator at all, but you have to preserve the accumulated error so that
> solid areas that are an integer don't reset it so each adjacent line
> gets the same pattern.

I implemented the accumulated error dithering (attached file, can be
applied over the previous 0001 patch). It greatly improves PNG
compression ratio for purely horizontal gradients (approximately +15%
instead of +10000%, in filesize), but produces small artifacts (it's
still way better than no dithering of course, they are almost invisible)
without a random accumulated error at the start of lines (which
increases a lot the filesize).


> May want to call the "on" setting PIXMAN_DITHERING_GOOD. On the
> assumption that anybody who wants it on is happy with "good" dithering,
> and that they may not want to pay for the slowness of "best" dithering.

Considering the prng used, the slowness is almost negligible ("good
except for the small stripes" dithering may in fact be slower)

-- 
Marc
From 85aa2a84e74f3079796ec4686c4fa2acf6c2e93f Mon Sep 17 00:00:00 2001
From: Marc Jeanmougin <m...@jeanmougin.fr>
Date: Tue, 27 Mar 2018 21:36:10 +0200
Subject: [PATCH 2/2] Adds PIXMAN_DITHERING_GOOD with diffusion of accumulated
 error

Signed-off-by: Marc Jeanmougin <m...@jeanmougin.fr>
---
 pixman/pixman-gradient-walker.c | 21 ++++++++++++++++++++-
 pixman/pixman-image.c           |  2 +-
 pixman/pixman.h                 |  1 +
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index dbd7a92..1311fa4 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -52,7 +52,7 @@ _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
 
     walker->need_reset = TRUE;
     walker->dithering = gradient->dithering;
-    walker->prng_state = rand();
+    walker->prng_state = (gradient->dithering == PIXMAN_DITHERING_BEST) ? rand() : 0;
 }
 
 static void
@@ -179,6 +179,7 @@ _pixman_dither (pixman_gradient_walker_t *walker, float *in)
 {
     float f_rem = (*in-(float)((int)(*in)));
     uint32_t i_rem = f_rem * 4294967296.;
+    uint32_t color_state;
 
     switch (walker->dithering)
     {
@@ -190,6 +191,24 @@ _pixman_dither (pixman_gradient_walker_t *walker, float *in)
             return *in +1;
         else
             return *in;
+
+    case PIXMAN_DITHERING_GOOD:
+        /* we use prng_state to keep four 8-bit values of errors to propagate */
+        color_state = walker->prng_state & 0xff;
+        i_rem >>= 24; /*keep 8 most significant bits*/
+        color_state+=i_rem;
+        if (color_state >= 256){
+            color_state -= 256;
+            /*rotate*/
+            walker->prng_state = (walker->prng_state >> 8) | (color_state<<24);
+            return *in+1;
+        }
+        else {
+            /*rotate*/
+            walker->prng_state = (walker->prng_state >> 8) | (color_state<<24);
+            return *in;
+        }
+
     case PIXMAN_DITHERING_NONE:
     default:
         /* round */
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 75f168e..61e6988 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -102,7 +102,7 @@ _pixman_init_gradient (gradient_t *                  gradient,
     gradient->n_stops = n_stops;
 
     gradient->common.property_changed = gradient_property_changed;
-    gradient->dithering = PIXMAN_DITHERING_NONE;
+    gradient->dithering = PIXMAN_DITHERING_GOOD;
 
     return TRUE;
 }
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 5ac0db6..2422eb8 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -319,6 +319,7 @@ typedef enum
 typedef enum
 {
     PIXMAN_DITHERING_NONE,
+    PIXMAN_DITHERING_GOOD,
     PIXMAN_DITHERING_BEST
 } pixman_dithering_t;
 
-- 
2.16.2

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to