From 98fef3cef2d0f7f463a2e4f9f1b35b09f7b6ea77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Wed, 9 Oct 2013 15:53:16 -0400 Subject: [PATCH] _cairo_color_double_to_short(): Use standard rounding algorithm 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. See this thread for more information: http://lists.freedesktop.org/archives/cairo/2013-October/024691.html Reference images updated: pthread-similar.ref.png 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 .../record90-paint-alpha.argb32.ref.png | Bin 105 -> 105 bytes .../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 9c852559e..c2a11a177 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 diff --git a/test/reference/pthread-similar.ref.png b/test/reference/pthread-similar.ref.png index a22210db81372a0e2d49f54b5ac28c0ee1c67c32..c8763ba0ea079539736e48c3c2d8a64102d13440 100644 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}}*PZ!6K zjK;U;H}WzV@-Q17zghoWUWxVN0l}=$J2PkQ4A1-ibl>M<)(lFZ{G=s}KfDs{BY+k% Nc)I$ztaD0e0s!+fGC}|V literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}~KPZ!6K zjK;U;895mY8IElDJ-`0^7#h1n&MM%lPZ`pWi2dRxxMGuOSLp3|^ZwUYZ N002ovPDHLkV1mVITUP)8 delta 222 zcmV<403rYN0e}LK83+ad0047(di0SY6@LeGNliru)(R8=0|PHykAeUI0HR4mK~z|U z?U&IF!ypVqkE(-s6pz9v9>t@0lx))e@I!EAscK84p8vR9$iv`Rw1{{h2{X&&kL$Pe z=?{Yd1Zb-I-&Jt03?ed(d+)PhtVG=30@$7b0<@|ZocCN+&qe@1M5G^hbv7KJhxJ=IwS1h@=9*$cj{Z_fY$2*7*6 Y6BtNIInZ`v!~g&Q07*qoM6N<$g0~1zmvv4FO#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@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@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@xNAsILf{