[gegl] buffer: round alpha component during u8 bilinear/box filtering
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: round alpha component during u8 bilinear/box filtering
- Date: Mon, 15 Oct 2018 07:13:38 +0000 (UTC)
commit 3114a74c6d7cb42293b68b3cfed3c77d1522e6b1
Author: Ell <ell_se yahoo com>
Date: Mon Oct 15 03:05:25 2018 -0400
buffer: round alpha component during u8 bilinear/box filtering
In gegl_{bilinear,boxfilter}_u8_nl_alpha(), round the resulting
alpha component to the nearest integer, instead of truncating it.
This improves the numerical stability of the algothims, and, in
particular, avoids potential discrepancies between the color and
alpha components, which can be particularly problematic with
premultiplied-alpha formats.
gegl/buffer/gegl-algorithms.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
---
diff --git a/gegl/buffer/gegl-algorithms.c b/gegl/buffer/gegl-algorithms.c
index dcb8db7a5..19682b1bf 100644
--- a/gegl/buffer/gegl-algorithms.c
+++ b/gegl/buffer/gegl-algorithms.c
@@ -255,8 +255,9 @@ gegl_boxfilter_u8_nl (guchar *dest_buf,
const gfloat m = middle_weight;
const gfloat b = bottom_weight;
-#define BOXFILTER_ROUND(val) lut_u16_to_u8[((int)((val)+0.5f))]
-#define C(val) lut_u8_to_u16f[(val)]
+#define C(val) lut_u8_to_u16f[(val)]
+#define BOXFILTER_ROUND(val) lut_u16_to_u8[((int)((val)+0.5f))]
+#define BOXFILTER_ROUND_ALPHA(val) ((int)((val)+0.5f))
dst[0] = BOXFILTER_ROUND(
(C(src[0][0]) * t + C(src[3][0]) * m + C(src[6][0]) * b) * l +
(C(src[1][0]) * t + C(src[4][0]) * m + C(src[7][0]) * b) * c +
@@ -414,7 +415,7 @@ gegl_boxfilter_u8_nl_alpha (guchar *dest_buf,
(C(src[0][2]) * t + C(src[3][2]) * m + C(src[6][2]) * b) * l +
(C(src[1][2]) * t + C(src[4][2]) * m + C(src[7][2]) * b) * c +
(C(src[2][2]) * t + C(src[5][2]) * m + C(src[8][2]) * b) * r);
- dst[3] = (
+ dst[3] = BOXFILTER_ROUND_ALPHA(
((src[0][3]) * t + (src[3][3]) * m + (src[6][3]) * b) * l +
((src[1][3]) * t + (src[4][3]) * m + (src[7][3]) * b) * c +
((src[2][3]) * t + (src[5][3]) * m + (src[8][3]) * b) * r);
@@ -427,7 +428,7 @@ gegl_boxfilter_u8_nl_alpha (guchar *dest_buf,
(C(src[0][0]) * t + C(src[3][0]) * m + C(src[6][0]) * b) * l +
(C(src[1][0]) * t + C(src[4][0]) * m + C(src[7][0]) * b) * c +
(C(src[2][0]) * t + C(src[5][0]) * m + C(src[8][0]) * b) * r);
- dst[1] = (
+ dst[1] = BOXFILTER_ROUND_ALPHA(
((src[0][1]) * t + (src[3][1]) * m + (src[6][1]) * b) * l +
((src[1][1]) * t + (src[4][1]) * m + (src[7][1]) * b) * c +
((src[2][1]) * t + (src[5][1]) * m + (src[8][1]) * b) * r);
@@ -442,7 +443,7 @@ gegl_boxfilter_u8_nl_alpha (guchar *dest_buf,
(C(src[1][i]) * t + C(src[4][i]) * m + C(src[7][i]) * b) * c +
(C(src[2][i]) * t + C(src[5][i]) * m + C(src[8][i]) * b) * r);
}
- dst[components-1] = (
+ dst[components-1] = BOXFILTER_ROUND_ALPHA(
((src[0][components-1]) * t + (src[3][components-1]) * m + (src[6][components-1]) * b) * l
+
((src[1][components-1]) * t + (src[4][components-1]) * m + (src[7][components-1]) * b) * c
+
((src[2][components-1]) * t + (src[5][components-1]) * m + (src[8][components-1]) * b) *
r);
@@ -451,8 +452,9 @@ gegl_boxfilter_u8_nl_alpha (guchar *dest_buf,
}
}
#undef CASE
-#undef BOXFILTER_ROUND
#undef C
+#undef BOXFILTER_ROUND
+#undef BOXFILTER_ROUND_ALPHA
static void
gegl_bilinear_u8_nl (guchar *dest_buf,
@@ -507,8 +509,9 @@ gegl_bilinear_u8_nl (guchar *dest_buf,
}\
}while(0)
-#define BILINEAR_ROUND(val) lut_u16_to_u8[(int)(val)]
-#define C(val) lut_u8_to_u16f[(val)]
+#define C(val) lut_u8_to_u16f[(val)]
+#define BILINEAR_ROUND(val) lut_u16_to_u8[((int)((val)+0.5f))]
+#define BILINEAR_ROUND_ALPHA(val) ((int)((val)+0.5f))
switch (components)
{
@@ -619,7 +622,7 @@ gegl_bilinear_u8_nl_alpha (guchar *dest_buf,
(C(src[0][i]) * rdx + C(src[1][i]) * ldx) * rdy +
(C(src[2][i]) * rdx + C(src[3][i]) * ldx) * dy);
dst[components - 1] =
- (
+ BILINEAR_ROUND_ALPHA(
((src[0][components-1]) * rdx + (src[1][components-1]) * ldx) * rdy +
((src[2][components-1]) * rdx + (src[3][components-1]) * ldx) * dy);
);
@@ -629,7 +632,7 @@ gegl_bilinear_u8_nl_alpha (guchar *dest_buf,
dst[0] = BILINEAR_ROUND(
(C(src[0][0]) * rdx + C(src[1][0]) * ldx) * rdy +
(C(src[2][0]) * rdx + C(src[3][0]) * ldx) * dy);
- dst[1] = (
+ dst[1] = BILINEAR_ROUND_ALPHA(
((src[0][1]) * rdx + (src[1][1]) * ldx) * rdy +
((src[2][1]) * rdx + (src[3][1]) * ldx) * dy);
);
@@ -654,7 +657,7 @@ gegl_bilinear_u8_nl_alpha (guchar *dest_buf,
dst[2] = BILINEAR_ROUND(
(C(src[0][2]) * rdx + C(src[1][2]) * ldx) * rdy +
(C(src[2][2]) * rdx + C(src[3][2]) * ldx) * dy);
- dst[3] = (
+ dst[3] = BILINEAR_ROUND_ALPHA(
((src[0][3]) * rdx + (src[1][3]) * ldx) * rdy +
((src[2][3]) * rdx + (src[3][3]) * ldx) * dy);
}
@@ -663,8 +666,9 @@ gegl_bilinear_u8_nl_alpha (guchar *dest_buf,
}
#undef IMPL
}
-#undef BILINEAR_ROUND
#undef C
+#undef BILINEAR_ROUND
+#undef BILINEAR_ROUND_ALPHA
static void
gegl_downscale_2x2_u8_nl (const Babl *format,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]