[Pixman] [PATCH] _cairo_color_double_to_short(): Use standard rounding algorithm

Søren Sandmann sandmann at cs.au.dk
Wed Oct 9 15:50:31 PDT 2013

```From: Søren Sandmann Pedersen <ssp at redhat.com>

The _cairo_color_double_to_short() function converts a double
precision floating point value in the range of [0.0, 1.0] to a
uint16_t integer by dividing the [0.0, 1.0] range into 65536
equal-sized intervals and then associating each interval with an
integer.

Under the assumption that an integer i corresponds to the real value i
/ 65535.0 this algorithm introduces more error than necessary as can
be seen from the following picture showing the analogous
transformation for two-bit integers:

+-----------+-----------+-----------+-----------+
0b00         |  0b01     |      0b10 |          0b11
+-----------+-----------+-----------+-----------+

which shows that some floating point values are not converted to the
integer that would minimize the error in value that that integer
corresponds to.

Instead, this patch uses standard rounding, which makes the diagram
look like this:

+-------+---------------+---------------+-------+
0b00     |      0b01     |      0b10     |      0b11
+-------+---------------+---------------+-------+

It's clear that if the values corresponding to the given integers are
fixed, then it's not possible to decrease the resulting error by
moving any of the interval boundaries.

http://lists.freedesktop.org/archives/cairo/2013-October/024691.html

Reference images updated:

record-paint-alpha.ref.png
record90-paint-alpha.argb32.ref
record90-paint-alpha.rgb24.ref.png
xcb-huge-image-shm.ref.png
xcb-huge-subimage.ref.png

All of these have only one-step differences to the old images.
---
src/cairo-color.c                                  |   11 +++--------
test/reference/pthread-similar.ref.png             |  Bin 170 -> 176 bytes
test/reference/record-paint-alpha.ref.png          |  Bin 256 -> 245 bytes
test/reference/record90-paint-alpha.argb32.ref.png |  Bin 105 -> 105 bytes
test/reference/record90-paint-alpha.rgb24.ref.png  |  Bin 105 -> 105 bytes
test/reference/xcb-huge-image-shm.ref.png          |  Bin 97 -> 97 bytes
test/reference/xcb-huge-subimage.ref.png           |  Bin 97 -> 97 bytes
7 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/cairo-color.c b/src/cairo-color.c
index 9c85255..c2a11a1 100644
--- a/src/cairo-color.c
+++ b/src/cairo-color.c
@@ -78,18 +78,13 @@ _cairo_stock_color (cairo_stock_t stock)
}

/* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
- * The conversion is designed to divide the input range into 65536
- * equally-sized regions. This is achieved by multiplying by 65536 and
- * then special-casing the result of an input value of 1.0 so that it
- * maps to 65535 instead of 65536.
+ * The conversion is designed to choose the integer i such that
+ * i / 65535.0 is as close as possible to the input value.
*/
uint16_t
_cairo_color_double_to_short (double d)
{
-    uint32_t i;
-    i = (uint32_t) (d * 65536);
-    i -= (i >> 16);
-    return i;
+    return d * 65535.0 + 0.5;
}

static void
index a22210db81372a0e2d49f54b5ac28c0ee1c67c32..c8763ba0ea079539736e48c3c2d8a64102d13440 100644
GIT binary patch
literal 176
zcmeAS at N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH\$wj^(N7l!{JxM1({\$v}}*PZ!6K
zjK;U;H}WzV at -Q17zghoWUWxVN0l}=\$J2PkQ4A1-ibl>M<)(lFZ{G=s}KfDs{BY+k%

literal 170
zcmeAS at N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH\$wj^(N7l!{JxM1({\$v}~KPZ!6K
zjK;U;895mY8IElDJ-`0^<Ulq~(+l~x&sA=(?>7#h1n&MM%lPZ`pWi2dRxx<G`njxg
HN at xNA*sC-G

diff --git a/test/reference/record-paint-alpha.ref.png b/test/reference/record-paint-alpha.ref.png
index ab7ce3e0424e1753452b2c915f89e650b3def7e8..487b8b622715a31075acfd53d83bf6a4a682f47d 100644
GIT binary patch
delta 211
zcmV;^04)E20`&oq83+OZ008_L?W2()6 at RKpL_t(YiS1Uw4Z|P|yj0zz-o%VTC&5e-
zHbIP%P5LScZfL7k2qAGV%V&JTHWo{a5hc9\$%Hy2-Ip%`Km;(I;7GsQZ{WCMKG0ksq
ztr0|&ZENjLhyb7vz7!b0\$?d18wu_E+XXc\$20gzHsr*7+dnrHkH^?L^b\$u@%v20%#A
zJ<uI^qTenG6tbt784;+t0sw5={WQ<`O`ZZDQQbvH%zx1oc#HA>MGuOSLp3|^ZwUYZ
N002ovPDHLkV1mVITUP)8

delta 222
z?U&IF!ypVqkE(-s6pz9v9>t at 0lx))e at I!EAscK84p8vR9\$iv`Rw1{{h2{X&&kL\$Pe
z=?{Yd1Zb-I-&Jt03?ed(d+)PhtVG=30@\$7b0<@|ZocCN+&qe at 1M5G^hbv7<j1xo}d
z{{se_#tK~=01\$}ueJ|\$Uo`JF#xcH<mr+xUA>KJhxJ=IwS1h@=9*\$cj{Z_fY\$2*7*6
Y6BtNIInZ`v!~g&Q07*qoM6N<\$g0~1<f&c&j

diff --git a/test/reference/record90-paint-alpha.argb32.ref.png b/test/reference/record90-paint-alpha.argb32.ref.png
index 57aa95d370160cdb8fe124b853408642d0d9aa43..5e9cb58d9c144989a5699c927af3a6feca01010f 100644
GIT binary patch
delta 48
zcmd1IoM5MYXMeptGc&U=5HogNJb19tV`}pWABKrHIF0U3 at aSd\$0#8>zmvv4FO#q}k
B5c2>4

delta 48
zcmd1IoM5MIQ}BR+nVDG_h#9*s9z59SF}3-G55u%goYs@(D7rBKfv2mV%Q~loCIEJ\$
B4`ToT

diff --git a/test/reference/record90-paint-alpha.rgb24.ref.png b/test/reference/record90-paint-alpha.rgb24.ref.png
index 57aa95d370160cdb8fe124b853408642d0d9aa43..5e9cb58d9c144989a5699c927af3a6feca01010f 100644
GIT binary patch
delta 48
zcmd1IoM5MYXMeptGc&U=5HogNJb19tV`}pWABKrHIF0U3 at aSd\$0#8>zmvv4FO#q}k
B5c2>4

delta 48
zcmd1IoM5MIQ}BR+nVDG_h#9*s9z59SF}3-G55u%goYs@(D7rBKfv2mV%Q~loCIEJ\$
B4`ToT

diff --git a/test/reference/xcb-huge-image-shm.ref.png b/test/reference/xcb-huge-image-shm.ref.png
index a0b24c8aac5178949c7af67543bd1dbe404d971c..5c274f8249ecb71077b8f1f40e6b5302788a068e 100644
GIT binary patch
delta 40
rcmYdHoM5MXXMeptGc&U=5CZ{&G#is+wbge=1|aZs^>bP0l+XkK#NY{j

delta 40
rcmYdHoM5MHQ}BR+nVDG_h=G7XT8qiWc3r<20}yz+`njxgN at xNAsILf{

diff --git a/test/reference/xcb-huge-subimage.ref.png b/test/reference/xcb-huge-subimage.ref.png
index a0b24c8aac5178949c7af67543bd1dbe404d971c..5c274f8249ecb71077b8f1f40e6b5302788a068e 100644
GIT binary patch
delta 40
rcmYdHoM5MXXMeptGc&U=5CZ{&G#is+wbge=1|aZs^>bP0l+XkK#NY{j

delta 40
rcmYdHoM5MHQ}BR+nVDG_h=G7XT8qiWc3r<20}yz+`njxgN at xNAsILf{

--
1.7.1

```