[gegl] color-reduction: add arithmetic dithers
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] color-reduction: add arithmetic dithers
- Date: Tue, 27 Sep 2016 22:23:54 +0000 (UTC)
commit e6fd6177a0d0c3ede8c96141fbb3066e2e32ddd6
Author: Øyvind Kolås <pippin gimp org>
Date: Tue Sep 27 16:51:27 2016 +0200
color-reduction: add arithmetic dithers
Adds addition and xor based, with covariant variant implementations of the
dithering methods described at http://pippin.gimp.org/a_dither/
gegl/gegl-enums.c | 5 +
gegl/gegl-enums.h | 6 +-
operations/common/color-reduction.c | 159 ++++++++++++++++++++++++++++++++++-
3 files changed, 165 insertions(+), 5 deletions(-)
---
diff --git a/gegl/gegl-enums.c b/gegl/gegl-enums.c
index 7dd4631..7e55c6f 100644
--- a/gegl/gegl-enums.c
+++ b/gegl/gegl-enums.c
@@ -90,6 +90,11 @@ gegl_dither_method_get_type (void)
{ GEGL_DITHER_RANDOM_COVARIANT, N_("Random Covariant"), "random-covariant" },
{ GEGL_DITHER_BAYER, N_("Bayer"), "bayer" },
{ GEGL_DITHER_FLOYD_STEINBERG, N_("Floyd-Steinberg"), "floyd-steinberg" },
+ { GEGL_DITHER_ARITHMETIC_ADD, N_("Arithmetic-add"), "add" },
+ { GEGL_DITHER_ARITHMETIC_ADD_COVARIANT, N_("Arithmetic-add-covariant"), "add" },
+ { GEGL_DITHER_ARITHMETIC_XOR, N_("Arithmetic-xor"), "xor" },
+ { GEGL_DITHER_ARITHMETIC_XOR_COVARIANT, N_("Arithmetic-xor-covariant"), "xor" },
+
{ 0, NULL, NULL }
};
gint i;
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index 3c08716..b669994 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -66,7 +66,11 @@ typedef enum {
GEGL_DITHER_RESILIENT,
GEGL_DITHER_RANDOM_COVARIANT,
GEGL_DITHER_BAYER,
- GEGL_DITHER_FLOYD_STEINBERG
+ GEGL_DITHER_FLOYD_STEINBERG,
+ GEGL_DITHER_ARITHMETIC_ADD,
+ GEGL_DITHER_ARITHMETIC_ADD_COVARIANT,
+ GEGL_DITHER_ARITHMETIC_XOR,
+ GEGL_DITHER_ARITHMETIC_XOR_COVARIANT,
} GeglDitherMethod;
GType gegl_dither_method_get_type (void) G_GNUC_CONST;
diff --git a/operations/common/color-reduction.c b/operations/common/color-reduction.c
index 8cd8109..f493efa 100644
--- a/operations/common/color-reduction.c
+++ b/operations/common/color-reduction.c
@@ -72,7 +72,7 @@ generate_channel_masks (guint *channel_bits,
channel_mask [i] = ~((1 << (16 - channel_bits [i])) - 1);
}
-static guint
+static inline guint
quantize_value (guint value,
guint n_bits,
guint mask)
@@ -244,6 +244,145 @@ process_row_bayer (GeglBufferIterator *gi,
}
static void
+process_row_arithmetic_add (GeglBufferIterator *gi,
+ guint channel_mask [4],
+ guint channel_bits [4],
+ gint y)
+{
+ guint16 *data_in = (guint16*) gi->data [0];
+ guint16 *data_out = (guint16*) gi->data [1];
+ guint x;
+ for (x = 0; x < gi->roi->width; x++)
+ {
+ guint pixel = 4 * (gi->roi->width * y + x);
+ guint ch;
+
+ for (ch = 0; ch < 4; ch++)
+ {
+ gint u = gi->roi->x + x;
+ gint v = gi->roi->y + y;
+ gfloat mask;
+ gfloat value;
+ gfloat value_clamped;
+ gfloat quantized;
+ mask = (((u+ch * 67) + v * 236) * 119) & 255;
+ mask = ((mask - 128) * 65536.0 / 256.0) / (1 << (channel_bits [ch] - 1));
+ value = data_in [pixel + ch] + mask;
+ value_clamped = CLAMP (value, 0.0, 65535.0);
+ quantized = quantize_value ((guint) (value_clamped + 0.5),
+ channel_bits [ch],
+ channel_mask [ch]);
+
+ data_out [pixel + ch] = (guint16) quantized;
+ }
+ }
+}
+
+static void
+process_row_arithmetic_xor (GeglBufferIterator *gi,
+ guint channel_mask [4],
+ guint channel_bits [4],
+ gint y)
+{
+ guint16 *data_in = (guint16*) gi->data [0];
+ guint16 *data_out = (guint16*) gi->data [1];
+ guint x;
+ for (x = 0; x < gi->roi->width; x++)
+ {
+ guint pixel = 4 * (gi->roi->width * y + x);
+ guint ch;
+
+ for (ch = 0; ch < 4; ch++)
+ {
+ gint u = gi->roi->x + x;
+ gint v = gi->roi->y + y;
+ gfloat mask;
+ gfloat value;
+ gfloat value_clamped;
+ gfloat quantized;
+ mask = (((u+ch * 17) ^ v * 149) * 1234) & 511;
+ mask = ((mask - 257) * 65536.0 / 512.0) / (1 << (channel_bits [ch] - 1));
+ value = data_in [pixel + ch] + mask;
+ value_clamped = CLAMP (value, 0.0, 65535.0);
+ quantized = quantize_value ((guint) (value_clamped + 0.5),
+ channel_bits [ch],
+ channel_mask [ch]);
+
+ data_out [pixel + ch] = (guint16) quantized;
+ }
+ }
+}
+
+static void
+process_row_arithmetic_add_covariant (GeglBufferIterator *gi,
+ guint channel_mask [4],
+ guint channel_bits [4],
+ gint y)
+{
+ guint16 *data_in = (guint16*) gi->data [0];
+ guint16 *data_out = (guint16*) gi->data [1];
+ guint x;
+ for (x = 0; x < gi->roi->width; x++)
+ {
+ guint pixel = 4 * (gi->roi->width * y + x);
+ guint ch;
+
+ for (ch = 0; ch < 4; ch++)
+ {
+ gint u = gi->roi->x + x;
+ gint v = gi->roi->y + y;
+ gfloat mask;
+ gfloat value;
+ gfloat value_clamped;
+ gfloat quantized;
+ mask = ((u+ v * 236) * 119) & 255;
+ mask = ((mask - 128) * 65536.0 / 256.0) / (1 << (channel_bits [ch] - 1));
+ value = data_in [pixel + ch] + mask;
+ value_clamped = CLAMP (value, 0.0, 65535.0);
+ quantized = quantize_value ((guint) (value_clamped + 0.5),
+ channel_bits [ch],
+ channel_mask [ch]);
+
+ data_out [pixel + ch] = (guint16) quantized;
+ }
+ }
+}
+
+static void
+process_row_arithmetic_xor_covariant (GeglBufferIterator *gi,
+ guint channel_mask [4],
+ guint channel_bits [4],
+ gint y)
+{
+ guint16 *data_in = (guint16*) gi->data [0];
+ guint16 *data_out = (guint16*) gi->data [1];
+ guint x;
+ for (x = 0; x < gi->roi->width; x++)
+ {
+ guint pixel = 4 * (gi->roi->width * y + x);
+ guint ch;
+
+ for (ch = 0; ch < 4; ch++)
+ {
+ gint u = gi->roi->x + x;
+ gint v = gi->roi->y + y;
+ gfloat mask;
+ gfloat value;
+ gfloat value_clamped;
+ gfloat quantized;
+ mask = ((u ^ v * 149) * 1234) & 511;
+ mask = ((mask - 257) * 65536.0 / 512.0) / (1 << (channel_bits [ch] - 1));
+ value = data_in [pixel + ch] + mask;
+ value_clamped = CLAMP (value, 0.0, 65535.0);
+ quantized = quantize_value ((guint) (value_clamped + 0.5),
+ channel_bits [ch],
+ channel_mask [ch]);
+
+ data_out [pixel + ch] = (guint16) quantized;
+ }
+ }
+}
+static void
process_row_random_covariant (GeglBufferIterator *gi,
guint channel_mask [4],
guint channel_bits [4],
@@ -261,9 +400,9 @@ process_row_random_covariant (GeglBufferIterator *gi,
gi->roi->y + y, 0, 0));
for (ch = 0; ch < 4; ch++)
{
- gdouble value;
- gdouble value_clamped;
- gdouble quantized;
+ gfloat value;
+ gfloat value_clamped;
+ gfloat quantized;
value = data_in [pixel + ch] + (r / (1 << channel_bits [ch]));
value_clamped = CLAMP (value, 0.0, 65535.0);
@@ -409,6 +548,18 @@ process_standard (GeglBuffer *input,
case GEGL_DITHER_FLOYD_STEINBERG:
/* Done separately */
break;
+ case GEGL_DITHER_ARITHMETIC_ADD:
+ process_row_arithmetic_add (gi, channel_mask, channel_bits, y);
+ break;
+ case GEGL_DITHER_ARITHMETIC_XOR:
+ process_row_arithmetic_xor (gi, channel_mask, channel_bits, y);
+ break;
+ case GEGL_DITHER_ARITHMETIC_ADD_COVARIANT:
+ process_row_arithmetic_add_covariant (gi, channel_mask, channel_bits, y);
+ break;
+ case GEGL_DITHER_ARITHMETIC_XOR_COVARIANT:
+ process_row_arithmetic_xor_covariant (gi, channel_mask, channel_bits, y);
+ break;
default:
process_row_no_dither (gi, channel_mask, channel_bits, y);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]