Rename GP_Context -> GP_Pixmap
[gfxprim.git] / include / core / GP_Convert.gen.h.t
blob02fe86f01980c5144158396d87fd133bf85806b7
1 @ include header.t
2 /*
3  * Convert PixelType values macros and functions
4  *
5  * Copyright (C) 2011-2014 Cyril Hrubis <metan@ucw.cz>
6  * Copyright (C) 2011      Tomas Gavenciak <gavento@ucw.cz>
7  */
9 @ # RGB -> CMYK requires special handling
10 @ def rgb_to_cmyk(in_pix, out_pix):
11 @     R = in_pix.chans['R']
12 @     G = in_pix.chans['G']
13 @     B = in_pix.chans['B']
14 @     C = out_pix.chans['C']
15 @     M = out_pix.chans['M']
16 @     Y = out_pix.chans['Y']
17 @     K = out_pix.chans['K']
18 @     max_size = max(R.size, G.size, B.size)
19 @     max_val = 2 ** max_size - 1
20         GP_Pixel _R = GP_SCALE_VAL_{{ R.size }}_{{ max_size }}(GP_GET_BITS({{ R.off }}+o1, {{ R.size }}, p1)); \
21         GP_Pixel _G = GP_SCALE_VAL_{{ G.size }}_{{ max_size }}(GP_GET_BITS({{ G.off }}+o1, {{ G.size }}, p1)); \
22         GP_Pixel _B = GP_SCALE_VAL_{{ B.size }}_{{ max_size }}(GP_GET_BITS({{ B.off }}+o1, {{ B.size }}, p1)); \
23         GP_Pixel _K = GP_MAX3(_R, _G, _B); \
24         GP_SET_BITS({{ C.off }}+o2, {{ C.size }}, p2, GP_SCALE_VAL_{{ max_size }}_{{ C.size }}((_K - _R))); \
25         GP_SET_BITS({{ M.off }}+o2, {{ M.size }}, p2, GP_SCALE_VAL_{{ max_size }}_{{ M.size }}((_K - _G))); \
26         GP_SET_BITS({{ Y.off }}+o2, {{ Y.size }}, p2, GP_SCALE_VAL_{{ max_size }}_{{ Y.size }}((_K - _B))); \
27         GP_SET_BITS({{ K.off }}+o2, {{ K.size }}, p2, GP_SCALE_VAL_{{ max_size }}_{{ K.size }}({{ max_val }} - _K)); \
28 @ end
30 @ def GP_Pixel_TYPE_TO_TYPE(pt1, pt2):
31 /*** {{ pt1.name }} -> {{ pt2.name }} ***
32  * macro reads p1 ({{ pt1.name }} at bit-offset o1)
33  * and writes to p2 ({{ pt2.name }} at bit-offset o2)
34  * the relevant part of p2 is assumed to be cleared (zero) */
35 #define GP_Pixel_{{ pt1.name }}_TO_{{ pt2.name }}_OFFSET(p1, o1, p2, o2) do { \
36 @     # special cases
37 @     if pt1.is_rgb() and pt2.is_cmyk():
38 @         rgb_to_cmyk(pt1, pt2)
39 @     else:
40 @         for c2 in pt2.chanslist:
41 @             # case 1: just copy a channel
42 @             if c2[0] in pt1.chans.keys():
43 @                 c1 = pt1.chans[c2[0]]
44         /* {{ c2[0] }}:={{ c1[0] }} */ GP_SET_BITS({{ c2.off }}+o2, {{ c2.size }}, p2,\
45                 GP_SCALE_VAL_{{ c1.size }}_{{ c2.size }}(GP_GET_BITS({{ c1.off }}+o1, {{ c1.size }}, p1))); \
46 @             # case 2: set A to full opacity (not present in source)
47 @             elif c2[0]=='A':
48         /* A:={{ c2.C_max }} */GP_SET_BITS({{ c2.off }}+o2, {{ c2.size }}, p2, {{ c2.C_max }}); \
49 @             # case 3: calculate V as average of RGB
50 @             elif c2[0]=='V' and pt1.is_rgb():
51         /* V:=RGB_avg */ GP_SET_BITS({{ c2.off }}+o2, {{ c2.size }}, p2, ( \
52 @                 for c1 in [pt1.chans['R'], pt1.chans['G'], pt1.chans['B']]:
53                 /* {{ c1.name }} */ GP_SCALE_VAL_{{ c1.size }}_{{ c2.size }}(GP_GET_BITS({{ c1.off }}+o1, {{ c1.size }}, p1)) + \
54 @                 end
55         0)/3);\
56 @             # case 4: set each RGB to V -#}
57 @             elif c2[0] in 'RGB' and pt1.is_gray():
58 @                 c1 = pt1.chans['V']
59         /* {{ c2[0] }}:=V */ GP_SET_BITS({{ c2.off }}+o2, {{ c2.size }}, p2,\
60                 GP_SCALE_VAL_{{ c1.size }}_{{ c2.size }}(GP_GET_BITS({{ c1.off }}+o1, {{ c1.size }}, p1))); \
61 @             # case 5: CMYK to RGB
62 @             elif c2[0] in 'RGB' and pt1.is_cmyk():
63 @                 K = pt1.chans['K']
64 @                 if c2[0] == 'R':
65 @                     V = pt1.chans['C']
66 @                 elif c2[0] == 'G':
67 @                     V = pt1.chans['M']
68 @                 else:
69 @                     V = pt1.chans['Y']
70 @                 end
71         GP_SET_BITS({{ c2.off }}+o2, {{ c2.size }}, p2,\
72                     (({{ c2.C_max }} * ({{ K.C_max }} - GP_GET_BITS({{ K.off }}+o1, {{ K.size }}, p1)) * \
73                      ({{ V.C_max }} - GP_GET_BITS({{ V.off }}+o1, {{ V.size }}, p1)))) / ({{ K.C_max }} * {{ V.C_max }})); \
74 @             # case 7: invalid mapping
75 @             else:
76 {{ error('Channel conversion ' + pt1.name + ' to ' + pt2.name + ' not supported.') }}
77 @     end
78 } while (0)
80 /* a version without offsets */
81 #define GP_Pixel_{{ pt1.name }}_TO_{{ pt2.name }}(p1, p2) \
82         GP_Pixel_{{ pt1.name }}_TO_{{ pt2.name }}_OFFSET(p1, 0, p2, 0)
84 @ end
86 #include "GP_GetSetBits.h"
87 #include "GP_Pixmap.h"
88 #include "GP_Pixel.h"
91 @ # Loop around "central" pixel types
93 @ for pt in [pixeltypes_dict['RGB888'], pixeltypes_dict['RGBA8888']]:
94 @     for i in pixeltypes:
95 @         if not i.is_unknown() and not i.is_palette():
96 @             GP_Pixel_TYPE_TO_TYPE(pt, i)
97 @             if i.name not in ['RGB888', 'RGBA8888']:
98 @                 GP_Pixel_TYPE_TO_TYPE(i, pt)
99 @     end
102  * Convert {{ pt.name }} to any other PixelType
103  * Does not work on palette types at all (yet)
104  */
105 GP_Pixel GP_{{ pt.name }}ToPixel(GP_Pixel pixel, GP_PixelType type);
108  * Function converting to {{ pt.name }} from any other PixelType
109  * Does not work on palette types at all (yet)
110  */
111 GP_Pixel GP_PixelTo{{ pt.name }}(GP_Pixel pixel, GP_PixelType type);
113 @ end
115 /* Experimental macros testing generated scripts */
116 @ GP_Pixel_TYPE_TO_TYPE(pixeltypes_dict['RGB565'], pixeltypes_dict['RGBA8888'])
117 @ GP_Pixel_TYPE_TO_TYPE(pixeltypes_dict['RGBA8888'], pixeltypes_dict['G2'])