1 #ifndef ENCODE_INCLUDED
2 #define ENCODE_INCLUDED
3
4 #include <unordered_map>
5 #include <string>
6 #include "ColorSpace.h"
7 #include <R.h>
8 #define R_NO_REMAP
9 #include <Rinternals.h>
10
11 #define OP_SET 1
12 #define OP_ADD 2
13 #define OP_MULT 3
14 #define OP_LEAST 4
15 #define OP_MOST 5
16
mod_val(double val,double mod,int op)17 inline double mod_val(double val, double mod, int op) {
18 switch (op) {
19 case OP_SET: return mod;
20 case OP_ADD: return val + mod;
21 case OP_MULT: return val * mod;
22 case OP_LEAST: return val < mod ? mod : val;
23 case OP_MOST: return val > mod ? mod : val;
24 }
25 return val;
26 }
27
28 struct rgb_colour {
29 int r;
30 int g;
31 int b;
32 int a;
33 };
34 typedef std::unordered_map<std::string, rgb_colour> ColourMap;
35
36 // Defined in init.cpp
37 ColourMap& get_named_colours();
38
39 SEXP encode_c(SEXP colour, SEXP alpha, SEXP from, SEXP white);
40 SEXP decode_c(SEXP codes, SEXP alpha, SEXP to, SEXP white, SEXP na);
41 SEXP encode_channel_c(SEXP codes, SEXP channel, SEXP value, SEXP space, SEXP op, SEXP white, SEXP na);
42 SEXP decode_channel_c(SEXP codes, SEXP channel, SEXP space, SEXP white, SEXP na);
43 SEXP load_colour_names_c(SEXP name, SEXP value);
44 SEXP encode_native_c(SEXP color);
45 SEXP decode_native_c(SEXP native);
46
47 template <typename Space>
48 inline void modify_channel(Space&, double value, int channel, int op);
49
50 template <>
51 inline void modify_channel<ColorSpace::Rgb>(ColorSpace::Rgb& color, double value, int channel, int op){
52 switch (channel) {
53 case 1:
54 color.r = mod_val(color.r, value, op);
55 break;
56 case 2:
57 color.g = mod_val(color.g, value, op);
58 break;
59 case 3:
60 color.b = mod_val(color.b, value, op);
61 break;
62 }
63 }
64
65 template <>
66 inline void modify_channel<ColorSpace::Xyz>(ColorSpace::Xyz& color, double value, int channel, int op){
67 switch (channel) {
68 case 1:
69 color.x = mod_val(color.x, value, op);
70 break;
71 case 2:
72 color.y = mod_val(color.y, value, op);
73 break;
74 case 3:
75 color.z = mod_val(color.z, value, op);
76 break;
77 }
78 }
79
80 template <>
81 inline void modify_channel<ColorSpace::Hsl>(ColorSpace::Hsl& color, double value, int channel, int op){
82 switch (channel) {
83 case 1:
84 color.h = mod_val(color.h, value, op);
85 break;
86 case 2:
87 color.s = mod_val(color.s, value, op);
88 break;
89 case 3:
90 color.l = mod_val(color.l, value, op);
91 break;
92 }
93 }
94
95 template <>
96 inline void modify_channel<ColorSpace::Lab>(ColorSpace::Lab& color, double value, int channel, int op){
97 switch (channel) {
98 case 1:
99 color.l = mod_val(color.l, value, op);
100 break;
101 case 2:
102 color.a = mod_val(color.a, value, op);
103 break;
104 case 3:
105 color.b = mod_val(color.b, value, op);
106 break;
107 }
108 }
109
110 template <>
111 inline void modify_channel<ColorSpace::Lch>(ColorSpace::Lch& color, double value, int channel, int op){
112 switch (channel) {
113 case 1:
114 color.l = mod_val(color.l, value, op);
115 break;
116 case 2:
117 color.c = mod_val(color.c, value, op);
118 break;
119 case 3:
120 color.h = mod_val(color.h, value, op);
121 break;
122 }
123 }
124
125 template <>
126 inline void modify_channel<ColorSpace::Luv>(ColorSpace::Luv& color, double value, int channel, int op){
127 switch (channel) {
128 case 1:
129 color.l = mod_val(color.l, value, op);
130 break;
131 case 2:
132 color.u = mod_val(color.u, value, op);
133 break;
134 case 3:
135 color.v = mod_val(color.v, value, op);
136 break;
137 }
138 }
139
140 template <>
141 inline void modify_channel<ColorSpace::Yxy>(ColorSpace::Yxy& color, double value, int channel, int op){
142 switch (channel) {
143 case 1:
144 color.y1 = mod_val(color.y1, value, op);
145 break;
146 case 2:
147 color.x = mod_val(color.x, value, op);
148 break;
149 case 3:
150 color.y2 = mod_val(color.y2, value, op);
151 break;
152 }
153 }
154
155 template <>
156 inline void modify_channel<ColorSpace::Cmy>(ColorSpace::Cmy& color, double value, int channel, int op){
157 switch (channel) {
158 case 1:
159 color.c = mod_val(color.c, value, op);
160 break;
161 case 2:
162 color.m = mod_val(color.m, value, op);
163 break;
164 case 3:
165 color.y = mod_val(color.y, value, op);
166 break;
167 }
168 }
169
170 template <>
171 inline void modify_channel<ColorSpace::Cmyk>(ColorSpace::Cmyk& color, double value, int channel, int op){
172 switch (channel) {
173 case 1:
174 color.c = mod_val(color.c, value, op);
175 break;
176 case 2:
177 color.m = mod_val(color.m, value, op);
178 break;
179 case 3:
180 color.y = mod_val(color.y, value, op);
181 break;
182 case 4:
183 color.k = mod_val(color.k, value, op);
184 break;
185 }
186 }
187
188 template <>
189 inline void modify_channel<ColorSpace::Hsv>(ColorSpace::Hsv& color, double value, int channel, int op){
190 switch (channel) {
191 case 1:
192 color.h = mod_val(color.h, value, op);
193 break;
194 case 2:
195 color.s = mod_val(color.s, value, op);
196 break;
197 case 3:
198 color.v = mod_val(color.v, value, op);
199 break;
200 }
201 }
202
203 template <>
204 inline void modify_channel<ColorSpace::Hsb>(ColorSpace::Hsb& color, double value, int channel, int op){
205 switch (channel) {
206 case 1:
207 color.h = mod_val(color.h, value, op);
208 break;
209 case 2:
210 color.s = mod_val(color.s, value, op);
211 break;
212 case 3:
213 color.b = mod_val(color.b, value, op);
214 break;
215 }
216 }
217
218 template <>
219 inline void modify_channel<ColorSpace::HunterLab>(ColorSpace::HunterLab& color, double value, int channel, int op){
220 switch (channel) {
221 case 1:
222 color.l = mod_val(color.l, value, op);
223 break;
224 case 2:
225 color.a = mod_val(color.a, value, op);
226 break;
227 case 3:
228 color.b = mod_val(color.b, value, op);
229 break;
230 }
231 }
232
233 template <>
234 inline void modify_channel<ColorSpace::Hcl>(ColorSpace::Hcl& color, double value, int channel, int op){
235 switch (channel) {
236 case 1:
237 color.h = mod_val(color.h, value, op);
238 break;
239 case 2:
240 color.c = mod_val(color.c, value, op);
241 break;
242 case 3:
243 color.l = mod_val(color.l, value, op);
244 break;
245 }
246 }
247
248 template <>
249 inline void modify_channel<ColorSpace::OkLab>(ColorSpace::OkLab& color, double value, int channel, int op){
250 switch (channel) {
251 case 1:
252 color.l = mod_val(color.l, value, op);
253 break;
254 case 2:
255 color.a = mod_val(color.a, value, op);
256 break;
257 case 3:
258 color.b = mod_val(color.b, value, op);
259 break;
260 }
261 }
262
263 template <>
264 inline void modify_channel<ColorSpace::OkLch>(ColorSpace::OkLch& color, double value, int channel, int op){
265 switch (channel) {
266 case 1:
267 color.l = mod_val(color.l, value, op);
268 break;
269 case 2:
270 color.c = mod_val(color.c, value, op);
271 break;
272 case 3:
273 color.h = mod_val(color.h, value, op);
274 break;
275 }
276 }
277
278
279 template <typename Space>
280 inline double grab_channel(Space&,int channel);
281
282 template <>
283 inline double grab_channel<ColorSpace::Rgb>(ColorSpace::Rgb& color, int channel){
284 switch (channel) {
285 case 1: return color.r;
286 case 2: return color.g;
287 case 3: return color.b;
288 }
289 return 0.0;
290 }
291
292 template <>
293 inline double grab_channel<ColorSpace::Xyz>(ColorSpace::Xyz& color, int channel){
294 switch (channel) {
295 case 1: return color.x;
296 case 2: return color.y;
297 case 3: return color.z;
298 }
299 return 0.0;
300 }
301
302 template <>
303 inline double grab_channel<ColorSpace::Hsl>(ColorSpace::Hsl& color, int channel){
304 switch (channel) {
305 case 1: return color.h;
306 case 2: return color.s;
307 case 3: return color.l;
308 }
309 return 0.0;
310 }
311
312 template <>
313 inline double grab_channel<ColorSpace::Lab>(ColorSpace::Lab& color, int channel){
314 switch (channel) {
315 case 1: return color.l;
316 case 2: return color.a;
317 case 3: return color.b;
318 }
319 return 0.0;
320 }
321
322 template <>
323 inline double grab_channel<ColorSpace::Lch>(ColorSpace::Lch& color, int channel){
324 switch (channel) {
325 case 1: return color.l;
326 case 2: return color.c;
327 case 3: return color.h;
328 }
329 return 0.0;
330 }
331
332 template <>
333 inline double grab_channel<ColorSpace::Luv>(ColorSpace::Luv& color, int channel){
334 switch (channel) {
335 case 1: return color.l;
336 case 2: return color.u;
337 case 3: return color.v;
338 }
339 return 0.0;
340 }
341
342 template <>
343 inline double grab_channel<ColorSpace::Yxy>(ColorSpace::Yxy& color, int channel){
344 switch (channel) {
345 case 1: return color.y1;
346 case 2: return color.x;
347 case 3: return color.y2;
348 }
349 return 0.0;
350 }
351
352 template <>
353 inline double grab_channel<ColorSpace::Cmy>(ColorSpace::Cmy& color, int channel){
354 switch (channel) {
355 case 1: return color.c;
356 case 2: return color.m;
357 case 3: return color.y;
358 }
359 return 0.0;
360 }
361
362 template <>
363 inline double grab_channel<ColorSpace::Cmyk>(ColorSpace::Cmyk& color, int channel){
364 switch (channel) {
365 case 1: return color.c;
366 case 2: return color.m;
367 case 3: return color.y;
368 case 4: return color.k;
369 }
370 return 0.0;
371 }
372
373 template <>
374 inline double grab_channel<ColorSpace::Hsv>(ColorSpace::Hsv& color, int channel){
375 switch (channel) {
376 case 1: return color.h;
377 case 2: return color.s;
378 case 3: return color.v;
379 }
380 return 0.0;
381 }
382
383 template <>
384 inline double grab_channel<ColorSpace::Hsb>(ColorSpace::Hsb& color, int channel){
385 switch (channel) {
386 case 1: return color.h;
387 case 2: return color.s;
388 case 3: return color.b;
389 }
390 return 0.0;
391 }
392
393 template <>
394 inline double grab_channel<ColorSpace::HunterLab>(ColorSpace::HunterLab& color, int channel){
395 switch (channel) {
396 case 1: return color.l;
397 case 2: return color.a;
398 case 3: return color.b;
399 }
400 return 0.0;
401 }
402
403 template <>
404 inline double grab_channel<ColorSpace::Hcl>(ColorSpace::Hcl& color, int channel){
405 switch (channel) {
406 case 1: return color.h;
407 case 2: return color.c;
408 case 3: return color.l;
409 }
410 return 0.0;
411 }
412
413 template <>
414 inline double grab_channel<ColorSpace::OkLab>(ColorSpace::OkLab& color, int channel){
415 switch (channel) {
416 case 1: return color.l;
417 case 2: return color.a;
418 case 3: return color.b;
419 }
420 return 0.0;
421 }
422
423 template <>
424 inline double grab_channel<ColorSpace::OkLch>(ColorSpace::OkLch& color, int channel){
425 switch (channel) {
426 case 1: return color.l;
427 case 2: return color.c;
428 case 3: return color.h;
429 }
430 return 0.0;
431 }
432
433 #endif
434