Newer
Older
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
(I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \
(I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \
(I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \
(I[4] = (T)(img)(x,_p4##y,z,c)), \
(I[13] = (T)(img)(x,_p3##y,z,c)), \
(I[22] = (T)(img)(x,_p2##y,z,c)), \
(I[31] = (T)(img)(x,_p1##y,z,c)), \
(I[40] = (T)(img)(x,y,z,c)), \
(I[49] = (T)(img)(x,_n1##y,z,c)), \
(I[58] = (T)(img)(x,_n2##y,z,c)), \
(I[67] = (T)(img)(x,_n3##y,z,c)), \
(I[76] = (T)(img)(x,_n4##y,z,c)), \
(I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \
(I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \
(I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \
(I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \
(I[41] = (T)(img)(_n1##x,y,z,c)), \
(I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \
(I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \
(I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \
(I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \
(I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \
(I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \
(I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \
(I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \
(I[42] = (T)(img)(_n2##x,y,z,c)), \
(I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \
(I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \
(I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \
(I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \
(I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \
(I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \
(I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \
(I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \
(I[43] = (T)(img)(_n3##x,y,z,c)), \
(I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \
(I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \
(I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \
(I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \
x + 4>=(img).width()?(img).width() - 1:x + 4); \
x<=(int)(x1) && ((_n4##x<(img).width() && ( \
(I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \
(I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \
(I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \
(I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \
(I[44] = (T)(img)(_n4##x,y,z,c)), \
(I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \
(I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \
(I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \
(I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \
_n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \
I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \
I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \
I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \
I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \
I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \
I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \
I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \
I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \
I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \
I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \
I[79] = I[80], \
_p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x)
#define cimg_for2x2x2(img,x,y,z,c,I,T) \
cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \
_n1##x = (int)( \
(I[0] = (T)(img)(0,y,z,c)), \
(I[2] = (T)(img)(0,_n1##y,z,c)), \
(I[4] = (T)(img)(0,y,_n1##z,c)), \
(I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \
1>=(img)._width?(img).width() - 1:1); \
(_n1##x<(img).width() && ( \
(I[1] = (T)(img)(_n1##x,y,z,c)), \
(I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \
(I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \
(I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
x==--_n1##x; \
I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \
++x, ++_n1##x)
#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \
cimg_for_in2((img)._depth,z0,z1,z) cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
_n1##x = (int)( \
(I[0] = (T)(img)(x,y,z,c)), \
(I[2] = (T)(img)(x,_n1##y,z,c)), \
(I[4] = (T)(img)(x,y,_n1##z,c)), \
(I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \
x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \
x<=(int)(x1) && ((_n1##x<(img).width() && ( \
(I[1] = (T)(img)(_n1##x,y,z,c)), \
(I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \
(I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \
(I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
x==--_n1##x); \
I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \
++x, ++_n1##x)
#define cimg_for3x3x3(img,x,y,z,c,I,T) \
cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \
_p1##x = 0, \
_n1##x = (int)( \
(I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \
(I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \
(I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \
(I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \
(I[12] = I[13] = (T)(img)(0,y,z,c)), \
(I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \
(I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \
(I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \
(I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \
1>=(img)._width?(img).width() - 1:1); \
(_n1##x<(img).width() && ( \
(I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \
(I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \
(I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \
(I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \
(I[14] = (T)(img)(_n1##x,y,z,c)), \
(I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \
(I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \
(I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \
(I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
x==--_n1##x; \
I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \
I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \
I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \
_p1##x = x++, ++_n1##x)
#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \
cimg_for_in3((img)._depth,z0,z1,z) cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
_p1##x = x - 1<0?0:x - 1, \
_n1##x = (int)( \
(I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \
(I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \
(I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \
(I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \
(I[12] = (T)(img)(_p1##x,y,z,c)), \
(I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \
(I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \
(I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \
(I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \
(I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \
(I[4] = (T)(img)(x,y,_p1##z,c)), \
(I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \
(I[10] = (T)(img)(x,_p1##y,z,c)), \
(I[13] = (T)(img)(x,y,z,c)), \
(I[16] = (T)(img)(x,_n1##y,z,c)), \
(I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \
(I[22] = (T)(img)(x,y,_n1##z,c)), \
(I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \
x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \
x<=(int)(x1) && ((_n1##x<(img).width() && ( \
(I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \
(I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \
(I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \
(I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \
(I[14] = (T)(img)(_n1##x,y,z,c)), \
(I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \
(I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \
(I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \
(I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
x==--_n1##x); \
I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \
I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \
I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \
_p1##x = x++, ++_n1##x)
#define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l)
#define cimglist_for_in(list,l0,l1,l) \
for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width - 1; \
l<=_max##l; ++l)
#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn
// Macros used to display error messages when exceptions are thrown.
// You should not use these macros is your own code.
#define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::"
#define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']'
#define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::"
#define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type()
#define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::"
#define cimglist_instance _width,_allocated_width,_data,pixel_type()
/*------------------------------------------------
#
#
# Define cimg_library:: namespace
#
#
-------------------------------------------------*/
//! Contains <i>all classes and functions</i> of the \CImg library.
/**
This namespace is defined to avoid functions and class names collisions
that could happen with the inclusion of other C++ header files.
Anyway, it should not happen often and you should reasonnably start most of your
\CImg-based programs with
\code
#include "CImg.h"
using namespace cimg_library;
\endcode
to simplify the declaration of \CImg Library objects afterwards.
**/
namespace cimg_library_suffixed {
// Declare the four classes of the CImg Library.
template<typename T=float> struct CImg;
template<typename T=float> struct CImgList;
struct CImgDisplay;
struct CImgException;
// Declare cimg:: namespace.
// This is an uncomplete namespace definition here. It only contains some
// necessary stuff to ensure a correct declaration order of the classes and functions
// defined afterwards.
namespace cimg {
// Define ascii sequences for colored terminal output.
#ifdef cimg_use_vt100
static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 };
static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 };
static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 };
static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 };
static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 };
static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 };
static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 };
static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 };
static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 };
static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 };
static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 };
#else
static const char t_normal[] = { 0 };
static const char *const t_black = cimg::t_normal,
*const t_red = cimg::t_normal,
*const t_green = cimg::t_normal,
*const t_yellow = cimg::t_normal,
*const t_blue = cimg::t_normal,
*const t_magenta = cimg::t_normal,
*const t_cyan = cimg::t_normal,
*const t_white = cimg::t_normal,
*const t_bold = cimg::t_normal,
*const t_underscore = cimg::t_normal;
#endif
inline std::FILE* output(std::FILE *file=0);
inline void info();
//! Avoid warning messages due to unused parameters. Do nothing actually.
template<typename T>
inline void unused(const T&, ...) {}
// [internal] Lock/unlock a mutex for managing concurrent threads.
// 'lock_mode' can be { 0=unlock | 1=lock | 2=trylock }.
// 'n' can be in [0,31] but mutex range [0,15] is reserved by CImg.
inline int mutex(const unsigned int n, const int lock_mode=1);
inline unsigned int& _exception_mode(const unsigned int value, const bool is_set) {
static unsigned int mode = cimg_verbosity;
if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); }
return mode;
}
// Functions to return standard streams 'stdin', 'stdout' and 'stderr'.
inline FILE* _stdin(const bool throw_exception=true);
inline FILE* _stdout(const bool throw_exception=true);
inline FILE* _stderr(const bool throw_exception=true);
// Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character
// at the end of the string.
#if cimg_OS==2 && defined(_MSC_VER)
inline int _snprintf(char *const s, const size_t size, const char *const format, ...) {
va_list ap;
va_start(ap,format);
const int result = _vsnprintf(s,size,format,ap);
va_end(ap);
return result;
}
inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) {
int result = -1;
cimg::mutex(6);
if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap);
if (result==-1) result = _vscprintf(format,ap);
cimg::mutex(6,0);
return result;
}
// Mutex-protected version of sscanf, sprintf and snprintf.
// Used only MacOSX, as it seems those functions are not re-entrant on MacOSX.
#elif defined(__MACOSX__) || defined(__APPLE__)
inline int _sscanf(const char *const s, const char *const format, ...) {
cimg::mutex(6);
va_list args;
va_start(args,format);
const int result = std::vsscanf(s,format,args);
va_end(args);
cimg::mutex(6,0);
return result;
}
inline int _sprintf(char *const s, const char *const format, ...) {
cimg::mutex(6);
va_list args;
va_start(args,format);
const int result = std::vsprintf(s,format,args);
va_end(args);
cimg::mutex(6,0);
return result;
}
inline int _snprintf(char *const s, const size_t n, const char *const format, ...) {
cimg::mutex(6);
va_list args;
va_start(args,format);
const int result = std::vsnprintf(s,n,format,args);
va_end(args);
cimg::mutex(6,0);
return result;
}
inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) {
cimg::mutex(6);
const int result = std::vsnprintf(s,size,format,ap);
cimg::mutex(6,0);
return result;
}
#endif
//! Set current \CImg exception mode.
/**
The way error messages are handled by \CImg can be changed dynamically, using this function.
\param mode Desired exception mode. Possible values are:
- \c 0: Hide library messages (quiet mode).
- \c 1: Print library messages on the console.
- \c 2: Display library messages on a dialog window.
- \c 3: Do as \c 1 + add extra debug warnings (slow down the code!).
- \c 4: Do as \c 2 + add extra debug warnings (slow down the code!).
**/
inline unsigned int& exception_mode(const unsigned int mode) {
return _exception_mode(mode,true);
}
//! Return current \CImg exception mode.
/**
\note By default, return the value of configuration macro \c cimg_verbosity
**/
inline unsigned int& exception_mode() {
return _exception_mode(0,false);
}
//! Set current \CImg openmp mode.
/**
The way openmp-based methods are handled by \CImg can be changed dynamically, using this function.
\param mode Desired openmp mode. Possible values are:
- \c 0: Never parallelize.
- \c 1: Always parallelize.
- \c 2: Adaptive parallelization mode (default behavior).
**/
inline unsigned int& _openmp_mode(const unsigned int value, const bool is_set) {
static unsigned int mode = 2;
if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); }
return mode;
}
inline unsigned int& openmp_mode(const unsigned int mode) {
return _openmp_mode(mode,true);
}
//! Return current \CImg openmp mode.
inline unsigned int& openmp_mode() {
return _openmp_mode(0,false);
}
#define cimg_openmp_if(cond) if (cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))
// Display a simple dialog box, and wait for the user's response.
inline int dialog(const char *const title, const char *const msg, const char *const button1_label="OK",
const char *const button2_label=0, const char *const button3_label=0,
const char *const button4_label=0, const char *const button5_label=0,
const char *const button6_label=0, const bool centering=false);
// Evaluate math expression.
inline double eval(const char *const expression,
const double x=0, const double y=0, const double z=0, const double c=0);
}
/*---------------------------------------
#
# Define the CImgException structures
#
--------------------------------------*/
//! Instances of \c CImgException are thrown when errors are encountered in a \CImg function call.
/**
\par Overview
CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException).
CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead.
These classes can be:
- \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal.
This is the only \c non-derived exception class.
- \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid.
This is probably one of the most thrown exception by \CImg.
For instance, the following example throws a \c CImgArgumentException:
\code
CImg<float> img(100,100,1,3); // Define a 100x100 color image with float-valued pixels.
img.mirror('e'); // Try to mirror image along the (non-existing) 'e'-axis.
\endcode
- \b CImgDisplayException: Thrown when something went wrong during the display of images in CImgDisplay instances.
- \b CImgInstanceException: Thrown when an instance associated to a called \CImg method does not fit
the function requirements. For instance, the following example throws a \c CImgInstanceException:
\code
const CImg<float> img; // Define an empty image.
const float value = img.at(0); // Try to read first pixel value (does not exist).
\endcode
- \b CImgIOException: Thrown when an error occured when trying to load or save image files.
This happens when trying to read files that do not exist or with invalid formats.
For instance, the following example throws a \c CImgIOException:
\code
const CImg<float> img("missing_file.jpg"); // Try to load a file that does not exist.
\endcode
- \b CImgWarningException: Thrown only if configuration macro \c cimg_strict_warnings is set, and
when a \CImg function has to display a warning message (see cimg::warn()).
It is not recommended to throw CImgException instances by yourself,
since they are expected to be thrown only by \CImg.
When an error occurs in a library function call, \CImg may display error messages on the screen or on the
standard output, depending on the current \CImg exception mode.
The \CImg exception mode can be get and set by functions cimg::exception_mode() and
cimg::exception_mode(unsigned int).
\par Exceptions handling
In all cases, when an error occurs in \CImg, an instance of the corresponding exception class is thrown.
This may lead the program to break (this is the default behavior), but you can bypass this behavior by
handling the exceptions by yourself,
using a usual <tt>try { ... } catch () { ... }</tt> bloc, as in the following example:
\code
#define "CImg.h"
using namespace cimg_library;
int main() {
cimg::exception_mode(0); // Enable quiet exception mode.
try {
... // Here, do what you want to stress CImg.
} catch (CImgException& e) { // You succeeded: something went wrong!
std::fprintf(stderr,"CImg Library Error: %s",e.what()); // Display your custom error message.
... // Do what you want now to save the ship!
}
}
\endcode
**/
struct CImgException : public std::exception {
#define _cimg_exception_err(etype,disp_flag) \
std::va_list ap, ap2; \
va_start(ap,format); va_start(ap2,format); \
int size = cimg_vsnprintf(0,0,format,ap2); \
if (size++>=0) { \
delete[] _message; \
_message = new char[size]; \
cimg_vsnprintf(_message,size,format,ap); \
if (cimg::exception_mode()) { \
std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
catch (CImgException&) {} \
if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
} \
} \
va_end(ap); va_end(ap2); \
char *_message;
CImgException() { _message = new char[1]; *_message = 0; }
CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); }
CImgException(const CImgException& e):std::exception(e) {
const size_t size = std::strlen(e._message);
_message = new char[size + 1];
std::strncpy(_message,e._message,size);
_message[size] = 0;
}
~CImgException() throw() { delete[] _message; }
CImgException& operator=(const CImgException& e) {
const size_t size = std::strlen(e._message);
_message = new char[size + 1];
std::strncpy(_message,e._message,size);
_message[size] = 0;
return *this;
}
//! Return a C-string containing the error message associated to the thrown exception.
const char *what() const throw() { return _message; }
};
// The CImgAbortException class is used to throw an exception when
// a computationally-intensive function has been aborted by an external signal.
struct CImgAbortException : public std::exception {
char *_message;
CImgAbortException() { _message = new char[1]; *_message = 0; }
CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); }
CImgAbortException(const CImgAbortException& e):std::exception(e) {
const size_t size = std::strlen(e._message);
_message = new char[size + 1];
std::strncpy(_message,e._message,size);
_message[size] = 0;
}
~CImgAbortException() throw() { delete[] _message; }
CImgAbortException& operator=(const CImgAbortException& e) {
const size_t size = std::strlen(e._message);
_message = new char[size + 1];
std::strncpy(_message,e._message,size);
_message[size] = 0;
return *this;
}
//! Return a C-string containing the error message associated to the thrown exception.
const char *what() const throw() { return _message; }
};
// The CImgArgumentException class is used to throw an exception related
// to invalid arguments encountered in a library function call.
struct CImgArgumentException : public CImgException {
CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); }
};
// The CImgDisplayException class is used to throw an exception related
// to display problems encountered in a library function call.
struct CImgDisplayException : public CImgException {
CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); }
};
// The CImgInstanceException class is used to throw an exception related
// to an invalid instance encountered in a library function call.
struct CImgInstanceException : public CImgException {
CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); }
};
// The CImgIOException class is used to throw an exception related
// to input/output file problems encountered in a library function call.
struct CImgIOException : public CImgException {
CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); }
};
// The CImgWarningException class is used to throw an exception for warnings
// encountered in a library function call.
struct CImgWarningException : public CImgException {
CImgWarningException(const char *const format, ...) { _cimg_exception_err("CImgWarningException",false); }
};
/*-------------------------------------
#
# Define cimg:: namespace
#
-----------------------------------*/
//! Contains \a low-level functions and variables of the \CImg Library.
/**
Most of the functions and variables within this namespace are used by the \CImg library for low-level operations.
You may use them to access specific const values or environment variables internally used by \CImg.
\warning Never write <tt>using namespace cimg_library::cimg;</tt> in your source code. Lot of functions in the
<tt>cimg:: namespace</tt> have the same names as standard C functions that may be defined in the global
namespace <tt>::</tt>.
**/
namespace cimg {
// Define traits that will be used to determine the best data type to work in CImg functions.
//
template<typename T> struct type {
static const char* string() {
static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24",
"unknown32", "unknown40", "unknown48", "unknown56",
"unknown64", "unknown72", "unknown80", "unknown88",
"unknown96", "unknown104", "unknown112", "unknown120",
"unknown128" };
return s[(sizeof(T)<17)?sizeof(T):0];
}
static bool is_float() { return false; }
static bool is_inf(const T) { return false; }
static bool is_nan(const T) { return false; }
static T min() { return ~max(); }
static T max() { return (T)1<<(8*sizeof(T) - 1); }
static T inf() { return max(); }
static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; }
static const char* format() { return "%s"; }
static const char* format_s() { return "%s"; }
static const char* format(const T& val) { static const char *const s = "unknown"; cimg::unused(val); return s; }
};
template<> struct type<bool> {
static const char* string() { static const char *const s = "bool"; return s; }
static bool is_float() { return false; }
static bool is_inf(const bool) { return false; }
static bool is_nan(const bool) { return false; }
static bool min() { return false; }
static bool max() { return true; }
static bool inf() { return max(); }
static bool is_inf() { return false; }
static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; }
static const char* format() { return "%s"; }
static const char* format_s() { return "%s"; }
static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; }
};
template<> struct type<unsigned char> {
static const char* string() { static const char *const s = "unsigned char"; return s; }
static bool is_float() { return false; }
static bool is_inf(const unsigned char) { return false; }
static bool is_nan(const unsigned char) { return false; }
static unsigned char min() { return 0; }
static unsigned char max() { return (unsigned char)-1; }
static unsigned char inf() { return max(); }
static unsigned char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; }
static const char* format() { return "%u"; }
static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned char val) { return (unsigned int)val; }
};
#if defined(CHAR_MAX) && CHAR_MAX==255
template<> struct type<char> {
static const char* string() { static const char *const s = "char"; return s; }
static bool is_float() { return false; }
static bool is_inf(const char) { return false; }
static bool is_nan(const char) { return false; }
static char min() { return 0; }
static char max() { return (char)-1; }
static char inf() { return max(); }
static char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; }
static const char* format() { return "%u"; }
static const char* format_s() { return "%u"; }
static unsigned int format(const char val) { return (unsigned int)val; }
};
#else
template<> struct type<char> {
static const char* string() { static const char *const s = "char"; return s; }
static bool is_float() { return false; }
static bool is_inf(const char) { return false; }
static bool is_nan(const char) { return false; }
static char min() { return ~max(); }
static char max() { return (char)((unsigned char)-1>>1); }
static char inf() { return max(); }
static char cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(char)val; }
static const char* format() { return "%d"; }
static const char* format_s() { return "%d"; }
static int format(const char val) { return (int)val; }
};
#endif
template<> struct type<signed char> {
static const char* string() { static const char *const s = "signed char"; return s; }
static bool is_float() { return false; }
static bool is_inf(const signed char) { return false; }
static bool is_nan(const signed char) { return false; }
static signed char min() { return ~max(); }
static signed char max() { return (signed char)((unsigned char)-1>>1); }
static signed char inf() { return max(); }
static signed char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(signed char)val; }
static const char* format() { return "%d"; }
static const char* format_s() { return "%d"; }
static int format(const signed char val) { return (int)val; }
};
template<> struct type<unsigned short> {
static const char* string() { static const char *const s = "unsigned short"; return s; }
static bool is_float() { return false; }
static bool is_inf(const unsigned short) { return false; }
static bool is_nan(const unsigned short) { return false; }
static unsigned short min() { return 0; }
static unsigned short max() { return (unsigned short)-1; }
static unsigned short inf() { return max(); }
static unsigned short cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned short)val; }
static const char* format() { return "%u"; }
static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned short val) { return (unsigned int)val; }
};
template<> struct type<short> {
static const char* string() { static const char *const s = "short"; return s; }
static bool is_float() { return false; }
static bool is_inf(const short) { return false; }
static bool is_nan(const short) { return false; }
static short min() { return ~max(); }
static short max() { return (short)((unsigned short)-1>>1); }
static short inf() { return max(); }
static short cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(short)val; }
static const char* format() { return "%d"; }
static const char* format_s() { return "%d"; }
static int format(const short val) { return (int)val; }
};
template<> struct type<unsigned int> {
static const char* string() { static const char *const s = "unsigned int"; return s; }
static bool is_float() { return false; }
static bool is_inf(const unsigned int) { return false; }
static bool is_nan(const unsigned int) { return false; }
static unsigned int min() { return 0; }
static unsigned int max() { return (unsigned int)-1; }
static unsigned int inf() { return max(); }
static unsigned int cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned int)val; }
static const char* format() { return "%u"; }
static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned int val) { return val; }
};
template<> struct type<int> {
static const char* string() { static const char *const s = "int"; return s; }
static bool is_float() { return false; }
static bool is_inf(const int) { return false; }
static bool is_nan(const int) { return false; }
static int min() { return ~max(); }
static int max() { return (int)((unsigned int)-1>>1); }
static int inf() { return max(); }
static int cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(int)val; }
static const char* format() { return "%d"; }
static const char* format_s() { return "%d"; }
static int format(const int val) { return val; }
};
template<> struct type<cimg_uint64> {
static const char* string() { static const char *const s = "unsigned int64"; return s; }
static bool is_float() { return false; }
static bool is_inf(const cimg_uint64) { return false; }
static bool is_nan(const cimg_uint64) { return false; }
static cimg_uint64 min() { return 0; }
static cimg_uint64 max() { return (cimg_uint64)-1; }
static cimg_uint64 inf() { return max(); }
static cimg_uint64 cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; }
static const char* format() { return cimg_fuint64; }
static const char* format_s() { return cimg_fuint64; }
static unsigned long format(const cimg_uint64 val) { return (unsigned long)val; }
};
template<> struct type<cimg_int64> {
static const char* string() { static const char *const s = "int64"; return s; }
static bool is_float() { return false; }
static bool is_inf(const cimg_int64) { return false; }
static bool is_nan(const cimg_int64) { return false; }
static cimg_int64 min() { return ~max(); }
static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); }
static cimg_int64 inf() { return max(); }
static cimg_int64 cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val;
}
static const char* format() { return cimg_fint64; }
static const char* format_s() { return cimg_fint64; }
static long format(const long val) { return (long)val; }
};
template<> struct type<double> {
static const char* string() { static const char *const s = "double"; return s; }
static bool is_float() { return true; }
static bool is_inf(const double val) {
#ifdef isinf
return (bool)isinf(val);
#else
return !is_nan(val) && (val<cimg::type<double>::min() || val>cimg::type<double>::max());
#endif
}
static bool is_nan(const double val) {
#ifdef isnan
return (bool)isnan(val);
#else
return !(val==val);
#endif
}
static double min() { return -DBL_MAX; }
static double max() { return DBL_MAX; }
static double inf() {
#ifdef INFINITY
return (double)INFINITY;
#else
return max()*max();
#endif
}
static double nan() {
#ifdef NAN
return (double)NAN;
#else
const double val_nan = -std::sqrt(-1.0); return val_nan;
#endif
}
static double cut(const double val) { return val; }
static const char* format() { return "%.17g"; }
static const char* format_s() { return "%g"; }
static double format(const double val) { return val; }
};
template<> struct type<float> {
static const char* string() { static const char *const s = "float"; return s; }
static bool is_float() { return true; }
static bool is_inf(const float val) {
#ifdef isinf
return (bool)isinf(val);
#else
return !is_nan(val) && (val<cimg::type<float>::min() || val>cimg::type<float>::max());
#endif
}
static bool is_nan(const float val) {
#ifdef isnan
return (bool)isnan(val);
#else
return !(val==val);
#endif
}
static float min() { return -FLT_MAX; }
static float max() { return FLT_MAX; }
static float inf() { return (float)cimg::type<double>::inf(); }
static float nan() { return (float)cimg::type<double>::nan(); }
static float cut(const double val) { return (float)val; }
static float cut(const float val) { return (float)val; }
static const char* format() { return "%.9g"; }
static const char* format_s() { return "%g"; }
static double format(const float val) { return (double)val; }
};
template<> struct type<long double> {
static const char* string() { static const char *const s = "long double"; return s; }
static bool is_float() { return true; }
static bool is_inf(const long double val) {
#ifdef isinf
return (bool)isinf(val);
#else
return !is_nan(val) && (val<cimg::type<long double>::min() || val>cimg::type<long double>::max());
#endif
}
static bool is_nan(const long double val) {
#ifdef isnan
return (bool)isnan(val);
#else
return !(val==val);
#endif
}
static long double min() { return -LDBL_MAX; }
static long double max() { return LDBL_MAX; }
static long double inf() { return max()*max(); }
static long double nan() { const long double val_nan = -std::sqrt(-1.0L); return val_nan; }
static long double cut(const long double val) { return val; }
static const char* format() { return "%.17g"; }
static const char* format_s() { return "%g"; }
static double format(const long double val) { return (double)val; }
};
#ifdef cimg_use_half
template<> struct type<half> {
static const char* string() { static const char *const s = "half"; return s; }
static bool is_float() { return true; }
static bool is_inf(const long double val) {
#ifdef isinf
return (bool)isinf(val);
#else
return !is_nan(val) && (val<cimg::type<half>::min() || val>cimg::type<half>::max());
#endif
}
static bool is_nan(const long double val) {
#ifdef isnan
return (bool)isnan(val);
#else
return !(val==val);
#endif
}
static half min() { return (half)-65504; }
static half max() { return (half)65504; }
static half inf() { return max()*max(); }
static half nan() { const half val_nan = (half)-std::sqrt(-1.0); return val_nan; }
static half cut(const double val) { return (half)val; }
static const char* format() { return "%.9g"; }
static const char* format_s() { return "%g"; }
static double format(const half val) { return (double)val; }
};
#endif
template<typename T, typename t> struct superset { typedef T type; };
template<> struct superset<bool,unsigned char> { typedef unsigned char type; };
template<> struct superset<bool,char> { typedef char type; };
template<> struct superset<bool,signed char> { typedef signed char type; };
template<> struct superset<bool,unsigned short> { typedef unsigned short type; };
template<> struct superset<bool,short> { typedef short type; };
template<> struct superset<bool,unsigned int> { typedef unsigned int type; };
template<> struct superset<bool,int> { typedef int type; };
template<> struct superset<bool,cimg_uint64> { typedef cimg_uint64 type; };
template<> struct superset<bool,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<bool,float> { typedef float type; };
template<> struct superset<bool,double> { typedef double type; };
template<> struct superset<unsigned char,char> { typedef short type; };
template<> struct superset<unsigned char,signed char> { typedef short type; };
template<> struct superset<unsigned char,unsigned short> { typedef unsigned short type; };
template<> struct superset<unsigned char,short> { typedef short type; };
template<> struct superset<unsigned char,unsigned int> { typedef unsigned int type; };
template<> struct superset<unsigned char,int> { typedef int type; };
template<> struct superset<unsigned char,cimg_uint64> { typedef cimg_uint64 type; };
template<> struct superset<unsigned char,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<unsigned char,float> { typedef float type; };
template<> struct superset<unsigned char,double> { typedef double type; };
template<> struct superset<signed char,unsigned char> { typedef short type; };
template<> struct superset<signed char,char> { typedef short type; };
template<> struct superset<signed char,unsigned short> { typedef int type; };
template<> struct superset<signed char,short> { typedef short type; };
template<> struct superset<signed char,unsigned int> { typedef cimg_int64 type; };
template<> struct superset<signed char,int> { typedef int type; };
template<> struct superset<signed char,cimg_uint64> { typedef cimg_int64 type; };
template<> struct superset<signed char,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<signed char,float> { typedef float type; };
template<> struct superset<signed char,double> { typedef double type; };
template<> struct superset<char,unsigned char> { typedef short type; };
template<> struct superset<char,signed char> { typedef short type; };
template<> struct superset<char,unsigned short> { typedef int type; };
template<> struct superset<char,short> { typedef short type; };
template<> struct superset<char,unsigned int> { typedef cimg_int64 type; };
template<> struct superset<char,int> { typedef int type; };
template<> struct superset<char,cimg_uint64> { typedef cimg_int64 type; };
template<> struct superset<char,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<char,float> { typedef float type; };
template<> struct superset<char,double> { typedef double type; };
template<> struct superset<unsigned short,char> { typedef int type; };
template<> struct superset<unsigned short,signed char> { typedef int type; };
template<> struct superset<unsigned short,short> { typedef int type; };
template<> struct superset<unsigned short,unsigned int> { typedef unsigned int type; };
template<> struct superset<unsigned short,int> { typedef int type; };
template<> struct superset<unsigned short,cimg_uint64> { typedef cimg_uint64 type; };
template<> struct superset<unsigned short,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<unsigned short,float> { typedef float type; };
template<> struct superset<unsigned short,double> { typedef double type; };
template<> struct superset<short,unsigned short> { typedef int type; };
template<> struct superset<short,unsigned int> { typedef cimg_int64 type; };
template<> struct superset<short,int> { typedef int type; };
template<> struct superset<short,cimg_uint64> { typedef cimg_int64 type; };
template<> struct superset<short,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<short,float> { typedef float type; };
template<> struct superset<short,double> { typedef double type; };
template<> struct superset<unsigned int,char> { typedef cimg_int64 type; };
template<> struct superset<unsigned int,signed char> { typedef cimg_int64 type; };
template<> struct superset<unsigned int,short> { typedef cimg_int64 type; };
template<> struct superset<unsigned int,int> { typedef cimg_int64 type; };
template<> struct superset<unsigned int,cimg_uint64> { typedef cimg_uint64 type; };
template<> struct superset<unsigned int,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<unsigned int,float> { typedef float type; };
template<> struct superset<unsigned int,double> { typedef double type; };
template<> struct superset<int,unsigned int> { typedef cimg_int64 type; };
template<> struct superset<int,cimg_uint64> { typedef cimg_int64 type; };
template<> struct superset<int,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<int,float> { typedef float type; };
template<> struct superset<int,double> { typedef double type; };
template<> struct superset<cimg_uint64,char> { typedef cimg_int64 type; };
template<> struct superset<cimg_uint64,signed char> { typedef cimg_int64 type; };
template<> struct superset<cimg_uint64,short> { typedef cimg_int64 type; };
template<> struct superset<cimg_uint64,int> { typedef cimg_int64 type; };
template<> struct superset<cimg_uint64,cimg_int64> { typedef cimg_int64 type; };
template<> struct superset<cimg_uint64,float> { typedef double type; };
template<> struct superset<cimg_uint64,double> { typedef double type; };
template<> struct superset<cimg_int64,float> { typedef double type; };
template<> struct superset<cimg_int64,double> { typedef double type; };
template<> struct superset<float,double> { typedef double type; };
#ifdef cimg_use_half
template<> struct superset<half,unsigned short> { typedef float type; };
template<> struct superset<half,short> { typedef float type; };
template<> struct superset<half,unsigned int> { typedef float type; };
template<> struct superset<half,int> { typedef float type; };
template<> struct superset<half,cimg_uint64> { typedef float type; };
template<> struct superset<half,cimg_int64> { typedef float type; };
template<> struct superset<half,float> { typedef float type; };
template<> struct superset<half,double> { typedef double type; };
#endif
template<typename t1, typename t2, typename t3> struct superset2 {
typedef typename superset<t1, typename superset<t2,t3>::type>::type type;
};
template<typename t1, typename t2, typename t3, typename t4> struct superset3 {
typedef typename superset<t1, typename superset2<t2,t3,t4>::type>::type type;
};
template<typename t1, typename t2> struct last { typedef t2 type; };
#define _cimg_Tt typename cimg::superset<T,t>::type
#define _cimg_Tfloat typename cimg::superset<T,float>::type
#define _cimg_Ttfloat typename cimg::superset2<T,t,float>::type
#define _cimg_Ttdouble typename cimg::superset2<T,t,double>::type
// Define variables used internally by CImg.
#if cimg_display==1
struct X11_info {
unsigned int nb_wins;
pthread_t *events_thread;
pthread_cond_t wait_event;
pthread_mutex_t wait_event_mutex;
CImgDisplay **wins;
Display *display;
unsigned int nb_bits;
bool is_blue_first;
bool is_shm_enabled;
bool byte_order;
#ifdef cimg_use_xrandr
XRRScreenSize *resolutions;
Rotation curr_rotation;
unsigned int curr_resolution;
unsigned int nb_resolutions;