From: Basile Clement <basile-pix...@clement.pm>

On some screens (typically low quality laptop screens), using Bayer
ordered dithering has been observed to cause color changes depending on
*where the gradient is rendered on the screen*, causing visible
flickering when moving an image on the screen.

To alleviate the issue, this patch adds support for ordered dithering
using a 64x64 matrix tuned from blue noise.  In addition to being devoid
of the positional dependency on screen, the blue noise matrix also
generates more pleasing and less discernable patterns.  As such, it is
now the method used for PIXMAN_DITHER_GOOD and PIXMAN_DITHER_BEST
dithering methods.

The 64x64 blue noise matrix has been generated using the provided
`pixman/dither/make-blue-noise.c` script, which uses the
void-and-cluster method.
---
 demos/dither.c                   |   1 +
 pixman/dither/blue-noise-64x64.h |  77 ++++
 pixman/dither/make-blue-noise.c  | 679 +++++++++++++++++++++++++++++++
 pixman/pixman-bits-image.c       |  16 +-
 pixman/pixman.h                  |   1 +
 test/tolerance-test.c            |   1 +
 test/utils.c                     |   1 +
 7 files changed, 775 insertions(+), 1 deletion(-)
 create mode 100644 pixman/dither/blue-noise-64x64.h
 create mode 100644 pixman/dither/make-blue-noise.c

diff --git a/demos/dither.c b/demos/dither.c
index d4271e6..d72c250 100644
--- a/demos/dither.c
+++ b/demos/dither.c
@@ -78,6 +78,7 @@ static const named_int_t dithers[] =
 {
     { "None",                   PIXMAN_REPEAT_NONE },
     { "Bayer 8x8",              PIXMAN_DITHER_ORDERED_BAYER_8 },
+    { "Blue noise 64x64",       PIXMAN_DITHER_ORDERED_BLUE_NOISE_64 },
 };
 
 static int
diff --git a/pixman/dither/blue-noise-64x64.h b/pixman/dither/blue-noise-64x64.h
new file mode 100644
index 0000000..e196d2d
--- /dev/null
+++ b/pixman/dither/blue-noise-64x64.h
@@ -0,0 +1,77 @@
+/* WARNING: This file is generated by make-blue-noise.c
+ * Please edit that file instead of this one.
+ */
+
+#ifndef BLUE_NOISE_64X64_H
+#define BLUE_NOISE_64X64_H
+
+#include <stdint.h>
+
+static const uint32_t dither_blue_noise_64x64[4096] = {
+    3039, 1368, 3169, 103, 2211, 1248, 2981, 668, 2633, 37, 3963, 2903, 384, 
2564, 3115, 1973, 3348, 830, 2505, 1293, 3054, 1060, 1505, 3268, 400, 1341, 
593, 3802, 3384, 429, 4082, 1411, 2503, 3863, 126, 1292, 1887, 2855, 205, 2094, 
2977, 1899, 3924, 356, 3088, 2500, 3942, 1409, 2293, 1734, 3732, 1291, 3227, 
277, 2054, 786, 2871, 411, 2425, 1678, 3986, 455, 2879, 2288,
+    388, 1972, 3851, 778, 2768, 3697, 944, 2123, 1501, 3533, 937, 1713, 1381, 
3888, 156, 1242, 516, 2888, 1607, 3676, 632, 2397, 3804, 2673, 1898, 3534, 
2593, 1777, 1170, 2299, 3013, 1838, 523, 3053, 1647, 3601, 3197, 959, 1520, 
3633, 893, 2437, 3367, 2187, 1258, 137, 1965, 401, 3546, 643, 3087, 2498, 733, 
2786, 3371, 4053, 1266, 1977, 3663, 183, 2570, 2107, 1183, 3708,
+    907, 2473, 1151, 3363, 1527, 1902, 232, 3903, 3060, 496, 2486, 3206, 2165, 
861, 2387, 3653, 2101, 3972, 132, 2162, 3437, 1827, 215, 895, 3114, 271, 969, 
2932, 197, 1598, 878, 3696, 1140, 2120, 904, 2431, 302, 3846, 2675, 481, 3187, 
66, 1440, 650, 3833, 2826, 3435, 901, 2936, 2111, 250, 1875, 3609, 1174, 1747, 
162, 2346, 3420, 913, 3172, 1383, 752, 3298, 1735,
+    3540, 2938, 249, 2324, 526, 3099, 2561, 1324, 2347, 1861, 1200, 3702, 257, 
3442, 1514, 2999, 992, 1766, 2735, 1163, 478, 2943, 1279, 3635, 2177, 1464, 
3672, 2386, 3871, 3340, 2690, 64, 3489, 2811, 3999, 633, 1948, 1243, 2269, 
1807, 1143, 2750, 3729, 1790, 2363, 1053, 1537, 2636, 4065, 1076, 1476, 3869, 
450, 2200, 2676, 658, 2979, 1548, 544, 1913, 2838, 3911, 116, 2698,
+    517, 1295, 3997, 1739, 3665, 1083, 3509, 599, 3400, 118, 2956, 720, 2689, 
1907, 567, 2523, 284, 3397, 711, 3219, 2450, 3985, 1665, 2549, 562, 3011, 1855, 
729, 1355, 528, 1908, 2456, 1384, 337, 1540, 2654, 3138, 3513, 703, 4080, 3314, 
2047, 855, 3037, 209, 3317, 577, 1828, 17, 2336, 3193, 2748, 962, 3441, 1450, 
3246, 1075, 3878, 2615, 3497, 1033, 2310, 1442, 2183,
+    1654, 3254, 2061, 738, 2832, 148, 2030, 1670, 909, 3850, 2109, 1533, 4046, 
1085, 3098, 3897, 1378, 2248, 3829, 1495, 1966, 23, 797, 3427, 1124, 4057, 95, 
2787, 2190, 3074, 3950, 742, 3194, 1999, 3386, 1113, 16, 1657, 2804, 201, 1543, 
383, 2559, 1325, 3604, 2068, 2493, 3771, 1284, 3460, 710, 1716, 2447, 80, 3811, 
2032, 347, 2227, 15, 1689, 397, 3084, 662, 3798,
+    973, 43, 2608, 3143, 1459, 2423, 4066, 2770, 3191, 1283, 2630, 314, 3235, 
2289, 72, 1822, 2840, 924, 350, 2653, 1057, 3715, 2235, 2775, 346, 2083, 1553, 
3292, 1081, 274, 1686, 1188, 2327, 3743, 578, 2234, 3916, 2519, 1011, 3056, 
2207, 3438, 3890, 537, 1617, 837, 3094, 373, 2795, 1980, 276, 3951, 1353, 3015, 
844, 1724, 3651, 2923, 1316, 4092, 2504, 3627, 1936, 2854,
+    2461, 3929, 1193, 421, 3746, 820, 1180, 286, 2261, 532, 3625, 1812, 802, 
1327, 3527, 670, 3730, 2025, 3124, 3565, 529, 2960, 1769, 1390, 3196, 2494, 
3756, 796, 3618, 2602, 3463, 2847, 166, 953, 1745, 2900, 438, 2070, 1418, 3741, 
639, 1205, 1891, 2882, 2282, 4012, 1182, 1696, 3630, 951, 2904, 2170, 3530, 
375, 2320, 2742, 1132, 701, 3216, 2023, 847, 1230, 310, 3431,
+    770, 1961, 3531, 1702, 2181, 3370, 1877, 3072, 1571, 3389, 1071, 2415, 
3782, 2803, 1610, 2454, 1211, 182, 1655, 2322, 1282, 3372, 287, 3935, 704, 
1232, 415, 1910, 2286, 1399, 556, 1964, 4068, 2444, 3605, 1272, 3345, 816, 
3526, 256, 2402, 2777, 955, 345, 3289, 111, 2727, 635, 2396, 1488, 3331, 600, 
1032, 1575, 4026, 515, 3507, 2433, 1605, 460, 3364, 2783, 1810, 1397,
+    2334, 223, 2945, 688, 2533, 99, 2705, 624, 3944, 2073, 46, 2978, 508, 
2132, 269, 3173, 3453, 2631, 4076, 694, 1892, 2586, 972, 2178, 3470, 1695, 
2849, 3141, 77, 3884, 994, 3029, 1536, 673, 3083, 124, 2583, 1722, 2821, 1944, 
4027, 1661, 3176, 3728, 1337, 1813, 3503, 2035, 3930, 157, 2537, 1865, 3096, 
2646, 1941, 3252, 1449, 135, 2836, 3758, 2139, 84, 3678, 3106,
+    3862, 1545, 3307, 1320, 3955, 1031, 3664, 1306, 2460, 776, 1487, 3294, 
1187, 3990, 1903, 1021, 549, 1484, 943, 3027, 97, 3853, 1499, 2880, 198, 2575, 
3995, 1089, 1587, 2475, 3282, 339, 2657, 1158, 2105, 1493, 3943, 580, 3232, 
1287, 846, 48, 2480, 2112, 771, 2534, 459, 3134, 850, 1298, 3790, 325, 3652, 
1249, 193, 940, 2202, 3895, 1829, 911, 1366, 2577, 1069, 534,
+    2104, 1009, 2667, 392, 1983, 2917, 1645, 324, 3439, 2869, 3705, 1767, 
2592, 756, 2916, 3683, 2276, 2850, 2053, 3594, 2403, 3181, 634, 3699, 1933, 
906, 519, 2150, 3673, 764, 1770, 2220, 3795, 3336, 502, 3547, 2339, 1110, 301, 
2210, 3354, 3643, 569, 1518, 2940, 3973, 1138, 1613, 2773, 2127, 2983, 1671, 
769, 2161, 3800, 2730, 3127, 1179, 533, 3259, 2284, 4014, 1651, 2820,
+    3566, 653, 1839, 3455, 2399, 789, 3149, 2244, 1863, 1099, 474, 2307, 158, 
3541, 1312, 1711, 0, 3902, 360, 1629, 1091, 395, 1781, 1191, 2374, 3353, 1419, 
3225, 206, 2931, 3553, 1046, 54, 1646, 2470, 910, 1860, 3137, 3770, 2635, 1562, 
2809, 1215, 3788, 222, 2199, 3335, 67, 3606, 524, 1001, 3309, 2410, 3473, 591, 
1619, 291, 2502, 3629, 2891, 335, 741, 3378, 168,
+    2384, 3129, 4051, 22, 1444, 3613, 543, 3893, 186, 2665, 4062, 933, 3058, 
2142, 449, 2711, 3224, 849, 1330, 3349, 2195, 2670, 3484, 2993, 32, 3774, 2722, 
1859, 2548, 1268, 583, 2027, 3165, 2807, 4029, 227, 2897, 1434, 721, 1816, 195, 
905, 2066, 3258, 1754, 970, 2674, 1880, 2338, 3915, 1485, 2660, 14, 1313, 2914, 
2046, 4074, 791, 1917, 1301, 1725, 2687, 2019, 1443,
+    418, 1186, 1664, 2859, 1049, 2056, 2741, 1226, 1589, 3186, 2042, 1377, 
3449, 1574, 3941, 1063, 1930, 2501, 3751, 2930, 671, 4031, 888, 2081, 1544, 
684, 1117, 351, 4052, 1698, 2393, 3881, 1439, 785, 1277, 2013, 3488, 441, 2459, 
3980, 3061, 3481, 2543, 419, 3020, 609, 3515, 1350, 799, 2878, 348, 2034, 3966, 
1824, 950, 3281, 1394, 2239, 3452, 55, 3922, 3119, 892, 3785,
+    3023, 2140, 782, 2492, 3817, 241, 3355, 2424, 856, 3639, 612, 2556, 245, 
2858, 705, 2316, 3562, 495, 1748, 128, 1912, 1454, 280, 2552, 3905, 3130, 2274, 
3472, 834, 3055, 240, 2692, 471, 2272, 3301, 2632, 1080, 3693, 2136, 1029, 
1364, 590, 1611, 4067, 1190, 2360, 3827, 261, 3180, 1768, 3471, 1103, 3003, 
520, 3674, 151, 2571, 555, 3033, 982, 2353, 504, 1259, 2555,
+    149, 3889, 3380, 493, 3178, 1681, 663, 1924, 2990, 49, 1792, 3861, 1192, 
1987, 3273, 297, 1457, 3043, 1177, 2292, 3249, 2829, 3682, 1154, 1758, 428, 
2872, 1993, 1500, 3703, 1129, 3421, 1840, 3754, 163, 659, 1733, 3182, 38, 2875, 
1957, 3614, 2237, 78, 1873, 2801, 1513, 2121, 1074, 2516, 667, 3710, 1429, 
2430, 2088, 2830, 1072, 3557, 1531, 2733, 1955, 3286, 3590, 1826,
+    2778, 1068, 1932, 1452, 2279, 1185, 3564, 3952, 1391, 2726, 3313, 2331, 
870, 3709, 1674, 2772, 4085, 808, 2596, 3848, 927, 538, 2335, 3334, 773, 3597, 
1347, 109, 2663, 608, 2108, 2994, 936, 1524, 2922, 3968, 2422, 1467, 845, 3870, 
321, 2704, 1073, 3308, 3680, 823, 430, 3375, 4030, 112, 2171, 2695, 267, 3374, 
731, 1627, 3919, 1871, 352, 3839, 1370, 234, 794, 1532,
+    3245, 647, 3575, 74, 3045, 2766, 285, 2174, 498, 1059, 1551, 385, 3125, 
2598, 143, 1128, 2095, 3395, 318, 1590, 3524, 1345, 1969, 242, 2759, 2092, 947, 
3926, 3244, 2356, 1658, 6, 3593, 2554, 1172, 1995, 371, 2755, 3417, 2294, 1570, 
3164, 748, 2517, 1401, 3111, 2420, 1662, 2910, 1276, 3276, 854, 1804, 4000, 
1253, 2987, 229, 2344, 3184, 649, 2196, 2921, 4095, 2389,
+    1289, 2193, 2579, 4023, 757, 1858, 986, 3199, 2514, 3475, 4021, 2154, 651, 
1432, 3468, 2404, 574, 1799, 3105, 2145, 86, 2614, 3218, 1565, 4088, 2481, 
3079, 1815, 323, 1212, 3837, 759, 2159, 435, 3223, 784, 3659, 1114, 1888, 550, 
1221, 3786, 1803, 499, 2117, 185, 3763, 942, 589, 2001, 3838, 1483, 3154, 2256, 
468, 2544, 3403, 898, 1208, 2610, 3622, 967, 1929, 378,
+    3781, 220, 1656, 1115, 3347, 2428, 3822, 1577, 712, 1959, 110, 2765, 1762, 
3854, 979, 2928, 3714, 1371, 746, 3969, 2884, 975, 3779, 641, 1142, 159, 1460, 
702, 3485, 2866, 2495, 3330, 1305, 3937, 1635, 2229, 2962, 146, 4055, 3091, 
2417, 100, 3508, 2933, 4006, 1167, 1920, 2760, 3552, 2545, 433, 2845, 142, 
1056, 1886, 3616, 1435, 2099, 3803, 1749, 27, 1446, 3350, 2843,
+    884, 3310, 2948, 2103, 447, 1351, 187, 2895, 3655, 1256, 3036, 932, 3325, 
2257, 451, 1915, 40, 2780, 2438, 1112, 1814, 423, 2290, 1905, 2898, 3419, 2306, 
3760, 1938, 486, 1019, 1791, 3010, 2628, 203, 3408, 1269, 2507, 1606, 862, 
2779, 2078, 952, 1529, 2638, 708, 3332, 1413, 2, 1726, 1156, 3500, 2392, 3791, 
3076, 812, 107, 2861, 501, 3050, 3487, 2455, 594, 1731,
+    2685, 1498, 680, 3908, 2621, 3529, 1786, 2236, 342, 2569, 1526, 3722, 230, 
1290, 3203, 3947, 1609, 3516, 467, 3267, 3685, 1461, 3140, 3569, 367, 1759, 
928, 2754, 1332, 2219, 4034, 260, 655, 1984, 978, 3814, 617, 2086, 3525, 279, 
3841, 1373, 3361, 319, 2251, 3066, 407, 2382, 3918, 3133, 2168, 762, 1523, 507, 
2641, 1677, 4025, 2413, 1584, 793, 2049, 1109, 3962, 2218,
+    1194, 3692, 266, 1687, 981, 3103, 740, 3983, 1005, 3434, 570, 2383, 1942, 
2718, 676, 2462, 1007, 2089, 1308, 2222, 233, 2568, 829, 1241, 2669, 3987, 514, 
3303, 69, 3142, 1603, 3560, 2295, 3288, 1497, 2696, 1764, 2865, 1058, 3271, 
1914, 477, 2529, 3927, 1736, 1273, 3752, 2029, 1012, 565, 2798, 4078, 1949, 
3305, 1175, 2179, 380, 3366, 1195, 3849, 2637, 416, 2959, 125,
+    3396, 2467, 2036, 3234, 2340, 68, 2819, 1436, 2011, 3139, 1704, 4073, 860, 
3582, 1468, 2969, 211, 3157, 4056, 866, 2935, 2000, 3923, 31, 2157, 1477, 2429, 
1147, 3792, 2557, 774, 2802, 1153, 3747, 464, 3192, 42, 3904, 539, 1474, 2283, 
803, 2876, 1061, 75, 3477, 747, 2893, 1538, 3626, 251, 1322, 2506, 189, 2791, 
3667, 939, 2991, 1971, 175, 3195, 1416, 3648, 1857,
+    3052, 454, 851, 3789, 1271, 1906, 3694, 2484, 406, 2757, 26, 1189, 2909, 
296, 2215, 3784, 1864, 637, 2715, 1673, 3445, 581, 1572, 3059, 3469, 761, 2984, 
1737, 2058, 440, 1414, 1921, 121, 2527, 894, 2223, 1302, 2377, 3077, 2666, 
3759, 3198, 1811, 3661, 2166, 2731, 1883, 359, 3285, 2458, 1805, 3459, 926, 
3834, 675, 1893, 1496, 2612, 657, 3523, 1763, 2354, 564, 961,
+    1367, 3977, 1588, 2714, 322, 3446, 1088, 625, 3887, 1354, 3535, 2090, 
3316, 1760, 1127, 483, 3491, 1421, 2301, 94, 1202, 3740, 2311, 1014, 1878, 
3836, 180, 3412, 991, 2868, 3953, 3450, 3081, 1632, 4071, 1882, 3543, 726, 
1719, 179, 1171, 364, 1420, 622, 3090, 1490, 946, 4007, 2212, 1102, 619, 2739, 
2189, 1669, 2937, 3426, 39, 3940, 2191, 1264, 887, 4091, 2792, 2135,
+    4, 2883, 2281, 631, 3044, 1641, 2232, 3243, 1773, 2319, 827, 2591, 629, 
3938, 2426, 3222, 2629, 1044, 3879, 3293, 1952, 2749, 275, 2590, 472, 1372, 
2496, 660, 3669, 2264, 208, 915, 2167, 561, 2828, 307, 3265, 1104, 3964, 2155, 
3425, 1951, 4077, 2391, 283, 3387, 2581, 115, 1415, 3069, 3896, 141, 3158, 
1214, 442, 2405, 1349, 3085, 425, 2528, 3002, 312, 1602, 3588,
+    1137, 3323, 1963, 1002, 3578, 2521, 127, 925, 2970, 273, 3737, 1573, 167, 
2863, 1509, 800, 147, 2059, 2942, 409, 921, 3151, 1451, 3909, 3333, 2844, 2096, 
1512, 3136, 1210, 1798, 2709, 1331, 3586, 1034, 1521, 2441, 2926, 488, 2585, 
775, 3031, 2693, 879, 3602, 1173, 2028, 3654, 2781, 841, 1975, 1507, 3646, 768, 
3991, 2012, 996, 3544, 1666, 3810, 1990, 3360, 753, 2597,
+    3736, 304, 1473, 3828, 485, 1334, 4008, 2072, 3495, 1136, 2806, 2004, 
3236, 1010, 2130, 3819, 1750, 3567, 644, 2515, 1794, 3636, 698, 2137, 1162, 
832, 3761, 326, 2613, 513, 3302, 3820, 357, 3163, 2259, 3733, 101, 1922, 1386, 
3587, 1640, 28, 1286, 2141, 1761, 2918, 693, 1639, 457, 3250, 2434, 365, 2599, 
1729, 3284, 2643, 306, 2793, 689, 1090, 104, 1309, 2305, 1831,
+    2776, 859, 2446, 2915, 1778, 3337, 2677, 614, 1508, 2409, 469, 4033, 1321, 
3563, 402, 3131, 2720, 1093, 1569, 4042, 1229, 2277, 216, 3046, 1817, 57, 3006, 
1684, 4059, 2016, 795, 2440, 1652, 1960, 610, 2763, 920, 3864, 3110, 1026, 
2326, 3762, 3233, 521, 3856, 173, 2457, 3939, 2138, 1262, 3572, 989, 3021, 
2238, 119, 1445, 3832, 1809, 2297, 3467, 2700, 3684, 3102, 394,
+    4036, 2050, 3256, 89, 2198, 1079, 248, 1845, 3805, 3104, 880, 1779, 2688, 
717, 2373, 1375, 262, 2249, 3071, 13, 2813, 3429, 1600, 3984, 2416, 3603, 1299, 
2298, 998, 3492, 1393, 2951, 10, 4009, 1247, 3462, 1679, 2204, 414, 2736, 316, 
1894, 2816, 1050, 3373, 1462, 3107, 817, 3464, 21, 1835, 4070, 568, 1178, 3718, 
875, 3168, 466, 2974, 1458, 2084, 616, 1564, 1018,
+    1693, 546, 1244, 3899, 716, 3160, 3608, 2877, 1220, 334, 3443, 2270, 44, 
3000, 1843, 3928, 3405, 766, 3686, 2040, 587, 993, 2647, 387, 930, 2753, 630, 
3274, 150, 2808, 453, 3638, 1092, 2352, 3030, 239, 2562, 700, 3240, 1257, 4016, 
730, 1515, 2203, 2551, 417, 1866, 1123, 2348, 2902, 1550, 2678, 2075, 3238, 
1630, 2531, 2115, 1255, 4054, 840, 290, 3874, 2477, 3399,
+    2250, 3577, 2817, 1626, 2576, 1356, 2315, 792, 2087, 2618, 1612, 3855, 
1263, 3637, 1036, 494, 1535, 2553, 1198, 1715, 3867, 3170, 1359, 1954, 3483, 
1539, 2069, 3886, 1772, 2487, 1534, 2045, 3242, 806, 1578, 2018, 3948, 1423, 
3596, 2076, 2466, 3424, 139, 3688, 871, 4049, 2852, 3342, 547, 3719, 327, 852, 
3505, 207, 2794, 542, 3600, 45, 2411, 3324, 1788, 3012, 1235, 61,
+    2655, 917, 253, 1986, 3738, 313, 1706, 4072, 120, 3229, 957, 597, 2024, 
3262, 2453, 2857, 2002, 3190, 210, 2784, 2206, 300, 2400, 3766, 553, 3152, 218, 
1150, 2988, 883, 3753, 627, 2664, 3831, 437, 3385, 1008, 2957, 60, 1636, 891, 
2899, 1776, 3062, 1315, 2026, 194, 1643, 2079, 1296, 3201, 2465, 1379, 1927, 
3898, 1125, 1847, 2846, 1552, 1028, 2725, 2169, 787, 3202,
+    1441, 3982, 3032, 1052, 3251, 605, 2639, 3073, 1431, 3642, 2329, 2949, 
341, 1634, 833, 129, 4020, 916, 3571, 669, 1506, 3411, 821, 2856, 1207, 2337, 
2683, 3448, 340, 2214, 3128, 235, 1738, 1288, 2833, 2419, 606, 1884, 2668, 552, 
3765, 1176, 399, 2302, 596, 3591, 2634, 767, 3845, 2767, 995, 3967, 491, 3057, 
814, 2300, 3422, 691, 3797, 254, 3645, 509, 3478, 1836,
+    2119, 475, 2445, 1525, 2175, 3539, 914, 1926, 473, 1157, 1800, 3971, 2701, 
3739, 2129, 3486, 1333, 1784, 2366, 2982, 1070, 4089, 1802, 73, 1642, 3958, 
835, 1837, 1480, 4043, 1217, 2469, 3416, 2113, 88, 3668, 1240, 3255, 3920, 
2355, 3167, 2003, 2645, 3936, 3228, 1592, 1144, 3474, 2394, 79, 1820, 2241, 
1594, 3656, 2584, 153, 1448, 3034, 2005, 2511, 1692, 1335, 3913, 217,
+    2822, 3391, 745, 3813, 192, 1274, 2941, 3847, 2489, 3440, 744, 161, 1422, 
1086, 572, 3004, 2617, 338, 3807, 2031, 236, 2472, 3065, 2098, 3358, 362, 2163, 
3574, 497, 2788, 1970, 948, 3885, 685, 3100, 1712, 2228, 292, 1408, 1016, 164, 
3537, 1417, 941, 34, 2172, 3001, 358, 1491, 3147, 699, 3356, 258, 1149, 2946, 
1787, 3931, 382, 1146, 3291, 818, 2890, 2379, 1096,
+    3679, 1328, 1901, 3162, 2747, 1730, 2253, 5, 1556, 2818, 2093, 3166, 2522, 
3410, 2287, 1701, 956, 3237, 620, 1596, 3300, 1307, 511, 3701, 1020, 2939, 
1362, 2532, 3208, 749, 3641, 160, 1522, 2624, 1095, 4086, 826, 2841, 3583, 
2173, 1727, 723, 2925, 1911, 2482, 3726, 863, 1962, 4028, 1111, 2835, 3773, 
2449, 2022, 582, 3278, 923, 2619, 2152, 4039, 92, 1934, 3145, 677,
+    2530, 53, 2303, 1003, 458, 3989, 739, 3321, 1064, 369, 3556, 877, 1900, 
426, 3876, 1, 3617, 2106, 1197, 2805, 3634, 857, 2706, 1504, 2418, 682, 3868, 
20, 1139, 1688, 2333, 3311, 2907, 1945, 265, 2385, 3433, 1601, 636, 2620, 3095, 
4044, 386, 3382, 1184, 527, 2814, 3414, 2342, 465, 1889, 1343, 874, 3479, 1502, 
2233, 3689, 1385, 559, 2745, 1463, 3465, 376, 1718,
+    3217, 4045, 1580, 3612, 2525, 1228, 3018, 1958, 3725, 2358, 1361, 3996, 
1581, 3063, 1224, 2737, 1475, 2442, 3946, 191, 1796, 2128, 3975, 134, 1916, 
3318, 1597, 2071, 3749, 2672, 403, 1278, 602, 3745, 3220, 1374, 445, 2064, 
3830, 243, 1252, 2390, 1563, 2724, 3875, 1818, 1346, 165, 1650, 3264, 2680, 
117, 2998, 4081, 343, 2799, 9, 3122, 1743, 3724, 1040, 2231, 3842, 1209,
+    900, 398, 2851, 697, 1797, 3482, 293, 2679, 1649, 566, 2954, 91, 2697, 
714, 2060, 3211, 781, 480, 3040, 1038, 2611, 666, 2989, 3458, 1201, 2796, 548, 
2975, 839, 3121, 1850, 4001, 2208, 1631, 790, 2558, 2972, 1148, 3213, 1849, 
3624, 971, 2102, 108, 772, 3101, 2589, 3777, 1042, 656, 3907, 2097, 1615, 2540, 
805, 1935, 1231, 3494, 2451, 268, 2995, 750, 2682, 2020,
+    3024, 1392, 2124, 3279, 106, 2217, 1387, 822, 3214, 3825, 2160, 1000, 
2395, 3691, 228, 4038, 1872, 3413, 1608, 2225, 3536, 303, 1653, 886, 2541, 224, 
4037, 2252, 1428, 172, 3504, 958, 2848, 113, 3628, 1834, 3979, 19, 2317, 779, 
2797, 518, 3174, 3549, 1482, 2266, 444, 2014, 3555, 2439, 1213, 3113, 535, 
1135, 3204, 3858, 2309, 931, 623, 2009, 3359, 1566, 140, 3550,
+    1808, 3872, 2488, 1152, 3764, 2892, 3960, 2412, 353, 1223, 1825, 3444, 
3116, 1717, 1082, 2313, 1280, 2661, 82, 3852, 1389, 3200, 2330, 3812, 2038, 
3581, 1728, 1039, 3339, 2427, 586, 2580, 1238, 3328, 2280, 1047, 595, 2662, 
1363, 3338, 1620, 3934, 2497, 1881, 1054, 3954, 3215, 864, 2887, 1801, 320, 
3519, 2378, 3704, 1753, 424, 2958, 1660, 4005, 2601, 1116, 3912, 2381, 573,
+    2740, 200, 828, 1667, 432, 1931, 1035, 1616, 3598, 2640, 728, 264, 1437, 
557, 3501, 2966, 372, 3734, 974, 1978, 758, 2719, 1145, 452, 1433, 725, 2681, 
408, 3843, 1918, 1547, 3906, 1996, 503, 1456, 3019, 3493, 1700, 3742, 355, 
2134, 176, 1311, 615, 2867, 315, 1680, 1314, 8, 3297, 1494, 783, 1950, 83, 
2656, 1382, 3561, 138, 2834, 1404, 330, 1904, 3156, 1027,
+    1357, 3381, 3041, 3666, 2729, 734, 3415, 177, 3051, 2021, 4079, 2823, 
3775, 2186, 2616, 869, 1668, 3148, 2367, 3315, 393, 4075, 1870, 2920, 3343, 
2362, 3188, 1303, 2782, 825, 3171, 259, 2905, 3717, 2538, 184, 2074, 838, 2860, 
2407, 1024, 3496, 3008, 3706, 1985, 2349, 3623, 2582, 4058, 2184, 2694, 3873, 
2964, 990, 3346, 690, 2033, 1066, 2201, 3490, 2971, 718, 3700, 2188,
+    4061, 391, 1989, 2325, 1430, 3150, 2125, 2526, 592, 1403, 976, 2351, 1165, 
1851, 114, 3921, 2063, 613, 1358, 2785, 1623, 2254, 25, 3542, 1045, 246, 1852, 
3554, 87, 2243, 3615, 1169, 727, 1705, 968, 3957, 3185, 1251, 500, 4063, 1751, 
2622, 842, 1519, 90, 3393, 819, 490, 1874, 999, 571, 1275, 2271, 1586, 4040, 
2448, 3126, 3731, 436, 885, 1708, 2421, 24, 1599,
+    889, 2563, 1199, 645, 70, 4013, 1237, 3723, 1694, 3499, 3, 3266, 484, 
2997, 3390, 1233, 2842, 3687, 152, 3480, 1084, 3698, 881, 2490, 1542, 3992, 
2209, 692, 1690, 3022, 1470, 2625, 2114, 3512, 2359, 381, 2684, 1897, 3368, 
1395, 3080, 289, 2065, 3981, 2758, 1141, 3097, 1472, 2870, 3352, 3707, 225, 
3159, 505, 1895, 214, 1222, 1774, 2686, 3978, 3275, 1196, 3518, 2825,
+    3270, 1720, 3796, 3466, 2650, 1841, 298, 899, 2862, 2091, 2671, 1744, 
3735, 801, 1560, 349, 2262, 903, 1833, 2524, 512, 3117, 1793, 2827, 476, 3038, 
1216, 2550, 3826, 980, 431, 4048, 35, 2992, 1265, 1595, 765, 3675, 76, 2247, 
696, 3456, 1254, 2452, 664, 1757, 2133, 3750, 145, 2332, 1554, 1981, 3580, 
2712, 868, 3640, 2919, 638, 2275, 1427, 309, 2595, 2006, 492,
+    2226, 178, 2911, 836, 1528, 3028, 2240, 3327, 404, 3970, 707, 1294, 2464, 
2131, 4032, 2600, 3319, 1406, 2913, 3974, 2156, 1425, 221, 3877, 2017, 811, 
3662, 272, 3287, 1988, 2408, 3357, 1746, 598, 3239, 3823, 2182, 2934, 1078, 
2604, 3840, 1697, 2906, 413, 3210, 3880, 331, 2644, 1260, 848, 3042, 2535, 
1077, 1438, 3261, 2365, 1561, 3799, 85, 3082, 1876, 674, 3932, 1101,
+    3644, 1344, 1943, 2401, 390, 3835, 1048, 2572, 1541, 1133, 3075, 3584, 
308, 2889, 1065, 1869, 601, 3783, 282, 1181, 736, 3312, 2368, 1126, 3383, 1675, 
2734, 1426, 628, 2873, 1317, 843, 2717, 2048, 1004, 2536, 333, 1782, 3295, 
1517, 219, 2153, 815, 3502, 1579, 2268, 987, 3409, 1780, 4018, 354, 665, 3914, 
47, 1956, 456, 1006, 2010, 3406, 1130, 3621, 2894, 1549, 3092,
+    2485, 640, 3993, 3179, 1270, 3436, 585, 1925, 3757, 2304, 136, 1976, 1486, 
646, 3520, 50, 3155, 1637, 2435, 3522, 1937, 2756, 3748, 661, 2224, 58, 3230, 
2357, 1830, 3892, 170, 3607, 1447, 3949, 190, 3392, 1336, 584, 4010, 918, 3016, 
3670, 1155, 2406, 52, 1304, 3009, 607, 2085, 2699, 3205, 1848, 2291, 3402, 
2764, 3865, 3048, 2508, 735, 2710, 443, 2341, 897, 263,
+    1785, 2769, 983, 56, 2197, 1685, 2703, 202, 2944, 810, 3377, 2626, 3787, 
3047, 2055, 1236, 2752, 2122, 945, 3093, 96, 1624, 439, 3014, 1388, 4015, 977, 
448, 3506, 1098, 2242, 3026, 506, 2361, 2952, 1862, 3619, 2790, 1992, 2483, 
525, 1868, 2652, 4093, 1998, 3595, 2478, 3816, 122, 1412, 929, 3716, 1166, 
1648, 813, 1300, 199, 1489, 3998, 1771, 1310, 3808, 2052, 3423,
+    434, 3712, 1625, 3558, 2955, 853, 4019, 1348, 3511, 1732, 1246, 487, 934, 
1672, 2510, 3965, 788, 3711, 396, 1369, 4090, 1055, 2603, 1879, 3528, 2518, 
2067, 3005, 1516, 2588, 751, 1740, 3418, 1131, 1576, 686, 2296, 1118, 18, 3263, 
1365, 3401, 294, 737, 3177, 410, 867, 1633, 2963, 3579, 2375, 252, 2881, 479, 
2471, 3576, 2180, 3306, 332, 2255, 3035, 41, 2648, 1396,
+    2929, 2230, 1219, 2512, 446, 2008, 3189, 2388, 626, 2164, 2831, 4047, 
2376, 174, 3272, 368, 1469, 3226, 2578, 1991, 2874, 2263, 3681, 876, 188, 1239, 
683, 3776, 226, 3183, 4083, 2148, 63, 2649, 3859, 299, 3086, 3933, 1585, 2185, 
3767, 988, 1707, 2908, 1407, 1844, 2771, 2245, 1161, 560, 1755, 3376, 2051, 
4064, 3135, 1832, 652, 2853, 1051, 3649, 760, 3290, 1105, 3945,
+    872, 154, 3207, 713, 3780, 1453, 281, 1087, 3695, 30, 3299, 1919, 1400, 
3551, 1119, 1890, 2314, 618, 1703, 3428, 724, 295, 3146, 1557, 3341, 2896, 
1683, 2723, 1974, 1017, 541, 1380, 3720, 804, 3280, 2082, 997, 2567, 777, 2961, 
213, 2707, 2328, 3632, 1025, 3891, 3304, 255, 4003, 3108, 2587, 1323, 743, 
1479, 105, 1013, 3901, 1618, 2044, 2627, 1465, 1846, 576, 1994,
+    2560, 3521, 1742, 2118, 2800, 3404, 1783, 2609, 2968, 1582, 1022, 412, 
2713, 687, 2976, 3857, 2761, 3620, 62, 1108, 3844, 1340, 2100, 540, 2345, 3925, 
405, 3457, 1319, 2468, 3362, 2815, 1867, 2372, 1281, 1714, 3690, 482, 3498, 
1842, 1285, 3994, 558, 2039, 81, 2499, 678, 1481, 1923, 964, 12, 3824, 2980, 
2205, 2762, 3432, 2398, 181, 3247, 462, 4094, 2350, 3589, 3089,
+    1555, 1094, 4041, 247, 1267, 908, 3959, 2041, 732, 3860, 2343, 3132, 3769, 
2144, 1621, 237, 912, 1329, 3025, 2146, 2642, 1775, 3721, 2746, 1121, 1953, 
902, 2285, 130, 3671, 1659, 278, 3153, 522, 2721, 123, 2996, 1466, 2380, 377, 
3231, 873, 1510, 3476, 3123, 1250, 2147, 3650, 2839, 3451, 2323, 1122, 3545, 
379, 1765, 1218, 603, 3768, 1360, 938, 2885, 133, 1245, 363,
+    2364, 554, 2743, 3344, 2474, 530, 3112, 169, 1297, 3430, 536, 1741, 98, 
1043, 2574, 3253, 2246, 1854, 4022, 510, 3283, 204, 858, 3398, 36, 3118, 1478, 
3794, 2986, 706, 2176, 922, 3559, 1097, 3976, 3322, 2149, 1160, 2810, 3883, 
2007, 2513, 2953, 328, 1721, 3793, 422, 2566, 807, 329, 1638, 1967, 648, 2520, 
3727, 3109, 2116, 2927, 2491, 1939, 3365, 1709, 2728, 3815,
+    2037, 3120, 831, 1405, 1896, 3592, 1622, 2369, 2864, 2151, 1107, 2542, 
3532, 1410, 3917, 427, 3568, 709, 2509, 1503, 1037, 2973, 2436, 1604, 4035, 
2594, 563, 1819, 2659, 1234, 4004, 2565, 1511, 2273, 1823, 336, 882, 3772, 575, 
1628, 171, 3570, 1120, 2260, 2716, 935, 3064, 1806, 1342, 3144, 3900, 2744, 
3296, 985, 1546, 238, 896, 1663, 305, 3660, 695, 2213, 960, 3407,
+    144, 1795, 3894, 2267, 51, 2708, 1023, 3818, 366, 1821, 4087, 2985, 755, 
2057, 2912, 949, 1583, 2774, 231, 3447, 2258, 3866, 1982, 672, 1225, 2077, 
3320, 1062, 370, 3241, 1968, 7, 3068, 681, 3631, 2573, 1567, 3175, 2321, 1067, 
3070, 722, 1856, 3744, 642, 1471, 4084, 131, 3514, 2443, 531, 1227, 155, 2265, 
4024, 2658, 3326, 3910, 1168, 3078, 1530, 3956, 489, 1424,
+    3647, 1203, 420, 2924, 3755, 719, 3248, 1376, 3067, 890, 196, 1559, 3269, 
270, 2432, 1885, 3212, 1164, 3778, 1752, 579, 1338, 344, 3585, 3017, 288, 3658, 
2371, 3882, 1691, 611, 2789, 3809, 1339, 389, 2950, 2015, 59, 3548, 2751, 2158, 
4011, 1352, 29, 3388, 2370, 2812, 1946, 954, 2110, 1558, 2947, 3573, 1909, 
1326, 679, 1853, 2312, 551, 2702, 33, 2414, 3209, 2824,
+    2547, 2143, 3379, 966, 1492, 1979, 2479, 463, 2194, 3657, 2738, 2318, 
1261, 3713, 604, 4002, 11, 2192, 2967, 919, 2607, 3369, 2837, 1676, 2539, 984, 
1568, 93, 2901, 1318, 3538, 1041, 2216, 1756, 3454, 1030, 4050, 1402, 798, 
1723, 311, 3277, 2546, 2886, 2043, 461, 1206, 3677, 361, 3260, 3988, 809, 2605, 
470, 3007, 3517, 102, 3221, 1398, 2062, 3611, 1134, 1928, 865,
+    4060, 621, 1710, 2606, 3510, 317, 4017, 1682, 3329, 1159, 1940, 654, 3461, 
1789, 1015, 2691, 1455, 3599, 374, 1947, 4069, 71, 2126, 763, 3961, 2278, 3161, 
1997, 824, 2623, 2080, 244, 3257, 780, 2732, 2308, 545, 3351, 2476, 3806, 1204, 
588, 1591, 963, 3610, 1699, 754, 3049, 2651, 1106, 65, 2221, 1644, 3821, 1100, 
2463, 1614, 3801, 965, 2965, 715, 3394, 1593, 212,
+};
+
+#endif /* BLUE_NOISE_64X64_H */
diff --git a/pixman/dither/make-blue-noise.c b/pixman/dither/make-blue-noise.c
new file mode 100644
index 0000000..45e48a6
--- /dev/null
+++ b/pixman/dither/make-blue-noise.c
@@ -0,0 +1,679 @@
+/* Blue noise generation using the void-and-cluster method as described in
+ *
+ *     The void-and-cluster method for dither array generation
+ *     Ulichney, Robert A (1993)
+ *
+ *     http://cv.ulichney.com/papers/1993-void-cluster.pdf
+ *
+ * Note that running with openmp (-DUSE_OPENMP) will trigger additional
+ * randomness due to computing reductions in parallel, and is not recommended
+ * unless generating very large dither arrays.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+#include <stdio.h>
+
+/* Booleans and utility functions */
+
+#ifndef TRUE
+#   define TRUE 1
+#endif
+
+#ifndef FALSE
+#   define FALSE 0
+#endif
+
+typedef int bool_t;
+
+int
+imin (int x, int y)
+{
+    return x < y ? x : y;
+}
+
+/* Memory allocation */
+void *
+malloc_abc (unsigned int a, unsigned int b, unsigned int c)
+{
+    if (a >= INT32_MAX / b)
+       return NULL;
+    else if (a * b >= INT32_MAX / c)
+       return NULL;
+    else
+       return malloc (a * b * c);
+}
+
+/* Random number generation */
+typedef uint32_t xorwow_state_t[5];
+
+uint32_t
+xorwow_next (xorwow_state_t *state)
+{
+    uint32_t s = (*state)[0],
+    t = (*state)[3];
+    (*state)[3] = (*state)[2];
+    (*state)[2] = (*state)[1];
+    (*state)[1] = s;
+
+    t ^= t >> 2;
+    t ^= t << 1;
+    t ^= s ^ (s << 4);
+
+    (*state)[0] = t;
+    (*state)[4] += 362437;
+
+    return t + (*state)[4];
+}
+
+float
+xorwow_float (xorwow_state_t *s)
+{
+    return (xorwow_next (s) >> 9) / (float)((1 << 23) - 1);
+}
+
+/* Floating point matrices
+ *
+ * Used to cache the cluster sizes.
+ */
+typedef struct matrix_t {
+    int width;
+    int height;
+    float *buffer;
+} matrix_t;
+
+bool_t
+matrix_init (matrix_t *matrix, int width, int height)
+{
+    float *buffer;
+
+    if (!matrix)
+       return FALSE;
+
+    buffer = malloc_abc (width, height, sizeof (float));
+
+    if (!buffer)
+       return FALSE;
+
+    matrix->buffer = buffer;
+    matrix->width  = width;
+    matrix->height = height;
+
+    return TRUE;
+}
+
+bool_t
+matrix_copy (matrix_t *dst, matrix_t const *src)
+{
+    float *srcbuf = src->buffer,
+         *srcend = src->buffer + src->width * src->height,
+         *dstbuf = dst->buffer;
+
+    if (dst->width != src->width || dst->height != src->height)
+       return FALSE;
+
+    while (srcbuf < srcend)
+       *dstbuf++ = *srcbuf++;
+
+    return TRUE;
+}
+
+float *
+matrix_get (matrix_t *matrix, int x, int y)
+{
+    return &matrix->buffer[y * matrix->width + x];
+}
+
+void
+matrix_destroy (matrix_t *matrix)
+{
+    free (matrix->buffer);
+}
+
+/* Binary patterns */
+typedef struct pattern_t {
+    int width;
+    int height;
+    bool_t *buffer;
+} pattern_t;
+
+bool_t
+pattern_init (pattern_t *pattern, int width, int height)
+{
+    bool_t *buffer;
+
+    if (!pattern)
+       return FALSE;
+
+    buffer = malloc_abc (width, height, sizeof (bool_t));
+
+    if (!buffer)
+       return FALSE;
+
+    pattern->buffer = buffer;
+    pattern->width  = width;
+    pattern->height = height;
+
+    return TRUE;
+}
+
+bool_t
+pattern_copy (pattern_t *dst, pattern_t const *src)
+{
+    bool_t *srcbuf = src->buffer,
+          *srcend = src->buffer + src->width * src->height,
+          *dstbuf = dst->buffer;
+
+    if (dst->width != src->width || dst->height != src->height)
+       return FALSE;
+
+    while (srcbuf < srcend)
+       *dstbuf++ = *srcbuf++;
+
+    return TRUE;
+}
+
+bool_t *
+pattern_get (pattern_t *pattern, int x, int y)
+{
+    return &pattern->buffer[y * pattern->width + x];
+}
+
+void
+pattern_fill_white_noise (pattern_t *pattern, float fraction,
+                         xorwow_state_t *s)
+{
+    bool_t *buffer = pattern->buffer;
+    bool_t *end    = buffer + (pattern->width * pattern->height);
+
+    while (buffer < end)
+       *buffer++ = xorwow_float (s) < fraction;
+}
+
+void
+pattern_destroy (pattern_t *pattern)
+{
+    free (pattern->buffer);
+}
+
+/* Dither arrays */
+typedef struct array_t {
+    int width;
+    int height;
+    uint32_t *buffer;
+} array_t;
+
+bool_t
+array_init (array_t *array, int width, int height)
+{
+    uint32_t *buffer;
+
+    if (!array)
+       return FALSE;
+
+    buffer = malloc_abc (width, height, sizeof (uint32_t));
+
+    if (!buffer)
+       return FALSE;
+
+    array->buffer = buffer;
+    array->width  = width;
+    array->height = height;
+
+    return TRUE;
+}
+
+uint32_t *
+array_get (array_t *array, int x, int y)
+{
+    return &array->buffer[y * array->width + x];
+}
+
+bool_t
+array_save_ppm (array_t *array, const char *filename)
+{
+    FILE *f = fopen(filename, "wb");
+
+    int i   = 0;
+    int bpp = 2;
+    uint8_t buffer[1024];
+
+    if (!f)
+       return FALSE;
+
+    if (array->width * array->height - 1 < 256)
+       bpp = 1;
+
+    fprintf(f, "P5 %d %d %d\n", array->width, array->height,
+           array->width * array->height - 1);
+    while (i < array->width * array->height)
+    {
+           int j = 0;
+           for (; j < 1024 / bpp && j < array->width * array->height; ++j)
+           {
+                   uint32_t v = array->buffer[i + j];
+                   if (bpp == 2)
+                   {
+                       buffer[2 * j] = v & 0xff;
+                       buffer[2 * j + 1] = (v & 0xff00) >> 8;
+                   } else {
+                       buffer[j] = v;
+                   }
+           }
+
+           fwrite((void *)buffer, bpp, j, f);
+           i += j;
+    }
+
+    if (fclose(f) != 0)
+       return FALSE;
+
+    return TRUE;
+}
+
+bool_t
+array_save (array_t *array, const char *filename)
+{
+    int x, y;
+    FILE *f = fopen(filename, "wb");
+
+    if (!f)
+       return FALSE;
+
+    fprintf (f, 
+"/* WARNING: This file is generated by make-blue-noise.c\n"
+" * Please edit that file instead of this one.\n"
+" */\n"
+"\n"
+"#ifndef BLUE_NOISE_%dX%d_H\n"
+"#define BLUE_NOISE_%dX%d_H\n"
+"\n"
+"#include <stdint.h>\n"
+"\n", array->width, array->height, array->width, array->height);
+
+    fprintf (f, "static const uint32_t dither_blue_noise_%dx%d[%d] = {\n",
+            array->width, array->height, array->width * array->height);
+
+    for (y = 0; y < array->height; ++y)
+    {
+       fprintf (f, "    ");
+       for (x = 0; x < array->width; ++x)
+       {
+           if (x != 0)
+               fprintf (f, ", ");
+
+           fprintf (f, "%d", *array_get (array, x, y));
+       }
+
+       fprintf (f, ",\n");
+    }
+    fprintf (f, "};\n");
+
+    fprintf (f, "\n#endif /* BLUE_NOISE_%dX%d_H */\n",
+            array->width, array->height);
+
+    if (fclose(f) != 0)
+       return FALSE;
+
+    return TRUE;
+}
+
+void
+array_destroy (array_t *array)
+{
+    free (array->buffer);
+}
+
+/* Dither array generation */
+bool_t
+compute_cluster_sizes (pattern_t *pattern, matrix_t *matrix)
+{
+    int width  = pattern->width,
+       height = pattern->height;
+
+    if (matrix->width != width || matrix->height != height)
+       return FALSE;
+
+    int px, py, qx, qy, dx, dy;
+    float tsqsi = 2.f * 1.5f * 1.5f;
+
+#ifdef USE_OPENMP
+#pragma omp parallel for default (none) \
+    private (py, px, qy, qx, dx, dy) \
+    shared (height, width, pattern, matrix, tsqsi)
+#endif
+    for (py = 0; py < height; ++py)
+    {
+       for (px = 0; px < width; ++px)
+       {
+           bool_t pixel = *pattern_get (pattern, px, py);
+           float dist   = 0.f;
+
+           for (qx = 0; qx < width; ++qx)
+           {
+               dx = imin (abs (qx - px), width - abs (qx - px));
+               dx = dx * dx;
+
+               for (qy = 0; qy < height; ++qy)
+               {
+                   dy = imin (abs (qy - py), height - abs (qy - py));
+                   dy = dy * dy;
+
+                   dist += (pixel == *pattern_get (pattern, qx, qy))
+                       * expf (- (dx + dy) / tsqsi);
+               }
+           }
+
+           *matrix_get (matrix, px, py) = dist;
+       }
+    }
+
+    return TRUE;
+}
+
+bool_t
+swap_pixel (pattern_t *pattern, matrix_t *matrix, int x, int y)
+{
+    int width  = pattern->width,
+       height = pattern->height;
+
+    bool_t new;
+
+    float f,
+          dist  = 0.f,
+         tsqsi = 2.f * 1.5f * 1.5f;
+
+    int px, py, dx, dy;
+    bool_t b;
+
+    new = !*pattern_get (pattern, x, y);
+    *pattern_get (pattern, x, y) = new;
+
+    if (matrix->width != width || matrix->height != height)
+       return FALSE;
+
+
+#ifdef USE_OPENMP
+#pragma omp parallel for reduction (+:dist) default (none) \
+    private (px, py, dx, dy, b, f) \
+    shared (x, y, width, height, pattern, matrix, new, tsqsi)
+#endif
+    for (py = 0; py < height; ++py)
+    {
+       dy = imin (abs (py - y), height - abs (py - y));
+       dy = dy * dy;
+
+       for (px = 0; px < width; ++px)
+       {
+           dx = imin (abs (px - x), width - abs (px - x));
+           dx = dx * dx;
+
+           b = (*pattern_get (pattern, px, py) == new);
+           f = expf (- (dx + dy) / tsqsi);
+           *matrix_get (matrix, px, py) += (2 * b - 1) * f;
+
+           dist += b * f;
+       }
+    }
+
+    *matrix_get (matrix, x, y) = dist;
+    return TRUE;
+}
+
+void
+largest_cluster (pattern_t *pattern, matrix_t *matrix,
+                bool_t pixel, int *xmax, int *ymax)
+{
+    int width       = pattern->width,
+       height      = pattern->height;
+
+    int   x, y;
+
+    float vmax = -INFINITY;
+
+#ifdef USE_OPENMP
+#pragma omp parallel default (none) \
+    private (x, y) \
+    shared (height, width, pattern, matrix, pixel, xmax, ymax, vmax)
+#endif
+    {
+       int xbest = -1,
+           ybest = -1;
+
+#ifdef USE_OPENMP
+       float vbest = -INFINITY;
+
+#pragma omp for reduction (max: vmax) collapse (2)
+#endif
+       for (y = 0; y < height; ++y)
+       {
+           for (x = 0; x < width; ++x)
+           {
+               if (*pattern_get (pattern, x, y) != pixel)
+                   continue;
+
+               if (*matrix_get (matrix, x, y) > vmax)
+               {
+                   vmax = *matrix_get (matrix, x, y);
+#ifdef USE_OPENMP
+                   vbest = vmax;
+#endif
+                   xbest = x;
+                   ybest = y;
+               }
+           }
+       }
+
+#ifdef USE_OPENMP
+#pragma omp barrier
+#pragma omp critical
+       {
+           if (vmax == vbest)
+           {
+               *xmax = xbest;
+               *ymax = ybest;
+           }
+       }
+#else
+       *xmax = xbest;
+       *ymax = ybest;
+#endif
+    }
+
+    assert (vmax > -INFINITY);
+}
+
+void
+generate_initial_binary_pattern (pattern_t *pattern, matrix_t *matrix)
+{
+    int xcluster = 0,
+       ycluster = 0,
+       xvoid    = 0,
+       yvoid    = 0;
+
+    for (;;)
+    {
+       largest_cluster (pattern, matrix, TRUE, &xcluster, &ycluster);
+       assert (*pattern_get (pattern, xcluster, ycluster) == TRUE);
+       swap_pixel (pattern, matrix, xcluster, ycluster);
+
+       largest_cluster (pattern, matrix, FALSE, &xvoid, &yvoid);
+       assert (*pattern_get (pattern, xvoid, yvoid) == FALSE);
+       swap_pixel (pattern, matrix, xvoid, yvoid);
+
+       if (xcluster == xvoid && ycluster == yvoid)
+           return;
+    }
+}
+
+bool_t
+generate_dither_array (array_t *array,
+                      pattern_t const *prototype, matrix_t const *matrix,
+                      pattern_t *temp_pattern, matrix_t *temp_matrix)
+{
+    int width        = prototype->width,
+       height       = prototype->height;
+
+    int x, y, rank;
+
+    int initial_rank = 0;
+
+    if (array->width != width || array->height != height)
+       return FALSE;
+
+    // Make copies of the prototype and associated sizes matrix since we will
+    // trash them
+    if (!pattern_copy (temp_pattern, prototype))
+       return FALSE;
+
+    if (!matrix_copy (temp_matrix, matrix))
+       return FALSE;
+
+    // Compute initial rank
+    for (y = 0; y < height; ++y)
+    {
+       for (x = 0; x < width; ++x)
+       {
+           if (*pattern_get (temp_pattern, x, y))
+               initial_rank += 1;
+
+           *array_get (array, x, y) = 0;
+       }
+    }
+
+    // Phase 1
+    for (rank = initial_rank; rank > 0; --rank)
+    {
+       largest_cluster (temp_pattern, temp_matrix, TRUE, &x, &y);
+       swap_pixel (temp_pattern, temp_matrix, x, y);
+       *array_get (array, x, y) = rank - 1;
+    }
+
+    // Make copies again for phases 2 & 3
+    if (!pattern_copy (temp_pattern, prototype))
+       return FALSE;
+
+    if (!matrix_copy (temp_matrix, matrix))
+       return FALSE;
+
+    // Phase 2 & 3
+    for (rank = initial_rank; rank < width * height; ++rank)
+    {
+       largest_cluster (temp_pattern, temp_matrix, FALSE, &x, &y);
+       swap_pixel (temp_pattern, temp_matrix, x, y);
+       *array_get (array, x, y) = rank;
+    }
+
+    return TRUE;
+}
+
+bool_t
+generate (int size, xorwow_state_t *s,
+         char const *c_filename, char const *ppm_filename)
+{
+    bool_t ok = TRUE;
+
+    pattern_t prototype, temp_pattern;
+    array_t   array;
+    matrix_t  matrix, temp_matrix;
+
+    printf ("Generating %dx%d blue noise...\n", size, size);
+
+    if (!pattern_init (&prototype, size, size))
+       return FALSE;
+
+    if (!pattern_init (&temp_pattern, size, size))
+    {
+       pattern_destroy (&prototype);
+       return FALSE;
+    }
+
+    if (!matrix_init (&matrix, size, size))
+    {
+       pattern_destroy (&temp_pattern);
+       pattern_destroy (&prototype);
+       return FALSE;
+    }
+
+    if (!matrix_init (&temp_matrix, size, size))
+    {
+       matrix_destroy (&matrix);
+       pattern_destroy (&temp_pattern);
+       pattern_destroy (&prototype);
+       return FALSE;
+    }
+
+    if (!array_init (&array, size, size))
+    {
+       matrix_destroy (&temp_matrix);
+       matrix_destroy (&matrix);
+       pattern_destroy (&temp_pattern);
+       pattern_destroy (&prototype);
+       return FALSE;
+    }
+
+    printf("Filling initial binary pattern with white noise...\n");
+    pattern_fill_white_noise (&prototype, .1, s);
+
+    printf("Initializing cluster sizes...\n");
+    if (!compute_cluster_sizes (&prototype, &matrix))
+    {
+       fprintf (stderr, "Error while computing cluster sizes\n");
+       ok = FALSE;
+       goto out;
+    }
+
+    printf("Generating initial binary pattern...\n");
+    generate_initial_binary_pattern (&prototype, &matrix);
+
+    printf("Generating dither array...\n");
+    if (!generate_dither_array (&array, &prototype, &matrix,
+                        &temp_pattern, &temp_matrix))
+    {
+       fprintf (stderr, "Error while generating dither array\n");
+       ok = FALSE;
+       goto out;
+    }
+
+    printf("Saving dither array...\n");
+    if (!array_save (&array, c_filename))
+    {
+       fprintf (stderr, "Error saving dither array\n");
+       ok = FALSE;
+       goto out;
+    }
+
+#if SAVE_PPM
+    if (!array_save_ppm (&array, ppm_filename))
+    {
+       fprintf (stderr, "Error saving dither array PPM\n");
+       ok = FALSE;
+       goto out;
+    }
+#else
+    (void)ppm_filename;
+#endif
+
+    printf("All done!\n");
+
+out:
+    array_destroy (&array);
+    matrix_destroy (&temp_matrix);
+    matrix_destroy (&matrix);
+    pattern_destroy (&temp_pattern);
+    pattern_destroy (&prototype);
+    return ok;
+}
+
+int
+main (void)
+{
+    xorwow_state_t s = {1185956906, 12385940, 983948, 349208051, 901842};
+
+    if (!generate (64, &s, "blue-noise-64x64.h", "blue-noise-64x64.ppm"))
+       return -1;
+
+    return 0;
+}
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index fe3919b..3b2822c 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -35,6 +35,7 @@
 #include "pixman-private.h"
 #include "pixman-combine32.h"
 #include "pixman-inlines.h"
+#include "dither/blue-noise-64x64.h"
 
 /* Fetch functions */
 
@@ -1048,6 +1049,15 @@ dest_write_back_narrow (pixman_iter_t *iter)
     iter->y++;
 }
 
+static const float
+dither_factor_blue_noise_64 (int x, int y)
+{
+    float m = dither_blue_noise_64x64[(y % 64) * 64 + x % 64];
+    float f = 64 * 64;
+
+    return m * (1. / f) + (1. / (2. * f));
+}
+
 static const float
 dither_factor_bayer_8 (int x, int y)
 {
@@ -1168,9 +1178,13 @@ dest_write_back_wide (pixman_iter_t *iter)
     case PIXMAN_DITHER_NONE:
        break;
 
-    case PIXMAN_DITHER_FAST:
     case PIXMAN_DITHER_GOOD:
     case PIXMAN_DITHER_BEST:
+    case PIXMAN_DITHER_ORDERED_BLUE_NOISE_64:
+       buffer = dither_apply_ordered (iter, dither_factor_blue_noise_64);
+       break;
+
+    case PIXMAN_DITHER_FAST:
     case PIXMAN_DITHER_ORDERED_BAYER_8:
        buffer = dither_apply_ordered (iter, dither_factor_bayer_8);
        break;
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 1f63f55..62dfb6a 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -292,6 +292,7 @@ typedef enum
     PIXMAN_DITHER_GOOD,
     PIXMAN_DITHER_BEST,
     PIXMAN_DITHER_ORDERED_BAYER_8,
+    PIXMAN_DITHER_ORDERED_BLUE_NOISE_64,
 } pixman_dither_t;
 
 typedef enum
diff --git a/test/tolerance-test.c b/test/tolerance-test.c
index 011cdb4..3c6e818 100644
--- a/test/tolerance-test.c
+++ b/test/tolerance-test.c
@@ -79,6 +79,7 @@ static const pixman_op_t operators[] =
 static const pixman_dither_t dithers[] =
 {
     PIXMAN_DITHER_ORDERED_BAYER_8,
+    PIXMAN_DITHER_ORDERED_BLUE_NOISE_64,
 };
 
 #define RANDOM_ELT(array)                                               \
diff --git a/test/utils.c b/test/utils.c
index 9ce7a6c..2e3b547 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1193,6 +1193,7 @@ static const dither_entry_t dither_list[] =
      */
 
     ENTRY (ORDERED_BAYER_8),
+    ENTRY (ORDERED_BLUE_NOISE_64),
     ENTRY (NONE),
 
 #undef ENTRY
-- 
2.21.0


_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to