[PATCH] _cairo_color_double_to_short(): Use standard rounding algorithm
Søren Sandmann <[email protected]>
| Newsgroups | gmane.comp.graphics.pixman,gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
From: Søren Sandmann Pedersen <[email protected]> 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 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 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^<Ulq~(+l~x&sA=(?>7#h1n&MM%lPZ`pWi2dRxx<G`njxg HN@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@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 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^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@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@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{ -- 1.7.1 _______________________________________________ Pixman mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/pixman