1 /*
2  *
3  *   Gimp-Print color management module - traditional Gimp-Print algorithm.
4  *
5  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
6  *	Robert Krawitz (rlk@alum.mit.edu)
7  *
8  *   This program is free software; you can redistribute it and/or modify it
9  *   under the terms of the GNU General Public License as published by the Free
10  *   Software Foundation; either version 2 of the License, or (at your option)
11  *   any later version.
12  *
13  *   This program is distributed in the hope that it will be useful, but
14  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  *   for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 /*
23  * This file must include only standard C header files.  The core code must
24  * compile on generic platforms that don't support glib, gimp, gtk, etc.
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include <gutenprint/gutenprint.h>
31 #include "gutenprint-internal.h"
32 #include <gutenprint/gutenprint-intl-internal.h>
33 #include <gutenprint/curve-cache.h>
34 #include <math.h>
35 #ifdef HAVE_LIMITS_H
36 #include <limits.h>
37 #endif
38 #include <string.h>
39 #include "color-conversion.h"
40 
41 #ifdef __GNUC__
42 #define inline __inline__
43 // There's no reason to inline the main loop with the dispatch
44 // functions only to fail inlining of calls from the inner loop.
45 // Also, inlining the main loop makes it hard to debug because we lose
46 // context of which print function is called.
47 #define NOINLINE __attribute__ ((noinline))
48 #else
49 $define NOINLINE
50 #endif
51 
52 #define CFUNC static unsigned NOINLINE
53 
54 /*
55  * RGB to grayscale luminance constants...
56  */
57 
58 #define LUM_RED		31
59 #define LUM_GREEN	61
60 #define LUM_BLUE	8
61 
62 /* rgb/hsl conversions taken from Gimp common/autostretch_hsv.c */
63 
64 #define FMAX(a, b) ((a) > (b) ? (a) : (b))
65 #define FMIN(a, b) ((a) < (b) ? (a) : (b))
66 
67 #define MAXB(bits) ((1 << (bits)) - 1)
68 
69 static inline void
calc_rgb_to_hsl(unsigned short * rgb,double * hue,double * sat,double * lightness)70 calc_rgb_to_hsl(unsigned short *rgb, double *hue, double *sat,
71 		double *lightness)
72 {
73   double red, green, blue;
74   double h, s, l;
75   double min, max;
76   double delta;
77   int maxval;
78 
79   red   = rgb[0] / 65535.0;
80   green = rgb[1] / 65535.0;
81   blue  = rgb[2] / 65535.0;
82 
83   if (red > green)
84     {
85       if (red > blue)
86 	{
87 	  max = red;
88 	  maxval = 0;
89 	}
90       else
91 	{
92 	  max = blue;
93 	  maxval = 2;
94 	}
95       min = FMIN(green, blue);
96     }
97   else
98     {
99       if (green > blue)
100 	{
101 	  max = green;
102 	  maxval = 1;
103 	}
104       else
105 	{
106 	  max = blue;
107 	  maxval = 2;
108 	}
109       min = FMIN(red, blue);
110     }
111 
112   l = (max + min) / 2.0;
113   delta = max - min;
114 
115   if (delta < .000001)	/* Suggested by Eugene Anikin <eugene@anikin.com> */
116     {
117       s = 0.0;
118       h = 0.0;
119     }
120   else
121     {
122       if (l <= .5)
123 	s = delta / (max + min);
124       else
125 	s = delta / (2 - max - min);
126 
127       if (maxval == 0)
128 	h = (green - blue) / delta;
129       else if (maxval == 1)
130 	h = 2 + (blue - red) / delta;
131       else
132 	h = 4 + (red - green) / delta;
133 
134       if (h < 0.0)
135 	h += 6.0;
136       else if (h > 6.0)
137 	h -= 6.0;
138     }
139 
140   *hue = h;
141   *sat = s;
142   *lightness = l;
143 }
144 
145 static inline double
hsl_value(double n1,double n2,double hue)146 hsl_value(double n1, double n2, double hue)
147 {
148   if (hue < 0)
149     hue += 6.0;
150   else if (hue > 6)
151     hue -= 6.0;
152   if (hue < 1.0)
153     return (n1 + (n2 - n1) * hue);
154   else if (hue < 3.0)
155     return (n2);
156   else if (hue < 4.0)
157     return (n1 + (n2 - n1) * (4.0 - hue));
158   else
159     return (n1);
160 }
161 
162 static inline void
calc_hsl_to_rgb(unsigned short * rgb,double h,double s,double l)163 calc_hsl_to_rgb(unsigned short *rgb, double h, double s, double l)
164 {
165   if (s < .0000001)
166     {
167       if (l > 1)
168 	l = 1;
169       else if (l < 0)
170 	l = 0;
171       rgb[0] = l * 65535;
172       rgb[1] = l * 65535;
173       rgb[2] = l * 65535;
174     }
175   else
176     {
177       double m1, m2;
178       double h1, h2;
179       h1 = h + 2;
180       h2 = h - 2;
181 
182       if (l < .5)
183 	m2 = l * (1 + s);
184       else
185 	m2 = l + s - (l * s);
186       m1 = (l * 2) - m2;
187       rgb[0] = 65535 * hsl_value(m1, m2, h1);
188       rgb[1] = 65535 * hsl_value(m1, m2, h);
189       rgb[2] = 65535 * hsl_value(m1, m2, h2);
190     }
191 }
192 
193 static inline double
update_saturation(double sat,double adjust,double isat,int bright_colors)194 update_saturation(double sat, double adjust, double isat, int bright_colors)
195 {
196   if (bright_colors || adjust < 1)
197     sat *= adjust;
198   else if (adjust > 1)
199     {
200       double s1 = sat * adjust;
201       double s2 = 1.0 - ((1.0 - sat) * isat);
202       sat = FMIN(s1, s2);
203     }
204   if (sat > 1)
205     sat = 1.0;
206   return sat;
207 }
208 
209 static inline double
interpolate_value(const double * vec,double val)210 interpolate_value(const double *vec, double val)
211 {
212   double base = (double)((int)(val));
213   double frac = val - base;
214   int ibase = (int) base;
215   double lval = vec[ibase];
216   if (frac > 0)
217     lval += (vec[ibase + 1] - lval) * frac;
218   return lval;
219 }
220 
221 static inline void
update_saturation_from_rgb(unsigned short * rgb,const unsigned short * brightness_lookup,double adjust,double isat,int do_usermap)222 update_saturation_from_rgb(unsigned short *rgb,
223 			   const unsigned short *brightness_lookup,
224 			   double adjust, double isat, int do_usermap)
225 {
226   double h, s, l;
227   calc_rgb_to_hsl(rgb, &h, &s, &l);
228   if (do_usermap)
229     {
230       unsigned short ub = (unsigned short) (l * 65535);
231       unsigned short val = brightness_lookup[ub];
232       l = ((double) val) / 65535;
233       if (val < ub)
234 	s = s * (65535 - ub) / (65535 - val);
235     }
236   s = update_saturation(s, adjust, isat, 0);
237   calc_hsl_to_rgb(rgb, h, s, l);
238 }
239 
240 static inline double
adjust_hue(const double * hue_map,double hue,size_t points)241 adjust_hue(const double *hue_map, double hue, size_t points)
242 {
243   if (hue_map)
244     {
245       hue += interpolate_value(hue_map, hue * points / 6.0);
246       if (hue < 0.0)
247 	hue += 6.0;
248       else if (hue >= 6.0)
249 	hue -= 6.0;
250     }
251   return hue;
252 }
253 
254 static inline void
adjust_hsl(unsigned short * rgbout,lut_t * lut,double ssat,double isat,int split_saturation,int adjust_hue_only,int bright_colors)255 adjust_hsl(unsigned short *rgbout, lut_t *lut, double ssat, double isat,
256 	   int split_saturation, int adjust_hue_only, int bright_colors)
257 {
258   const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map));
259   const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map));
260   const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map));
261   size_t hue_count = CURVE_CACHE_FAST_COUNT(&(lut->hue_map));
262   size_t lum_count = CURVE_CACHE_FAST_COUNT(&(lut->lum_map));
263   size_t sat_count = CURVE_CACHE_FAST_COUNT(&(lut->sat_map));
264   double h, s, l;
265   double oh;
266   rgbout[0] ^= 65535;
267   rgbout[1] ^= 65535;
268   rgbout[2] ^= 65535;
269   calc_rgb_to_hsl(rgbout, &h, &s, &l);
270   s = update_saturation(s, ssat, isat, 0);
271   if (!adjust_hue_only && lut->sat_map.d_cache)
272     {
273       double nh = h * sat_count / 6.0;
274       double tmp = interpolate_value(sat_map, nh);
275       if (tmp < .9999 || tmp > 1.0001)
276 	s = update_saturation(s, tmp, tmp > 1.0 ? 1.0 / tmp : 1.0,
277 			      bright_colors);
278     }
279   oh = h;
280   h = adjust_hue(hue_map, h, hue_count);
281   calc_hsl_to_rgb(rgbout, h, s, l);
282 
283   if (!adjust_hue_only && s > 0.00001)
284     {
285       /*
286        * Perform luminosity adjustment only on color component.
287        * This way the luminosity of the gray component won't be affected.
288        * We'll add the gray back at the end.
289        */
290 
291       unsigned gray = FMIN(rgbout[0], FMIN(rgbout[1], rgbout[2]));
292       int i;
293       /*
294        * Scale the components by the amount of color left.
295        * This way the luminosity calculations will come out right.
296        */
297       if (gray > 0)
298 	for (i = 0; i < 3; i++)
299 	  rgbout[i] = (rgbout[i] - gray) * 65535.0 / (65535 - gray);
300 
301       if (lut->lum_map.d_cache)
302 	{
303 	  calc_rgb_to_hsl(rgbout, &h, &s, &l);
304 	  if (lut->lum_map.d_cache && l > 0.00001 && l < .99999)
305 	    {
306 	      double nh = oh * lum_count / 6.0;
307 	      double oel = interpolate_value(lum_map,nh);
308 	      if (oel <= 1)
309 		l *= oel;
310 	      else
311 		{
312 		  double g1 = pow(l, 1.0 / oel);
313 		  double g2 = 1.0 - pow(1.0 - l, oel);
314 		  l = FMIN(g1, g2);
315 		}
316 	      calc_hsl_to_rgb(rgbout, h, s, l);
317 	    }
318 	}
319       if (gray > 0)
320 	for (i = 0; i < 3; i++)
321 	  rgbout[i] = gray + (rgbout[i] * (65535 - gray) / 65535.0);
322     }
323 
324   rgbout[0] ^= 65535;
325   rgbout[1] ^= 65535;
326   rgbout[2] ^= 65535;
327 }
328 
329 #define GENERIC_COLOR_FUNC(fromname, toname)				\
330 CFUNC									\
331 fromname##_to_##toname(const stp_vars_t *vars, const unsigned char *in,	\
332 		       unsigned short *out)				\
333 {									\
334   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
335   if (!lut->printed_colorfunc)						\
336     {									\
337       lut->printed_colorfunc = 1;					\
338       stp_dprintf(STP_DBG_COLORFUNC, vars,				\
339 		   "Colorfunc is %s_%d_to_%s, %s, %s, %d, %d\n",	\
340 		   #fromname, lut->channel_depth, #toname,		\
341 		   lut->input_color_description->name,			\
342 		   lut->output_color_description->name,			\
343 		   lut->steps, lut->invert_output);			\
344     }									\
345   if (lut->channel_depth == 8)						\
346     return fromname##_8_to_##toname(vars, in, out);			\
347   else									\
348     return fromname##_16_to_##toname(vars, in, out);			\
349 }
350 
351 #define BD(bits) (65535u / (unsigned) MAXB(bits))
352 
353 #define COLOR_TO_COLOR_FUNC(T, bits)					\
354 CFUNC									\
355 color_##bits##_to_color(const stp_vars_t *vars, const unsigned char *in, \
356 			unsigned short *out)				\
357 {									\
358   int i;								\
359   double isat = 1.0;							\
360   double ssat = stp_get_float_parameter(vars, "Saturation");		\
361   double sbright = stp_get_float_parameter(vars, "Brightness");		\
362   int i0 = -1;								\
363   int i1 = -1;								\
364   int i2 = -1;								\
365   unsigned short o0 = 0;						\
366   unsigned short o1 = 0;						\
367   unsigned short o2 = 0;						\
368   unsigned short nz0 = 0;						\
369   unsigned short nz1 = 0;						\
370   unsigned short nz2 = 0;						\
371   const unsigned short *red;						\
372   const unsigned short *green;						\
373   const unsigned short *blue;						\
374   const unsigned short *brightness;					\
375   const unsigned short *contrast;					\
376   const T *s_in = (const T *) in;					\
377   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
378   int compute_saturation = ssat <= .99999 || ssat >= 1.00001;		\
379   int split_saturation = ssat > 1.4;					\
380   int bright_color_adjustment = 0;					\
381   int hue_only_color_adjustment = 0;					\
382   int do_user_adjustment = 0;						\
383   if (lut->color_correction->correction == COLOR_CORRECTION_BRIGHT)	\
384     bright_color_adjustment = 1;					\
385   if (lut->color_correction->correction == COLOR_CORRECTION_HUE)	\
386     hue_only_color_adjustment = 1;					\
387   if (sbright != 1)							\
388     do_user_adjustment = 1;						\
389   compute_saturation |= do_user_adjustment;				\
390 									\
391   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				\
392     stp_curve_resample(stp_curve_cache_get_curve(&(lut->channel_curves[i])), \
393 		       1 << bits);					\
394   stp_curve_resample							\
395     (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536);	\
396   stp_curve_resample							\
397     (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \
398   red =									\
399     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	\
400   green =								\
401     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	\
402   blue =								\
403     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	\
404   brightness=								\
405     stp_curve_cache_get_ushort_data(&(lut->brightness_correction));	\
406   contrast =								\
407     stp_curve_cache_get_ushort_data(&(lut->contrast_correction));	\
408   (void) stp_curve_cache_get_double_data(&(lut->hue_map));		\
409   (void) stp_curve_cache_get_double_data(&(lut->lum_map));		\
410   (void) stp_curve_cache_get_double_data(&(lut->sat_map));		\
411   const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map));	\
412   const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map));	\
413   const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map));	\
414 									\
415   if (split_saturation)							\
416     ssat = sqrt(ssat);							\
417   if (ssat > 1)								\
418     isat = 1.0 / ssat;							\
419   for (i = 0; i < lut->image_width; i++)				\
420     {									\
421       if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2])		\
422 	{								\
423 	  out[0] = o0;							\
424 	  out[1] = o1;							\
425 	  out[2] = o2;							\
426 	}								\
427       else								\
428 	{								\
429 	  i0 = s_in[0];							\
430 	  i1 = s_in[1];							\
431 	  i2 = s_in[2];							\
432 	  out[0] = contrast[i0];					\
433 	  out[1] = contrast[i1];					\
434 	  out[2] = contrast[i2];				 	\
435 	  if ((compute_saturation))					\
436 	    update_saturation_from_rgb(out, brightness, ssat, isat,	\
437 				       do_user_adjustment);		\
438 	  if ((split_saturation || lum_map || hue_map || sat_map) &&	\
439 	      (out[0] != out[1] || out[0] != out[2]))			\
440 	    adjust_hsl(out, lut, ssat, isat, split_saturation,		\
441 		       hue_only_color_adjustment, bright_color_adjustment); \
442 	  out[0] = red[out[0] / BD(bits)];				\
443 	  out[1] = green[out[1] / BD(bits)];				\
444 	  out[2] = blue[out[2] / BD(bits)];				\
445 	  o0 = out[0];							\
446 	  o1 = out[1];							\
447 	  o2 = out[2];							\
448 	  nz0 |= o0;							\
449 	  nz1 |= o1;							\
450 	  nz2 |= o2;							\
451 	}								\
452       s_in += 3;							\
453       out += 3;								\
454     }									\
455   return (nz0 ? 0 : 1) +  (nz1 ? 0 : 2) +  (nz2 ? 0 : 4);		\
456 }
457 
458 COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color
459 COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color
GENERIC_COLOR_FUNC(color,color)460 GENERIC_COLOR_FUNC(color, color)
461 
462 #define COLOR_TO_KCMY_FUNC(T, bits)					\
463 CFUNC									\
464 color_##bits##_to_kcmy(const stp_vars_t *vars, const unsigned char *in,	\
465 		      unsigned short *out)				\
466 {									\
467   int i;								\
468   double isat = 1.0;							\
469   double ssat = stp_get_float_parameter(vars, "Saturation");		\
470   double sbright = stp_get_float_parameter(vars, "Brightness");		\
471   union {								\
472     unsigned short nz[4];						\
473     unsigned long long nzl;						\
474   } nzx;								\
475   unsigned retval = 0;							\
476   const unsigned short *red;						\
477   const unsigned short *green;						\
478   const unsigned short *blue;						\
479   const unsigned short *brightness;					\
480   const unsigned short *contrast;					\
481   const T *s_in = (const T *) in;					\
482   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
483   int compute_saturation = ssat <= .99999 || ssat >= 1.00001;		\
484   int split_saturation = ssat > 1.4;					\
485   int bright_color_adjustment = 0;					\
486   int hue_only_color_adjustment = 0;					\
487   int do_user_adjustment = 0;						\
488   if (lut->color_correction->correction == COLOR_CORRECTION_BRIGHT)	\
489     bright_color_adjustment = 1;					\
490   if (lut->color_correction->correction == COLOR_CORRECTION_HUE)	\
491     hue_only_color_adjustment = 1;					\
492   if (sbright != 1)							\
493     do_user_adjustment = 1;						\
494   compute_saturation |= do_user_adjustment;				\
495   nzx.nzl = 0ull;							\
496 									\
497   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				\
498     stp_curve_resample(stp_curve_cache_get_curve(&(lut->channel_curves[i])), \
499 		       1 << bits);					\
500   stp_curve_resample							\
501     (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536);	\
502   stp_curve_resample							\
503     (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \
504   red =									\
505     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	\
506   green =								\
507     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	\
508   blue =								\
509     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	\
510   brightness=								\
511     stp_curve_cache_get_ushort_data(&(lut->brightness_correction));	\
512   contrast =								\
513     stp_curve_cache_get_ushort_data(&(lut->contrast_correction));	\
514   (void) stp_curve_cache_get_double_data(&(lut->hue_map));		\
515   (void) stp_curve_cache_get_double_data(&(lut->lum_map));		\
516   (void) stp_curve_cache_get_double_data(&(lut->sat_map));		\
517   const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map));	\
518   const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map));	\
519   const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map));	\
520 									\
521   if (split_saturation)							\
522     ssat = sqrt(ssat);							\
523   if (ssat > 1)								\
524     isat = 1.0 / ssat;							\
525   for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3)		\
526     {									\
527       out[1] = contrast[s_in[0]];				\
528       out[2] = contrast[s_in[1]];				\
529       out[3] = contrast[s_in[2]];				\
530       if ((compute_saturation))						\
531 	update_saturation_from_rgb(out + 1, brightness, ssat, isat,	\
532 				   do_user_adjustment);			\
533       if ((split_saturation || lum_map || hue_map || sat_map) &&	\
534 	  (out[1] != out[2] || out[1] != out[3]))			\
535 	adjust_hsl(out + 1, lut, ssat, isat, split_saturation,		\
536 		   hue_only_color_adjustment, bright_color_adjustment);	\
537       out[1] = red[out[1] / BD(bits)];					\
538       out[2] = green[out[2] / BD(bits)];				\
539       out[3] = blue[out[3] / BD(bits)];					\
540       out[0] = FMIN(out[1], FMIN(out[2], out[3]));			\
541       out[1] -= out[0];							\
542       out[2] -= out[0];							\
543       out[3] -= out[0];							\
544       nzx.nzl |= *(unsigned long long *) out;				\
545     }									\
546   for (i = 0; i < 4; i++)						\
547     if (nzx.nz[i] == 0)							\
548       retval |= (1 << i);						\
549   return retval;							\
550 }
551 
552 COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy
553 COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_kcmy
554 GENERIC_COLOR_FUNC(color, kcmy)
555 
556 /*
557  * 'rgb_to_rgb()' - Convert rgb image data to RGB.
558  */
559 
560 #define FAST_COLOR_TO_COLOR_FUNC(T, bits)				\
561 CFUNC									\
562 color_##bits##_to_color_fast(const stp_vars_t *vars, const unsigned char *in, \
563 			     unsigned short *out)			\
564 {									\
565   int i;								\
566   int i0 = -1;								\
567   int i1 = -1;								\
568   int i2 = -1;								\
569   int o0 = 0;								\
570   int o1 = 0;								\
571   int o2 = 0;								\
572   int nz0 = 0;								\
573   int nz1 = 0;								\
574   int nz2 = 0;								\
575   const T *s_in = (const T *) in;					\
576   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
577   const unsigned short *red;						\
578   const unsigned short *green;						\
579   const unsigned short *blue;						\
580   const unsigned short *brightness;					\
581   const unsigned short *contrast;					\
582   double isat = 1.0;							\
583   double saturation = stp_get_float_parameter(vars, "Saturation");	\
584   double sbright = stp_get_float_parameter(vars, "Brightness");		\
585   int compute_saturation = saturation <= .99999 || saturation >= 1.00001; \
586   int do_user_adjustment = 0;						\
587   if (sbright != 1)							\
588     do_user_adjustment = 1;						\
589   compute_saturation |= do_user_adjustment;				\
590 									\
591   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				\
592     stp_curve_resample(lut->channel_curves[i].curve, 65536);		\
593   stp_curve_resample							\
594     (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536);	\
595   stp_curve_resample							\
596     (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \
597   red =									\
598     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	\
599   green =								\
600     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	\
601   blue =								\
602     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	\
603   brightness=								\
604     stp_curve_cache_get_ushort_data(&(lut->brightness_correction));	\
605   contrast =								\
606     stp_curve_cache_get_ushort_data(&(lut->contrast_correction));	\
607 									\
608   if (saturation > 1)							\
609     isat = 1.0 / saturation;						\
610   for (i = 0; i < lut->image_width; i++)				\
611     {									\
612       if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2])		\
613 	{								\
614 	  out[0] = o0;							\
615 	  out[1] = o1;							\
616 	  out[2] = o2;							\
617 	}								\
618       else								\
619 	{								\
620 	  i0 = s_in[0];							\
621 	  i1 = s_in[1];							\
622 	  i2 = s_in[2];							\
623 	  out[0] = contrast[s_in[0]];					\
624 	  out[1] = contrast[s_in[1]];					\
625 	  out[2] = contrast[s_in[2]];					\
626 	  if ((compute_saturation))					\
627 	    update_saturation_from_rgb(out, brightness, saturation, isat, 1); \
628 	  out[0] = red[out[0]];						\
629 	  out[1] = green[out[1]];					\
630 	  out[2] = blue[out[2]];					\
631 	  o0 = out[0];							\
632 	  o1 = out[1];							\
633 	  o2 = out[2];							\
634 	  nz0 |= o0;							\
635 	  nz1 |= o1;							\
636 	  nz2 |= o2;							\
637 	}								\
638       s_in += 3;							\
639       out += 3;								\
640     }									\
641   return (nz0 ? 0 : 1) +  (nz1 ? 0 : 2) +  (nz2 ? 0 : 4);		\
642 }
643 
644 FAST_COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color_fast
645 FAST_COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color_fast
646 GENERIC_COLOR_FUNC(color, color_fast)
647 
648 #define FAST_COLOR_TO_KCMY_FUNC(T, bits)				\
649 CFUNC									\
650 color_##bits##_to_kcmy_fast(const stp_vars_t *vars, const unsigned char *in, \
651 			     unsigned short *out)			\
652 {									\
653   int i;								\
654   union {								\
655     unsigned short nz[4];						\
656     unsigned long long nzl;						\
657   } nzx;								\
658   unsigned retval = 0;							\
659   unsigned short c, m, y, k;						\
660   const T *s_in = (const T *) in;					\
661   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
662   const unsigned short *red;						\
663   const unsigned short *green;						\
664   const unsigned short *blue;						\
665   const unsigned short *brightness;					\
666   const unsigned short *contrast;					\
667   double isat = 1.0;							\
668   double saturation = stp_get_float_parameter(vars, "Saturation");	\
669   double sbright = stp_get_float_parameter(vars, "Brightness");		\
670   int compute_saturation = saturation <= .99999 || saturation >= 1.00001; \
671   int do_user_adjustment = 0;						\
672   if (sbright != 1)							\
673     do_user_adjustment = 1;						\
674   compute_saturation |= do_user_adjustment;				\
675   nzx.nzl = 0ull;							\
676 									\
677   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				\
678     stp_curve_resample(lut->channel_curves[i].curve, 65536);		\
679   stp_curve_resample							\
680     (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536);	\
681   stp_curve_resample							\
682     (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \
683   red =									\
684     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	\
685   green =								\
686     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	\
687   blue =								\
688     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	\
689   brightness=								\
690     stp_curve_cache_get_ushort_data(&(lut->brightness_correction));	\
691   contrast =								\
692     stp_curve_cache_get_ushort_data(&(lut->contrast_correction));	\
693 									\
694   if (saturation > 1)							\
695     isat = 1.0 / saturation;						\
696   for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3)		\
697     {									\
698       c = contrast[s_in[0]];						\
699       m = contrast[s_in[1]];						\
700       y = contrast[s_in[2]];						\
701       if (compute_saturation)						\
702 	{								\
703 	  unsigned short tmp[3];					\
704 	  tmp[0] = c;							\
705 	  tmp[1] = m;							\
706 	  tmp[2] = y;							\
707 	  update_saturation_from_rgb(tmp, brightness, saturation,	\
708 				     isat, 1);				\
709 	  c = tmp[0];							\
710 	  m = tmp[1];							\
711 	  y = tmp[2];							\
712 	}								\
713       c = red[c];							\
714       m = green[m];							\
715       y = blue[y];							\
716       k = FMIN(c, FMIN(m, y));						\
717       out[0] = k;							\
718       out[1] = c - k;							\
719       out[2] = m - k;							\
720       out[3] = y - k;							\
721       nzx.nzl |= *(unsigned long long *) out;				\
722     }									\
723   for (i = 0; i < 4; i++)						\
724     if (nzx.nz[i] == 0)							\
725       retval |= (1 << i);						\
726   return retval;							\
727 }
728 
729 FAST_COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy_fast
730 FAST_COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_color_fast
731 GENERIC_COLOR_FUNC(color, kcmy_fast)
732 
733 #define RAW_COLOR_TO_COLOR_FUNC(T, bits)				    \
734 CFUNC									    \
735 color_##bits##_to_color_raw(const stp_vars_t *vars, const unsigned char *in,\
736 			    unsigned short *out)			    \
737 {									    \
738   int i;								    \
739   int j;								    \
740   int nz = 0;								    \
741   const T *s_in = (const T *) in;					    \
742   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
743   unsigned mask = 0;							    \
744   if (lut->invert_output)						    \
745     mask = 0xffff;							    \
746 									    \
747   for (i = 0; i < lut->image_width; i++)				    \
748     {									    \
749       unsigned bit = 1;							    \
750       for (j = 0; j < 3; j++, bit += bit)				    \
751 	{								    \
752 	  out[j] = (s_in[j] * (65535 / ((1 << bits) - 1))) ^ mask;	    \
753 	  if (out[j])							    \
754 	    nz |= bit;							    \
755 	}								    \
756       s_in += 3;							    \
757       out += 3;								    \
758     }									    \
759   return nz;								    \
760 }
761 
762 RAW_COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color_raw
763 RAW_COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color_raw
764 GENERIC_COLOR_FUNC(color, color_raw)
765 
766 #define RAW_COLOR_TO_KCMY_FUNC(T, bits)					\
767 CFUNC									\
768 color_##bits##_to_kcmy_raw(const stp_vars_t *vars, const unsigned char *in, \
769 			    unsigned short *out)			\
770 {									\
771   int i;								\
772   union {								\
773     unsigned short nz[4];						\
774     unsigned long long nzl;						\
775   } nzx;								\
776   unsigned retval = 0;							\
777   const T *s_in = (const T *) in;					\
778   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
779   unsigned mask = 0;							\
780   if (lut->invert_output)						\
781     mask = 0xffff;							\
782   nzx.nzl = 0ull;							\
783 									\
784   for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3)		\
785     {									\
786       unsigned c = (s_in[0] * BD(bits)) ^ mask;				\
787       unsigned m = (s_in[1] * BD(bits)) ^ mask;				\
788       unsigned y = (s_in[2] * BD(bits)) ^ mask;				\
789       unsigned k = FMIN(c, FMIN(m, y));					\
790       out[0] = k;							\
791       out[1] = c - k;							\
792       out[2] = m - k;							\
793       out[3] = y - k;							\
794       nzx.nzl |= *(unsigned long long *) out;				\
795     }									\
796   for (i = 0; i < 4; i++)						\
797     if (nzx.nz[i] == 0)							\
798       retval |= (1 << i);						\
799   return retval;							\
800 }
801 
802 RAW_COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy_raw
803 RAW_COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_kcmy_raw
804 GENERIC_COLOR_FUNC(color, kcmy_raw)
805 
806 /*
807  * 'gray_to_rgb()' - Convert gray image data to RGB.
808  */
809 
810 #define GRAY_TO_COLOR_FUNC(T, bits)					    \
811 CFUNC									    \
812 gray_##bits##_to_color(const stp_vars_t *vars, const unsigned char *in,	    \
813 		   unsigned short *out)					    \
814 {									    \
815   int i;								    \
816   int i0 = -1;								    \
817   int o0 = 0;								    \
818   int o1 = 0;								    \
819   int o2 = 0;								    \
820   int nz0 = 0;								    \
821   int nz1 = 0;								    \
822   int nz2 = 0;								    \
823   const T *s_in = (const T *) in;					    \
824   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
825   const unsigned short *red;						    \
826   const unsigned short *green;						    \
827   const unsigned short *blue;						    \
828   const unsigned short *user;						    \
829 									    \
830   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				    \
831     stp_curve_resample(lut->channel_curves[i].curve, 65536);		    \
832   stp_curve_resample							    \
833     (stp_curve_cache_get_curve(&(lut->user_color_correction)), 1 << bits);  \
834   red =									    \
835     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	    \
836   green =								    \
837     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	    \
838   blue =								    \
839     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	    \
840   user =								    \
841     stp_curve_cache_get_ushort_data(&(lut->user_color_correction));	    \
842 									    \
843   for (i = 0; i < lut->image_width; i++)				    \
844     {									    \
845       if (i0 == s_in[0])						    \
846 	{								    \
847 	  out[0] = o0;							    \
848 	  out[1] = o1;							    \
849 	  out[2] = o2;							    \
850 	}								    \
851       else								    \
852 	{								    \
853 	  i0 = s_in[0];							    \
854 	  out[0] = red[user[s_in[0]]];					    \
855 	  out[1] = green[user[s_in[0]]];				    \
856 	  out[2] = blue[user[s_in[0]]];					    \
857 	  o0 = out[0];							    \
858 	  o1 = out[1];							    \
859 	  o2 = out[2];							    \
860 	  nz0 |= o0;							    \
861 	  nz1 |= o1;							    \
862 	  nz2 |= o2;							    \
863 	}								    \
864       s_in += 1;							    \
865       out += 3;								    \
866     }									    \
867   return (nz0 ? 0 : 1) +  (nz1 ? 0 : 2) +  (nz2 ? 0 : 4);		    \
868 }
869 
870 GRAY_TO_COLOR_FUNC(unsigned char, 8) // gray_8_to_color
871 GRAY_TO_COLOR_FUNC(unsigned short, 16) // gray_16_to_color
872 GENERIC_COLOR_FUNC(gray, color)
873 
874 #define GRAY_TO_KCMY_FUNC(T, bits)					\
875 CFUNC									\
876 gray_##bits##_to_kcmy(const stp_vars_t *vars, const unsigned char *in,	\
877 		      unsigned short *out)				\
878 {									\
879   int i;								\
880   union {								\
881     unsigned short nz[4];						\
882     unsigned long long nzl;						\
883   } nzx;								\
884   unsigned retval = 0;							\
885   const T *s_in = (const T *) in;					\
886   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
887   const unsigned short *red;						\
888   const unsigned short *green;						\
889   const unsigned short *blue;						\
890   const unsigned short *user;						\
891 									\
892   for (i = CHANNEL_C; i <= CHANNEL_Y; i++)				\
893     stp_curve_resample(lut->channel_curves[i].curve, 65536);		\
894   stp_curve_resample							\
895     (stp_curve_cache_get_curve(&(lut->user_color_correction)), 1 << bits); \
896   red =									\
897     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C]));	\
898   green =								\
899     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M]));	\
900   blue =								\
901     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y]));	\
902   user =								\
903     stp_curve_cache_get_ushort_data(&(lut->user_color_correction));	\
904 									\
905   for (i = 0; i < lut->image_width; i++, out += 4, s_in++)		\
906     {									\
907       out[1] = red[user[s_in[0]]];					\
908       out[2] = green[user[s_in[0]]];					\
909       out[3] = blue[user[s_in[0]]];					\
910       out[0] = FMIN(out[1], FMIN(out[2], out[3]));			\
911       out[1] -= out[0];							\
912       out[2] -= out[0];							\
913       out[3] -= out[0];							\
914       nzx.nzl |= *(unsigned long long *) out;				\
915     }									\
916   for (i = 0; i < 4; i++)						\
917     if (nzx.nz[i] == 0)							\
918       retval |= (1 << i);						\
919   return retval;							\
920 }
921 
922 GRAY_TO_KCMY_FUNC(unsigned char, 8) // gray_8_to_kcmy
923 GRAY_TO_KCMY_FUNC(unsigned short, 16) // gray_16_to_kcmy
924 GENERIC_COLOR_FUNC(gray, kcmy)
925 
926 #define GRAY_TO_COLOR_RAW_FUNC(T, bits)					   \
927 CFUNC									   \
928 gray_##bits##_to_color_raw(const stp_vars_t *vars, const unsigned char *in,\
929 			   unsigned short *out)				   \
930 {									   \
931   int i;								   \
932   int nz = 7;								   \
933   const T *s_in = (const T *) in;					   \
934   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	   \
935   unsigned mask = 0;							   \
936   if (lut->invert_output)						   \
937     mask = 0xffff;							   \
938 									   \
939   for (i = 0; i < lut->image_width; i++)				   \
940     {									   \
941       unsigned outval = (s_in[0] * (65535 / (1 << bits))) ^ mask;	   \
942       out[0] = outval;							   \
943       out[1] = outval;							   \
944       out[2] = outval;							   \
945       if (outval)							   \
946 	nz = 0;								   \
947       s_in++;								   \
948       out += 3;								   \
949     }									   \
950   return nz;								   \
951 }
952 
953 GRAY_TO_COLOR_RAW_FUNC(unsigned char, 8) // gray_8_to_color_raw
954 GRAY_TO_COLOR_RAW_FUNC(unsigned short, 16) // gray_16_to_color_raw
955 GENERIC_COLOR_FUNC(gray, color_raw)
956 
957 #define GRAY_TO_KCMY_RAW_FUNC(T, bits)					\
958 CFUNC									\
959 gray_##bits##_to_kcmy_raw(const stp_vars_t *vars, const unsigned char *in, \
960 			   unsigned short *out)				\
961 {									\
962   int i;								\
963   int nz = 7;								\
964   const T *s_in = (const T *) in;					\
965   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
966   unsigned mask = 0;							\
967   if (lut->invert_output)						\
968     mask = 0xffff;							\
969 									\
970   for (i = 0; i < lut->image_width; i++, out += 4, s_in++)		\
971     {									\
972       unsigned outval = (s_in[0] * (65535 / (1 << bits))) ^ mask;	\
973       out[0] = outval;							\
974       out[1] = 0;							\
975       out[2] = 0;							\
976       out[3] = 0;							\
977       if (outval)							\
978 	nz = 0;								\
979     }									\
980   return nz;								\
981 }
982 
983 GRAY_TO_KCMY_RAW_FUNC(unsigned char, 8) // gray_8_to_kcmy_raw
984 GRAY_TO_KCMY_RAW_FUNC(unsigned short, 16) // gray_16_to_kcmy_raw
985 GENERIC_COLOR_FUNC(gray, kcmy_raw)
986 
987 #define COLOR_TO_KCMY_THRESHOLD_FUNC(T, name)				\
988 CFUNC									\
989 name##_to_kcmy_threshold(const stp_vars_t *vars,			\
990 			const unsigned char *in,			\
991 			unsigned short *out)				\
992 {									\
993   int i;								\
994   int z = 15;								\
995   const T *s_in = (const T *) in;					\
996   unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)));			\
997   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
998   int width = lut->image_width;						\
999   unsigned mask = 0;							\
1000   memset(out, 0, width * 4 * sizeof(unsigned short));			\
1001   if (lut->invert_output)						\
1002     mask = (1 << (sizeof(T) * 8)) - 1;					\
1003 									\
1004   for (i = 0; i < width; i++, out += 4, s_in += 3)			\
1005     {									\
1006       unsigned c = s_in[0] ^ mask;					\
1007       unsigned m = s_in[1] ^ mask;					\
1008       unsigned y = s_in[2] ^ mask;					\
1009       unsigned k = (c < m ? (c < y ? c : y) : (m < y ? m : y));		\
1010       if (k >= high_bit)						\
1011 	{								\
1012 	  c -= k;							\
1013 	  m -= k;							\
1014 	  y -= k;							\
1015 	}								\
1016       if (k >= high_bit)						\
1017 	{								\
1018 	  z &= 0xe;							\
1019 	  out[0] = 65535;						\
1020 	}								\
1021       if (c >= high_bit)						\
1022 	{								\
1023 	  z &= 0xd;							\
1024 	  out[1] = 65535;						\
1025 	}								\
1026       if (m >= high_bit)						\
1027 	{								\
1028 	  z &= 0xb;							\
1029 	  out[2] = 65535;						\
1030 	}								\
1031       if (y >= high_bit)						\
1032 	{								\
1033 	  z &= 0x7;							\
1034 	  out[3] = 65535;						\
1035 	}								\
1036     }									\
1037   return z;								\
1038 }
1039 
1040 COLOR_TO_KCMY_THRESHOLD_FUNC(unsigned char, color_8) // color_8_to_kcmy_threshold
1041 COLOR_TO_KCMY_THRESHOLD_FUNC(unsigned short, color_16) // color_16_to_kcmy_threshold
1042 GENERIC_COLOR_FUNC(color, kcmy_threshold)
1043 
1044 #define CMYK_TO_KCMY_THRESHOLD_FUNC(T, name)				\
1045 CFUNC									\
1046 name##_to_kcmy_threshold(const stp_vars_t *vars,			\
1047 			const unsigned char *in,			\
1048 			unsigned short *out)				\
1049 {									\
1050   int i;								\
1051   int z = 15;								\
1052   const T *s_in = (const T *) in;					\
1053   unsigned desired_high_bit = 0;					\
1054   unsigned high_bit = 1 << ((sizeof(T) * 8) - 1);			\
1055   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1056   int width = lut->image_width;						\
1057   memset(out, 0, width * 4 * sizeof(unsigned short));			\
1058   if (!lut->invert_output)						\
1059     desired_high_bit = high_bit;					\
1060 									\
1061   for (i = 0; i < width; i++, out += 4, s_in += 4)			\
1062     {									\
1063       if ((s_in[3] & high_bit) == desired_high_bit)			\
1064 	{								\
1065 	  z &= 0xe;							\
1066 	  out[0] = 65535;						\
1067 	}								\
1068       if ((s_in[0] & high_bit) == desired_high_bit)			\
1069 	{								\
1070 	  z &= 0xd;							\
1071 	  out[1] = 65535;						\
1072 	}								\
1073       if ((s_in[1] & high_bit) == desired_high_bit)			\
1074 	{								\
1075 	  z &= 0xb;							\
1076 	  out[2] = 65535;						\
1077 	}								\
1078       if ((s_in[2] & high_bit) == desired_high_bit)			\
1079 	{								\
1080 	  z &= 0x7;							\
1081 	  out[3] = 65535;						\
1082 	}								\
1083     }									\
1084   return z;								\
1085 }
1086 
1087 CMYK_TO_KCMY_THRESHOLD_FUNC(unsigned char, cmyk_8) // cmyk_8_to_kcmy_threshold
1088 CMYK_TO_KCMY_THRESHOLD_FUNC(unsigned short, cmyk_16) // cmyk_16_to_kcmy_threshodl
1089 GENERIC_COLOR_FUNC(cmyk, kcmy_threshold)
1090 
1091 #define KCMY_TO_KCMY_THRESHOLD_FUNC(T, name)				\
1092 CFUNC									\
1093 name##_to_kcmy_threshold(const stp_vars_t *vars,			\
1094 			 const unsigned char *in,			\
1095 			 unsigned short *out)				\
1096 {									\
1097   int i;								\
1098   int j;								\
1099   unsigned nz[4];							\
1100   unsigned z = 0xf;							\
1101   const T *s_in = (const T *) in;					\
1102   unsigned desired_high_bit = 0;					\
1103   unsigned high_bit = 1 << ((sizeof(T) * 8) - 1);			\
1104   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1105   int width = lut->image_width;						\
1106   memset(out, 0, width * 4 * sizeof(unsigned short));			\
1107   if (!lut->invert_output)						\
1108     desired_high_bit = high_bit;					\
1109   for (i = 0; i < 4; i++)						\
1110     nz[i] = z & ~(1 << i);						\
1111 									\
1112   for (i = 0; i < width; i++)						\
1113     {									\
1114       for (j = 0; j < 4; j++)						\
1115 	{								\
1116 	  if ((*s_in++ & high_bit) == desired_high_bit)			\
1117 	    {								\
1118 	      z &= nz[j];						\
1119 	      *out = 65535;						\
1120 	    }								\
1121 	  out++;							\
1122 	}								\
1123     }									\
1124   return z;								\
1125 }
1126 
1127 KCMY_TO_KCMY_THRESHOLD_FUNC(unsigned char, kcmy_8) // kcmy_8_to_kcmy_threshold
1128 KCMY_TO_KCMY_THRESHOLD_FUNC(unsigned short, kcmy_16) // kcmy_8_to_kcmy_threshold
1129 GENERIC_COLOR_FUNC(kcmy, kcmy_threshold)
1130 
1131 #define GRAY_TO_COLOR_THRESHOLD_FUNC(T, name, bits, channels)		\
1132 CFUNC									\
1133 gray_##bits##_to_##name##_threshold(const stp_vars_t *vars,		\
1134 				    const unsigned char *in,		\
1135 				    unsigned short *out)		\
1136 {									\
1137   int i;								\
1138   int z = (1 << channels) - 1;						\
1139   int desired_high_bit = 0;						\
1140   unsigned high_bit = 1 << ((sizeof(T) * 8) - 1);			\
1141   const T *s_in = (const T *) in;					\
1142   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1143   int width = lut->image_width;						\
1144   memset(out, 0, width * channels * sizeof(unsigned short));		\
1145   if (!lut->invert_output)						\
1146     desired_high_bit = high_bit;					\
1147 									\
1148   for (i = 0; i < width; i++, out += channels, s_in++)			\
1149     {									\
1150       if ((s_in[0] & high_bit) == desired_high_bit)			\
1151 	{								\
1152 	  int j;							\
1153 	  z = 0;							\
1154 	  for (j = 0; j < channels; j++)				\
1155 	    out[j] = 65535;						\
1156 	}								\
1157     }									\
1158   return z;								\
1159 }
1160 
1161 
1162 GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned char, color, 8, 3) // gray_8_to_color_threshold
1163 GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned short, color, 16, 3) // gray_16_to_color_threshold
1164 GENERIC_COLOR_FUNC(gray, color_threshold)
1165 
1166 GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned char, kcmy, 8, 4) // gray_8_to_kcmy_threshold
1167 GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned short, kcmy, 16, 4) // gray_16_to_kcmy_threshold
1168 GENERIC_COLOR_FUNC(gray, kcmy_threshold)
1169 
1170 #define COLOR_TO_COLOR_THRESHOLD_FUNC(T, name)				\
1171 CFUNC									\
1172 name##_to_color_threshold(const stp_vars_t *vars,			\
1173 		       const unsigned char *in,				\
1174 		       unsigned short *out)				\
1175 {									\
1176   int i;								\
1177   int z = 7;								\
1178   int desired_high_bit = 0;						\
1179   unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)) * 4);		\
1180   const T *s_in = (const T *) in;					\
1181   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1182   int width = lut->image_width;						\
1183   memset(out, 0, width * 3 * sizeof(unsigned short));			\
1184   if (!lut->invert_output)						\
1185     desired_high_bit = high_bit;					\
1186 									\
1187   for (i = 0; i < width; i++, out += 3, s_in += 3)			\
1188     {									\
1189       if ((s_in[0] & high_bit) == desired_high_bit)			\
1190 	{								\
1191 	  z &= 6;							\
1192 	  out[0] = 65535;						\
1193 	}								\
1194       if ((s_in[1] & high_bit) == desired_high_bit)			\
1195 	{								\
1196 	  z &= 5;							\
1197 	  out[1] = 65535;						\
1198 	}								\
1199       if ((s_in[1] & high_bit) == desired_high_bit)			\
1200 	{								\
1201 	  z &= 3;							\
1202 	  out[2] = 65535;						\
1203 	}								\
1204     }									\
1205   return z;								\
1206 }
1207 
1208 COLOR_TO_COLOR_THRESHOLD_FUNC(unsigned char, color_8) // color_8_to_color_threshold
1209 COLOR_TO_COLOR_THRESHOLD_FUNC(unsigned short, color_16) // color_8_to_color_threshold
1210 GENERIC_COLOR_FUNC(color, color_threshold)
1211 
1212 #define COLOR_TO_GRAY_THRESHOLD_FUNC(T, name, channels, max_channels)	\
1213 CFUNC									\
1214 name##_to_gray_threshold(const stp_vars_t *vars,			\
1215 			const unsigned char *in,			\
1216 			unsigned short *out)				\
1217 {									\
1218   int i;								\
1219   int z = 1;								\
1220   int desired_high_bit = 0;						\
1221   unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)));			\
1222   const T *s_in = (const T *) in;					\
1223   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1224   int width = lut->image_width;						\
1225   memset(out, 0, width * sizeof(unsigned short));			\
1226   if (!lut->invert_output)						\
1227     desired_high_bit = high_bit;					\
1228 									\
1229   for (i = 0; i < width; i++, out++, s_in += channels)			\
1230     {									\
1231       unsigned gval =							\
1232 	(max_channels - channels) * (1 << ((sizeof(T) * 8) - 1));	\
1233       int j;								\
1234       for (j = 0; j < channels; j++)					\
1235 	gval += s_in[j];						\
1236       gval /= channels;							\
1237       if ((gval & high_bit) == desired_high_bit)			\
1238 	{								\
1239 	  out[0] = 65535;						\
1240 	  z = 0;							\
1241 	}								\
1242     }									\
1243   return z;								\
1244 }
1245 
1246 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, cmyk_8, 4, 4) // cmyk_8_to_gray_threshold
1247 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, cmyk_16, 4, 4) // cmyk_16_to_gray_threshold
1248 GENERIC_COLOR_FUNC(cmyk, gray_threshold)
1249 
1250 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, kcmy_8, 4, 4) // kcmy_8_to_gray_threshold
1251 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, kcmy_16, 4, 4) // kcmy_16_to_gray_threshold
1252 GENERIC_COLOR_FUNC(kcmy, gray_threshold)
1253 
1254 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, color_8, 3, 3) // color_8_to_gray_threshold
1255 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, color_16, 3, 3) // color_16_to_gray_threshold
1256 GENERIC_COLOR_FUNC(color, gray_threshold)
1257 
1258 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, gray_8, 1, 1) // gray_8_to_gray_threshold
1259 COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, gray_16, 1, 1) // gray_16_to_gray_threshold
1260 GENERIC_COLOR_FUNC(gray, gray_threshold)
1261 
1262 #define CMYK_TO_COLOR_FUNC(namein, name2, T, bits, offset)		\
1263 static unsigned								\
1264 namein##_##bits##_to_##name2(const stp_vars_t *vars, const unsigned char *in, \
1265 			   unsigned short *out)				\
1266 {									\
1267   int i;								\
1268   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1269   unsigned status;							\
1270   size_t real_steps = lut->steps;					\
1271   const T *s_in = (const T *) in;					\
1272   unsigned short *tmp;							\
1273   int width = lut->image_width;						\
1274 									\
1275   if (!lut->cmy_tmp)							\
1276     lut->cmy_tmp = stp_malloc(3 * 2 * lut->image_width);		\
1277   tmp = lut->cmy_tmp;							\
1278   memset(lut->cmy_tmp, 0, width * 3 * sizeof(unsigned short));		\
1279 									\
1280   for (i = 0; i < width; i++, tmp += 3, s_in += 4)			\
1281     {									\
1282       unsigned c = (s_in[0 + offset] + s_in[(3 + offset) % 4]) *	\
1283 	(65535 / MAXB(bits));						\
1284       unsigned m = (s_in[1 + offset] + s_in[(3 + offset) % 4]) *	\
1285 	(65535 / MAXB(bits));						\
1286       unsigned y = (s_in[2 + offset] + s_in[(3 + offset) % 4]) *	\
1287 	(65535 / MAXB(bits));						\
1288       if (c > MAXB(16))							\
1289 	c = MAXB(16);							\
1290       if (m > MAXB(16))							\
1291 	m = MAXB(16);							\
1292       if (y > MAXB(16))							\
1293 	y = MAXB(16);							\
1294       tmp[0] = c;							\
1295       tmp[1] = m;							\
1296       tmp[2] = y;							\
1297     }									\
1298   lut->steps = 65536;							\
1299   status =								\
1300     color_16_to_##name2(vars, (const unsigned char *) lut->cmy_tmp, out); \
1301   lut->steps = real_steps;						\
1302   return status;							\
1303 }
1304 
1305 CMYK_TO_COLOR_FUNC(cmyk, color, unsigned char, 8, 0) // cmyk_8_to_color
1306 CMYK_TO_COLOR_FUNC(cmyk, color, unsigned short, 16, 0) // cmyk_16_to_color
1307 GENERIC_COLOR_FUNC(cmyk, color)
1308 CMYK_TO_COLOR_FUNC(kcmy, color, unsigned char, 8, 1) // kcmy_8_to_color
1309 CMYK_TO_COLOR_FUNC(kcmy, color, unsigned short, 16, 1) // kcmy_16_to_color
1310 GENERIC_COLOR_FUNC(kcmy, color)
1311 CMYK_TO_COLOR_FUNC(cmyk, color_threshold, unsigned char, 8, 0) // cmyk_8_to_color_threshold
1312 CMYK_TO_COLOR_FUNC(cmyk, color_threshold, unsigned short, 16, 0) // cmyk_16_to_color_threshold
1313 GENERIC_COLOR_FUNC(cmyk, color_threshold)
1314 CMYK_TO_COLOR_FUNC(kcmy, color_threshold, unsigned char, 8, 1) // kcmy_8_to_color_threshold
1315 CMYK_TO_COLOR_FUNC(kcmy, color_threshold, unsigned short, 16, 1) // kcmy_16_to_color_threshold
1316 GENERIC_COLOR_FUNC(kcmy, color_threshold)
1317 CMYK_TO_COLOR_FUNC(cmyk, color_fast, unsigned char, 8, 0) // cmyk_8_to_color_fast
1318 CMYK_TO_COLOR_FUNC(cmyk, color_fast, unsigned short, 16, 0) // cmyk_16_to_color_fast
1319 GENERIC_COLOR_FUNC(cmyk, color_fast)
1320 CMYK_TO_COLOR_FUNC(kcmy, color_fast, unsigned char, 8, 1) // kcmy_8_to_color_fast
1321 CMYK_TO_COLOR_FUNC(kcmy, color_fast, unsigned short, 16, 1) // kcmy_16_to_color_fast
1322 GENERIC_COLOR_FUNC(kcmy, color_fast)
1323 CMYK_TO_COLOR_FUNC(cmyk, color_raw, unsigned char, 8, 0) // cmyk_8_to_color_raw
1324 CMYK_TO_COLOR_FUNC(cmyk, color_raw, unsigned short, 16, 0) // cmyk_16_to_color_raw
1325 GENERIC_COLOR_FUNC(cmyk, color_raw)
1326 CMYK_TO_COLOR_FUNC(kcmy, color_raw, unsigned char, 8, 1) // kcmy_8_to_color_raw
1327 CMYK_TO_COLOR_FUNC(kcmy, color_raw, unsigned short, 16, 1) // kcmy_16_to_color_raw
1328 GENERIC_COLOR_FUNC(kcmy, color_raw)
1329 
1330 #define CMYK_TO_KCMY_FUNC(T, size)					    \
1331 CFUNC									    \
1332 cmyk_##size##_to_kcmy(const stp_vars_t *vars,				    \
1333 		      const unsigned char *in,				    \
1334 		      unsigned short *out)				    \
1335 {									    \
1336   int i;								    \
1337   unsigned retval = 0;							    \
1338   int j;								    \
1339   int nz[4];								    \
1340   const T *s_in = (const T *) in;					    \
1341   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1342   const unsigned short *user;						    \
1343   const unsigned short *maps[4];					    \
1344 									    \
1345   for (i = 0; i < 4; i++)						    \
1346     {									    \
1347       stp_curve_resample(lut->channel_curves[i].curve, 65536);		    \
1348       maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \
1349     }									    \
1350   stp_curve_resample(lut->user_color_correction.curve, 1 << size);	    \
1351   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));    \
1352 									    \
1353   memset(nz, 0, sizeof(nz));						    \
1354 									    \
1355   for (i = 0; i < lut->image_width; i++, out += 4)			    \
1356     {									    \
1357       for (j = 0; j < 4; j++)						    \
1358 	{								    \
1359 	  int outpos = (j + 1) & 3;					    \
1360 	  int inval = *s_in++;						    \
1361 	  nz[outpos] |= inval;						    \
1362 	  out[outpos] = maps[outpos][user[inval]];			    \
1363 	}								    \
1364     }									    \
1365   for (j = 0; j < 4; j++)						    \
1366     if (nz[j] == 0)							    \
1367       retval |= (1 << j);						    \
1368   return retval;							    \
1369 }
1370 
1371 CMYK_TO_KCMY_FUNC(unsigned char, 8) // cmyk_8_to_kcmy
1372 CMYK_TO_KCMY_FUNC(unsigned short, 16) // cmyk_16_to_kcmy
1373 GENERIC_COLOR_FUNC(cmyk, kcmy)
1374 
1375 #define KCMY_TO_KCMY_FUNC(T, size)					    \
1376 CFUNC									    \
1377 kcmy_##size##_to_kcmy(const stp_vars_t *vars,				    \
1378 		      const unsigned char *in,				    \
1379 		      unsigned short *out)				    \
1380 {									    \
1381   int i;								    \
1382   unsigned retval = 0;							    \
1383   int j;								    \
1384   int nz[4];								    \
1385   const T *s_in = (const T *) in;					    \
1386   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1387   const unsigned short *user;						    \
1388   const unsigned short *maps[4];					    \
1389 									    \
1390   for (i = 0; i < 4; i++)						    \
1391     {									    \
1392       stp_curve_resample(lut->channel_curves[i].curve, 65536);		    \
1393       maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \
1394     }									    \
1395   stp_curve_resample(lut->user_color_correction.curve, 1 << size);	    \
1396   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));    \
1397 									    \
1398   memset(nz, 0, sizeof(nz));						    \
1399 									    \
1400   for (i = 0; i < lut->image_width; i++, out += 4)			    \
1401     {									    \
1402       for (j = 0; j < 4; j++)						    \
1403 	{								    \
1404 	  int inval = *s_in++;						    \
1405 	  nz[j] |= inval;						    \
1406 	  out[j] = maps[j][user[inval]];				    \
1407 	}								    \
1408     }									    \
1409   for (j = 0; j < 4; j++)						    \
1410     if (nz[j] == 0)							    \
1411       retval |= (1 << j);						    \
1412   return retval;							    \
1413 }
1414 
1415 KCMY_TO_KCMY_FUNC(unsigned char, 8) // kcmy_8_to_kcmy
1416 KCMY_TO_KCMY_FUNC(unsigned short, 16) // kcmy_16_to_kcmy
1417 GENERIC_COLOR_FUNC(kcmy, kcmy)
1418 
1419 
1420 #define GRAY_TO_GRAY_FUNC(T, bits)					   \
1421 CFUNC									   \
1422 gray_##bits##_to_gray(const stp_vars_t *vars,				   \
1423 		      const unsigned char *in,				   \
1424 		      unsigned short *out)				   \
1425 {									   \
1426   int i;								   \
1427   int i0 = -1;								   \
1428   int o0 = 0;								   \
1429   int nz = 0;								   \
1430   const T *s_in = (const T *) in;					   \
1431   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	   \
1432   int width = lut->image_width;						   \
1433   const unsigned short *composite;					   \
1434   const unsigned short *user;						   \
1435 									   \
1436   stp_curve_resample							   \
1437     (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536); \
1438   composite =								   \
1439     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K]));	   \
1440   stp_curve_resample(lut->user_color_correction.curve, 1 << bits);	   \
1441   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));   \
1442 									   \
1443   memset(out, 0, width * sizeof(unsigned short));			   \
1444 									   \
1445   for (i = 0; i < lut->image_width; i++)				   \
1446     {									   \
1447       if (i0 != s_in[0])						   \
1448 	{								   \
1449 	  i0 = s_in[0];							   \
1450 	  o0 = composite[user[i0]];					   \
1451 	  nz |= o0;							   \
1452 	}								   \
1453       out[0] = o0;							   \
1454       s_in ++;								   \
1455       out ++;								   \
1456     }									   \
1457   return nz == 0;							   \
1458 }
1459 
1460 GRAY_TO_GRAY_FUNC(unsigned char, 8) // gray_8_to_gray
1461 GRAY_TO_GRAY_FUNC(unsigned short, 16) // gray_16_to_gray
1462 GENERIC_COLOR_FUNC(gray, gray)
1463 
1464 #define COLOR_TO_GRAY_FUNC(T, bits)					      \
1465 CFUNC									      \
1466 color_##bits##_to_gray(const stp_vars_t *vars,				      \
1467 		       const unsigned char *in,				      \
1468 		       unsigned short *out)				      \
1469 {									      \
1470   int i;								      \
1471   int i0 = -1;								      \
1472   int i1 = -1;								      \
1473   int i2 = -1;								      \
1474   int o0 = 0;								      \
1475   int nz = 0;								      \
1476   const T *s_in = (const T *) in;					      \
1477   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	      \
1478   int l_red = LUM_RED;							      \
1479   int l_green = LUM_GREEN;						      \
1480   int l_blue = LUM_BLUE;						      \
1481   const unsigned short *composite;					      \
1482   const unsigned short *user;						      \
1483 									      \
1484   stp_curve_resample							      \
1485     (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536);    \
1486   composite =								      \
1487     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K]));	      \
1488   stp_curve_resample(lut->user_color_correction.curve, 1 << bits);	      \
1489   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));      \
1490 									      \
1491   if (lut->input_color_description->color_model == COLOR_BLACK)		      \
1492     {									      \
1493       l_red = (100 - l_red) / 2;					      \
1494       l_green = (100 - l_green) / 2;					      \
1495       l_blue = (100 - l_blue) / 2;					      \
1496     }									      \
1497 									      \
1498   for (i = 0; i < lut->image_width; i++)				      \
1499     {									      \
1500       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2])		      \
1501 	{								      \
1502 	  i0 = s_in[0];							      \
1503 	  i1 = s_in[1];							      \
1504 	  i2 = s_in[2];							      \
1505 	  o0 =								      \
1506 	    composite[user[(i0 * l_red + i1 * l_green + i2 * l_blue) / 100]]; \
1507 	  nz |= o0;							      \
1508 	}								      \
1509       out[0] = o0;							      \
1510       s_in += 3;							      \
1511       out ++;								      \
1512     }									      \
1513   return nz == 0;							      \
1514 }
1515 
1516 COLOR_TO_GRAY_FUNC(unsigned char, 8) // color_8_to_gray
1517 COLOR_TO_GRAY_FUNC(unsigned short, 16) // color_16_to_gray
1518 GENERIC_COLOR_FUNC(color, gray)
1519 
1520 
1521 #define CMYK_TO_GRAY_FUNC(T, bits)					    \
1522 CFUNC									    \
1523 cmyk_##bits##_to_gray(const stp_vars_t *vars,				    \
1524 		      const unsigned char *in,				    \
1525 		      unsigned short *out)				    \
1526 {									    \
1527   int i;								    \
1528   int i0 = -1;								    \
1529   int i1 = -1;								    \
1530   int i2 = -1;								    \
1531   int i3 = -4;								    \
1532   int o0 = 0;								    \
1533   int nz = 0;								    \
1534   const T *s_in = (const T *) in;					    \
1535   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1536   int l_red = LUM_RED;							    \
1537   int l_green = LUM_GREEN;						    \
1538   int l_blue = LUM_BLUE;						    \
1539   int l_white = 0;							    \
1540   const unsigned short *composite;					    \
1541   const unsigned short *user;						    \
1542 									    \
1543   stp_curve_resample							    \
1544     (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536);  \
1545   composite =								    \
1546     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K]));	    \
1547   stp_curve_resample(lut->user_color_correction.curve, 1 << bits);	    \
1548   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));    \
1549 									    \
1550   if (lut->input_color_description->color_model == COLOR_BLACK)		    \
1551     {									    \
1552       l_red = (100 - l_red) / 3;					    \
1553       l_green = (100 - l_green) / 3;					    \
1554       l_blue = (100 - l_blue) / 3;					    \
1555       l_white = (100 - l_white) / 3;					    \
1556     }									    \
1557 									    \
1558   for (i = 0; i < lut->image_width; i++)				    \
1559     {									    \
1560       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \
1561 	{								    \
1562 	  i0 = s_in[0];							    \
1563 	  i1 = s_in[1];							    \
1564 	  i2 = s_in[2];							    \
1565 	  i3 = s_in[3];							    \
1566 	  o0 = composite[user[(i0 * l_red + i1 * l_green +		    \
1567 			  i2 * l_blue + i3 * l_white) / 100]];		    \
1568 	  nz |= o0;							    \
1569 	}								    \
1570       out[0] = o0;							    \
1571       s_in += 4;							    \
1572       out ++;								    \
1573     }									    \
1574   return nz ? 0 : 1;							    \
1575 }
1576 
1577 CMYK_TO_GRAY_FUNC(unsigned char, 8) // cmyk_8_to_gray
1578 CMYK_TO_GRAY_FUNC(unsigned short, 16) // cmyk_16_to_gray
1579 GENERIC_COLOR_FUNC(cmyk, gray)
1580 
1581 #define KCMY_TO_GRAY_FUNC(T, bits)					    \
1582 CFUNC									    \
1583 kcmy_##bits##_to_gray(const stp_vars_t *vars,				    \
1584 		      const unsigned char *in,				    \
1585 		      unsigned short *out)				    \
1586 {									    \
1587   int i;								    \
1588   int i0 = -1;								    \
1589   int i1 = -1;								    \
1590   int i2 = -1;								    \
1591   int i3 = -4;								    \
1592   int o0 = 0;								    \
1593   int nz = 0;								    \
1594   const T *s_in = (const T *) in;					    \
1595   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1596   int l_red = LUM_RED;							    \
1597   int l_green = LUM_GREEN;						    \
1598   int l_blue = LUM_BLUE;						    \
1599   int l_white = 0;							    \
1600   const unsigned short *composite;					    \
1601   const unsigned short *user;						    \
1602 									    \
1603   stp_curve_resample							    \
1604     (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536);  \
1605   composite =								    \
1606     stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K]));	    \
1607   stp_curve_resample(lut->user_color_correction.curve, 1 << bits);	    \
1608   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));    \
1609 									    \
1610   if (lut->input_color_description->color_model == COLOR_BLACK)		    \
1611     {									    \
1612       l_red = (100 - l_red) / 3;					    \
1613       l_green = (100 - l_green) / 3;					    \
1614       l_blue = (100 - l_blue) / 3;					    \
1615       l_white = (100 - l_white) / 3;					    \
1616     }									    \
1617 									    \
1618   for (i = 0; i < lut->image_width; i++)				    \
1619     {									    \
1620       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \
1621 	{								    \
1622 	  i0 = s_in[0];							    \
1623 	  i1 = s_in[1];							    \
1624 	  i2 = s_in[2];							    \
1625 	  i3 = s_in[3];							    \
1626 	  o0 = composite[user[(i0 * l_red + i1 * l_green +		    \
1627 			  i2 * l_blue + i3 * l_white) / 100]];		    \
1628 	  nz |= o0;							    \
1629 	}								    \
1630       out[0] = o0;							    \
1631       s_in += 4;							    \
1632       out ++;								    \
1633     }									    \
1634   return nz ? 0 : 1;							    \
1635 }
1636 
1637 KCMY_TO_GRAY_FUNC(unsigned char, 8) // kcmy_8_to_gray
1638 KCMY_TO_GRAY_FUNC(unsigned short, 16) // kcmy_16_to_gray
1639 GENERIC_COLOR_FUNC(kcmy, gray)
1640 
1641 #define GRAY_TO_GRAY_RAW_FUNC(T, bits)					\
1642 CFUNC									\
1643 gray_##bits##_to_gray_raw(const stp_vars_t *vars,			\
1644 			  const unsigned char *in,			\
1645 			  unsigned short *out)				\
1646 {									\
1647   int i;								\
1648   int nz = 0;								\
1649   const T *s_in = (const T *) in;					\
1650   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1651   int width = lut->image_width;						\
1652   unsigned mask = 0;							\
1653   if (lut->invert_output)						\
1654     mask = 0xffff;							\
1655 									\
1656   memset(out, 0, width * sizeof(unsigned short));			\
1657 									\
1658   for (i = 0; i < lut->image_width; i++)				\
1659     {									\
1660       out[0] = (s_in[0] * (65535 / ((1 << bits) - 1))) ^ mask;		\
1661       nz |= out[0];							\
1662       s_in ++;								\
1663       out ++;								\
1664     }									\
1665   return nz == 0;							\
1666 }
1667 
1668 GRAY_TO_GRAY_RAW_FUNC(unsigned char, 8) // gray_8_to_gray_raw
1669 GRAY_TO_GRAY_RAW_FUNC(unsigned short, 16) // gray_16_to_gray_raw
1670 GENERIC_COLOR_FUNC(gray, gray_raw)
1671 
1672 #define COLOR_TO_GRAY_RAW_FUNC(T, bits, invertable, name2)		\
1673 CFUNC									\
1674 color_##bits##_to_gray_##name2(const stp_vars_t *vars,			\
1675 			       const unsigned char *in,			\
1676 			       unsigned short *out)			\
1677 {									\
1678   int i;								\
1679   int i0 = -1;								\
1680   int i1 = -1;								\
1681   int i2 = -1;								\
1682   int o0 = 0;								\
1683   int nz = 0;								\
1684   const T *s_in = (const T *) in;					\
1685   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1686   int l_red = LUM_RED;							\
1687   int l_green = LUM_GREEN;						\
1688   int l_blue = LUM_BLUE;						\
1689   unsigned mask = 0;							\
1690   if (lut->invert_output && invertable)					\
1691     mask = 0xffff;							\
1692 									\
1693   if (lut->input_color_description->color_model == COLOR_BLACK)		\
1694     {									\
1695       l_red = (100 - l_red) / 2;					\
1696       l_green = (100 - l_green) / 2;					\
1697       l_blue = (100 - l_blue) / 2;					\
1698     }									\
1699 									\
1700   for (i = 0; i < lut->image_width; i++)				\
1701     {									\
1702       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2])		\
1703 	{								\
1704 	  i0 = s_in[0];							\
1705 	  i1 = s_in[1];							\
1706 	  i2 = s_in[2];							\
1707 	  o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_red +		\
1708 		i1 * (65535 / ((1 << bits) - 1)) * l_green +		\
1709 		i2 * (65535 / ((1 << bits) - 1)) * l_blue) / 100;	\
1710 	  o0 ^= mask;							\
1711 	  nz |= o0;							\
1712 	}								\
1713       out[0] = o0;							\
1714       s_in += 3;							\
1715       out ++;								\
1716     }									\
1717   return nz == 0;							\
1718 }
1719 
1720 COLOR_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // color_8_to_gray_raw
1721 COLOR_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // color_16_to_gray_raw
1722 GENERIC_COLOR_FUNC(color, gray_raw)
1723 COLOR_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // color_8_to_gray_noninvert
1724 COLOR_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // color_16_to_gray_noninvert
1725 // GENERIC_COLOR_FUNC(color, gray_noninvert)
1726 
1727 
1728 #define CMYK_TO_GRAY_RAW_FUNC(T, bits, invertable, name2)		    \
1729 CFUNC									    \
1730 cmyk_##bits##_to_gray_##name2(const stp_vars_t *vars,			    \
1731 			      const unsigned char *in,			    \
1732 			      unsigned short *out)			    \
1733 {									    \
1734   int i;								    \
1735   int i0 = -1;								    \
1736   int i1 = -1;								    \
1737   int i2 = -1;								    \
1738   int i3 = -4;								    \
1739   int o0 = 0;								    \
1740   int nz = 0;								    \
1741   const T *s_in = (const T *) in;					    \
1742   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1743   int l_red = LUM_RED;							    \
1744   int l_green = LUM_GREEN;						    \
1745   int l_blue = LUM_BLUE;						    \
1746   int l_white = 0;							    \
1747   unsigned mask = 0;							    \
1748   if (lut->invert_output && invertable)					    \
1749     mask = 0xffff;							    \
1750 									    \
1751   if (lut->input_color_description->color_model == COLOR_BLACK)		    \
1752     {									    \
1753       l_red = (100 - l_red) / 3;					    \
1754       l_green = (100 - l_green) / 3;					    \
1755       l_blue = (100 - l_blue) / 3;					    \
1756       l_white = (100 - l_white) / 3;					    \
1757     }									    \
1758 									    \
1759   for (i = 0; i < lut->image_width; i++)				    \
1760     {									    \
1761       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \
1762 	{								    \
1763 	  i0 = s_in[0];							    \
1764 	  i1 = s_in[1];							    \
1765 	  i2 = s_in[2];							    \
1766 	  i3 = s_in[3];							    \
1767 	  o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_red +		    \
1768 		i1 * (65535 / ((1 << bits) - 1)) * l_green +		    \
1769 		i2 * (65535 / ((1 << bits) - 1)) * l_blue +		    \
1770 		i3 * (65535 / ((1 << bits) - 1)) * l_white) / 100;	    \
1771 	  o0 ^= mask;							    \
1772 	  nz |= o0;							    \
1773 	}								    \
1774       out[0] = o0;							    \
1775       s_in += 4;							    \
1776       out ++;								    \
1777     }									    \
1778   return nz ? 0 : 1;							    \
1779 }
1780 
1781 CMYK_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // cmyk_8_to_gray_raw
1782 CMYK_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // cmyk_16_to_gray_raw
1783 GENERIC_COLOR_FUNC(cmyk, gray_raw)
1784 CMYK_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // cmyk_8_to_gray_noninvert
1785 CMYK_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // cmyk_16_to_gray_noninvert
1786 // GENERIC_COLOR_FUNC(cmyk, gray_noninvert)
1787 
1788 #define KCMY_TO_GRAY_RAW_FUNC(T, bits, invertable, name2)		    \
1789 CFUNC									    \
1790 kcmy_##bits##_to_gray_##name2(const stp_vars_t *vars,			    \
1791 			      const unsigned char *in,			    \
1792 			      unsigned short *out)			    \
1793 {									    \
1794   int i;								    \
1795   int i0 = -1;								    \
1796   int i1 = -1;								    \
1797   int i2 = -1;								    \
1798   int i3 = -4;								    \
1799   int o0 = 0;								    \
1800   int nz = 0;								    \
1801   const T *s_in = (const T *) in;					    \
1802   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
1803   int l_red = LUM_RED;							    \
1804   int l_green = LUM_GREEN;						    \
1805   int l_blue = LUM_BLUE;						    \
1806   int l_white = 0;							    \
1807   unsigned mask = 0;							    \
1808   if (lut->invert_output && invertable)					    \
1809     mask = 0xffff;							    \
1810 									    \
1811   if (lut->input_color_description->color_model == COLOR_BLACK)		    \
1812     {									    \
1813       l_red = (100 - l_red) / 3;					    \
1814       l_green = (100 - l_green) / 3;					    \
1815       l_blue = (100 - l_blue) / 3;					    \
1816       l_white = (100 - l_white) / 3;					    \
1817     }									    \
1818 									    \
1819   for (i = 0; i < lut->image_width; i++)				    \
1820     {									    \
1821       if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \
1822 	{								    \
1823 	  i0 = s_in[0];							    \
1824 	  i1 = s_in[1];							    \
1825 	  i2 = s_in[2];							    \
1826 	  i3 = s_in[3];							    \
1827 	  o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_white +		    \
1828 		i1 * (65535 / ((1 << bits) - 1)) * l_red +		    \
1829 		i2 * (65535 / ((1 << bits) - 1)) * l_green +		    \
1830 		i3 * (65535 / ((1 << bits) - 1)) * l_blue) / 100;	    \
1831 	  o0 ^= mask;							    \
1832 	  nz |= o0;							    \
1833 	}								    \
1834       out[0] = o0;							    \
1835       s_in += 4;							    \
1836       out ++;								    \
1837     }									    \
1838   return nz ? 0 : 1;							    \
1839 }
1840 
1841 KCMY_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // kcmy_8_to_gray_raw
1842 KCMY_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // kcmy_16_to_gray_raw
1843 GENERIC_COLOR_FUNC(kcmy, gray_raw)
1844 KCMY_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // kcmy_8_to_gray_noninvert
1845 KCMY_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // kcmy_16_to_gray_noninvert
1846 // GENERIC_COLOR_FUNC(kcmy, gray_noninvert)
1847 
1848 #define CMYK_TO_KCMY_RAW_FUNC(T, bits)					\
1849 CFUNC									\
1850 cmyk_##bits##_to_kcmy_raw(const stp_vars_t *vars,			\
1851 			  const unsigned char *in,			\
1852 			  unsigned short *out)				\
1853 {									\
1854   int i;								\
1855   int j;								\
1856   int nz[4];								\
1857   unsigned retval = 0;							\
1858   const T *s_in = (const T *) in;					\
1859   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1860 									\
1861   memset(nz, 0, sizeof(nz));						\
1862   for (i = 0; i < lut->image_width; i++)				\
1863     {									\
1864       out[0] = s_in[3] * (65535 / ((1 << bits) - 1));			\
1865       out[1] = s_in[0] * (65535 / ((1 << bits) - 1));			\
1866       out[2] = s_in[1] * (65535 / ((1 << bits) - 1));			\
1867       out[3] = s_in[2] * (65535 / ((1 << bits) - 1));			\
1868       for (j = 0; j < 4; j++)						\
1869 	nz[j] |= out[j];						\
1870       s_in += 4;							\
1871       out += 4;								\
1872     }									\
1873   for (j = 0; j < 4; j++)						\
1874     if (nz[j] == 0)							\
1875       retval |= (1 << j);						\
1876   return retval;							\
1877 }
1878 
1879 CMYK_TO_KCMY_RAW_FUNC(unsigned char, 8) // cmyk_8_to_kcmy_raw
1880 CMYK_TO_KCMY_RAW_FUNC(unsigned short, 16) // cmyk_16_to_kcmy_raw
1881 GENERIC_COLOR_FUNC(cmyk, kcmy_raw)
1882 
1883 #define KCMY_TO_KCMY_RAW_FUNC(T, bits)					\
1884 CFUNC									\
1885 kcmy_##bits##_to_kcmy_raw(const stp_vars_t *vars,			\
1886 			  const unsigned char *in,			\
1887 			  unsigned short *out)				\
1888 {									\
1889   int i;								\
1890   int j;								\
1891   int nz[4];								\
1892   unsigned retval = 0;							\
1893   const T *s_in = (const T *) in;					\
1894   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1895 									\
1896   memset(nz, 0, sizeof(nz));						\
1897   for (i = 0; i < lut->image_width; i++)				\
1898     {									\
1899       for (j = 0; j < 4; j++)						\
1900 	{								\
1901 	  out[j] = s_in[j] * (65535 / ((1 << bits) - 1));		\
1902 	  nz[j] |= out[j];						\
1903 	}								\
1904       s_in += 4;							\
1905       out += 4;								\
1906     }									\
1907   for (j = 0; j < 4; j++)						\
1908     if (nz[j] == 0)							\
1909       retval |= (1 << j);						\
1910   return retval;							\
1911 }
1912 
1913 KCMY_TO_KCMY_RAW_FUNC(unsigned char, 8) // kcmy_8_to_kcmy_raw
1914 KCMY_TO_KCMY_RAW_FUNC(unsigned short, 16) // kcmy_16_to_kcmy_raw
1915 GENERIC_COLOR_FUNC(kcmy, kcmy_raw)
1916 
1917 #define DESATURATED_FUNC(name, name2, bits)				   \
1918 CFUNC									   \
1919 name##_##bits##_to_##name2##_desaturated(const stp_vars_t *vars,	   \
1920 				         const unsigned char *in,	   \
1921 				         unsigned short *out)		   \
1922 {									   \
1923   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	   \
1924   size_t real_steps = lut->steps;					   \
1925   unsigned status;							   \
1926   if (!lut->gray_tmp)							   \
1927     lut->gray_tmp = stp_malloc(2 * lut->image_width);			   \
1928   name##_##bits##_to_gray_noninvert(vars, in, lut->gray_tmp);		   \
1929   lut->steps = 65536;							   \
1930   status = gray_16_to_##name2(vars, (unsigned char *) lut->gray_tmp, out); \
1931   lut->steps = real_steps;						   \
1932   return status;							   \
1933 }
1934 
1935 DESATURATED_FUNC(color, color, 8) // color_8_to_color_desaturated
1936 DESATURATED_FUNC(color, color, 16) // color_16_to_color_desaturated
1937 GENERIC_COLOR_FUNC(color, color_desaturated)
1938 DESATURATED_FUNC(color, kcmy, 8) // color_8_to_kcmy_desaturated
1939 DESATURATED_FUNC(color, kcmy, 16) // color_8_to_kcmy_desaturated
1940 GENERIC_COLOR_FUNC(color, kcmy_desaturated)
1941 
1942 DESATURATED_FUNC(cmyk, color, 8) // cmyk_8_to_color_desaturated
1943 DESATURATED_FUNC(cmyk, color, 16) // cmyk_16_to_color_desaturated
1944 GENERIC_COLOR_FUNC(cmyk, color_desaturated)
1945 DESATURATED_FUNC(cmyk, kcmy, 8) // cmyk_8_to_kcmy_desaturated
1946 DESATURATED_FUNC(cmyk, kcmy, 16) // cmyk_16_to_kcmy_desaturated
1947 GENERIC_COLOR_FUNC(cmyk, kcmy_desaturated)
1948 
1949 DESATURATED_FUNC(kcmy, color, 8) // kcmy_8_to_color_desaturated
1950 DESATURATED_FUNC(kcmy, color, 16) // kcmy_16_to_kcmy_desaturated
1951 GENERIC_COLOR_FUNC(kcmy, color_desaturated)
1952 DESATURATED_FUNC(kcmy, kcmy, 8) // kcmy_8_to_color_desaturated
1953 DESATURATED_FUNC(kcmy, kcmy, 16) // kcmy_16_to_kcmy_desaturated
1954 GENERIC_COLOR_FUNC(kcmy, kcmy_desaturated)
1955 
1956 #define CMYK_DISPATCH(name)						\
1957 CFUNC									\
1958 CMYK_to_##name(const stp_vars_t *vars, const unsigned char *in,		\
1959 	       unsigned short *out)					\
1960 {									\
1961   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1962   if (lut->input_color_description->color_id == COLOR_ID_CMYK)		\
1963     return cmyk_to_##name(vars, in, out);				\
1964   else if (lut->input_color_description->color_id == COLOR_ID_KCMY)	\
1965     return kcmy_to_##name(vars, in, out);				\
1966   else									\
1967     {									\
1968       stp_eprintf(vars, "Bad dispatch to CMYK_to_%s: %d\n", #name,	\
1969 		  lut->input_color_description->color_id);		\
1970       return 0;								\
1971     }									\
1972 }
1973 
1974 CMYK_DISPATCH(color)		/* CMYK_to_color */
1975 CMYK_DISPATCH(color_raw)	/* CMYK_to_color_raw */
1976 CMYK_DISPATCH(color_fast)	/* CMYK_to_color_fast */
1977 CMYK_DISPATCH(color_threshold)	/* CMYK_to_color_threshold */
1978 CMYK_DISPATCH(color_desaturated) /* CMYK_to_color_desaturated */
1979 CMYK_DISPATCH(kcmy)		 /* CMYK_to_kcmy */
1980 CMYK_DISPATCH(kcmy_raw)		 /* CMYK_to_kcmy_raw */
1981 CMYK_DISPATCH(kcmy_threshold)	 /* CMYK_to_kcmy_threshold */
1982 CMYK_DISPATCH(kcmy_desaturated)	 /* CMYK_to_kcmy_desaturated */
1983 CMYK_DISPATCH(gray)		 /* CMYK_to_gray */
1984 CMYK_DISPATCH(gray_raw)		 /* CMYK_to_gray_raw */
1985 CMYK_DISPATCH(gray_threshold)	 /* CMYK_to_gray_threshold */
1986 
1987 #define RAW_TO_RAW_THRESHOLD_FUNC(T, name)				\
1988 CFUNC									\
1989 name##_to_raw_threshold(const stp_vars_t *vars,				\
1990 			const unsigned char *in,			\
1991 			unsigned short *out)				\
1992 {									\
1993   int i;								\
1994   int j;								\
1995   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
1996   unsigned nz[STP_CHANNEL_LIMIT];					\
1997   unsigned z = (1 << lut->out_channels) - 1;				\
1998   const T *s_in = (const T *) in;					\
1999   unsigned desired_high_bit = 0;					\
2000   unsigned high_bit = 1 << ((sizeof(T) * 8) - 1);			\
2001   int width = lut->image_width;						\
2002   memset(out, 0, width * lut->out_channels * sizeof(unsigned short));	\
2003   if (!lut->invert_output)						\
2004     desired_high_bit = high_bit;					\
2005   for (i = 0; i < lut->out_channels; i++)				\
2006     nz[i] = z & ~(1 << i);						\
2007 									\
2008   for (i = 0; i < width; i++)						\
2009     {									\
2010       for (j = 0; j < lut->out_channels; j++)				\
2011 	{								\
2012 	  if ((*s_in++ & high_bit) == desired_high_bit)			\
2013 	    {								\
2014 	      z &= nz[j];						\
2015 	      *out = 65535;						\
2016 	    }								\
2017 	  out++;							\
2018 	}								\
2019     }									\
2020   return z;								\
2021 }
2022 
2023 RAW_TO_RAW_THRESHOLD_FUNC(unsigned char, raw_8) // raw_8_to_raw_threshold
2024 RAW_TO_RAW_THRESHOLD_FUNC(unsigned short, raw_16) // raw_16_to_raw_threshold
2025 GENERIC_COLOR_FUNC(raw, raw_threshold)
2026 
2027 #define RAW_TO_RAW_FUNC(T, size)					    \
2028 CFUNC									    \
2029 raw_##size##_to_raw(const stp_vars_t *vars,				    \
2030 		    const unsigned char *in,				    \
2031 		    unsigned short *out)				    \
2032 {									    \
2033   int i;								    \
2034   unsigned retval = 0;							    \
2035   int j;								    \
2036   int nz[STP_CHANNEL_LIMIT];						    \
2037   const T *s_in = (const T *) in;					    \
2038   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	    \
2039   const unsigned short *maps[STP_CHANNEL_LIMIT];			    \
2040   const unsigned short *user;						    \
2041 									    \
2042   for (i = 0; i < lut->out_channels; i++)				    \
2043     {									    \
2044       stp_curve_resample(lut->channel_curves[i].curve, 65536);		    \
2045       maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \
2046     }									    \
2047   stp_curve_resample(lut->user_color_correction.curve, 1 << size);	    \
2048   user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction));    \
2049 									    \
2050   memset(nz, 0, sizeof(nz));						    \
2051 									    \
2052   for (i = 0; i < lut->image_width; i++, out += lut->out_channels)	    \
2053     {									    \
2054       for (j = 0; j < lut->out_channels; j++)				    \
2055 	{								    \
2056 	  int inval = *s_in++;						    \
2057 	  nz[j] |= inval;						    \
2058 	  out[j] = maps[j][user[inval]];				    \
2059 	}								    \
2060     }									    \
2061   for (j = 0; j < lut->out_channels; j++)				    \
2062     if (nz[j] == 0)							    \
2063       retval |= (1 << j);						    \
2064   return retval;							    \
2065 }
2066 
2067 RAW_TO_RAW_FUNC(unsigned char, 8) // raw_8_to_raw
2068 RAW_TO_RAW_FUNC(unsigned short, 16) // raw_8_to_raw
2069 GENERIC_COLOR_FUNC(raw, raw)
2070 
2071 
2072 #define RAW_TO_RAW_RAW_FUNC(T, bits)					\
2073 CFUNC									\
2074 raw_##bits##_to_raw_raw(const stp_vars_t *vars,				\
2075 		        const unsigned char *in,			\
2076 		        unsigned short *out)				\
2077 {									\
2078   int i;								\
2079   int j;								\
2080   int nz[STP_CHANNEL_LIMIT];						\
2081   unsigned retval = 0;							\
2082   const T *s_in = (const T *) in;					\
2083   lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color"));	\
2084   int colors = lut->in_channels;					\
2085 									\
2086   memset(nz, 0, sizeof(nz));						\
2087   for (i = 0; i < lut->image_width; i++)				\
2088     {									\
2089       for (j = 0; j < colors; j++)					\
2090 	{								\
2091 	  nz[j] |= s_in[j];						\
2092 	  out[j] = s_in[j] * (65535 / ((1 << bits) - 1));		\
2093 	}								\
2094       s_in += colors;							\
2095       out += colors;							\
2096     }									\
2097   for (j = 0; j < colors; j++)						\
2098     if (nz[j] == 0)							\
2099       retval |= (1 << j);						\
2100   return retval;							\
2101 }
2102 
2103 RAW_TO_RAW_RAW_FUNC(unsigned char, 8) // raw_8_to_raw_raw
2104 RAW_TO_RAW_RAW_FUNC(unsigned short, 16) // raw_16_to_raw_raw
2105 GENERIC_COLOR_FUNC(raw, raw_raw)
2106 
2107 
2108 #define CONVERSION_FUNCTION_WITH_FAST(from, to, from2)			\
2109 CFUNC									\
2110 generic_##from##_to_##to(const stp_vars_t *v,				\
2111 			 const unsigned char *in,			\
2112 			 unsigned short *out)				\
2113 {									\
2114   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));		\
2115   switch (lut->color_correction->correction)				\
2116     {									\
2117     case COLOR_CORRECTION_UNCORRECTED:					\
2118       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2119 		  "Colorfunc: %s_to_%s_fast\n", #from2, #to);		\
2120       return from2##_to_##to##_fast(v, in, out);			\
2121     case COLOR_CORRECTION_ACCURATE:					\
2122     case COLOR_CORRECTION_BRIGHT:					\
2123     case COLOR_CORRECTION_HUE:						\
2124       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2125 		  "Colorfunc: %s_to_%s\n", #from2, #to);		\
2126       return from2##_to_##to(v, in, out);				\
2127     case COLOR_CORRECTION_DESATURATED:					\
2128       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2129 		  "Colorfunc: %s_to_%s_desaturated\n", #from2, #to);	\
2130       return from2##_to_##to##_desaturated(v, in, out);			\
2131     case COLOR_CORRECTION_THRESHOLD:					\
2132     case COLOR_CORRECTION_PREDITHERED:					\
2133       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2134 		  "Colorfunc: %s_to_%s_threshold\n", #from2, #to);	\
2135       return from2##_to_##to##_threshold(v, in, out);			\
2136     case COLOR_CORRECTION_DENSITY:					\
2137     case COLOR_CORRECTION_RAW:						\
2138       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2139 		  "Colorfunc: %s_to_%s_raw\n", #from2, #to);		\
2140       return from2##_to_##to##_raw(v, in, out);				\
2141     default:								\
2142       return (unsigned) -1;						\
2143     }									\
2144 }
2145 
2146 #define CONVERSION_FUNCTION_WITHOUT_FAST(from, to, from2)		\
2147 CFUNC									\
2148 generic_##from##_to_##to(const stp_vars_t *v,				\
2149 			 const unsigned char *in,			\
2150 			 unsigned short *out)				\
2151 {									\
2152   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));		\
2153   switch (lut->color_correction->correction)				\
2154     {									\
2155     case COLOR_CORRECTION_UNCORRECTED:					\
2156     case COLOR_CORRECTION_ACCURATE:					\
2157     case COLOR_CORRECTION_BRIGHT:					\
2158     case COLOR_CORRECTION_HUE:						\
2159       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2160 		  "Colorfunc: %s_to_%s\n", #from2, #to);		\
2161       return from2##_to_##to(v, in, out);				\
2162     case COLOR_CORRECTION_DESATURATED:					\
2163       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2164 		  "Colorfunc: %s_to_%s_desaturated\n", #from2, #to);	\
2165       return from2##_to_##to##_desaturated(v, in, out);			\
2166     case COLOR_CORRECTION_THRESHOLD:					\
2167     case COLOR_CORRECTION_PREDITHERED:					\
2168       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2169 		  "Colorfunc: %s_to_%s_threshold\n", #from2, #to);	\
2170       return from2##_to_##to##_threshold(v, in, out);			\
2171     case COLOR_CORRECTION_DENSITY:					\
2172     case COLOR_CORRECTION_RAW:						\
2173       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2174 		  "Colorfunc: %s_to_%s_raw\n", #from2, #to);		\
2175       return from2##_to_##to##_raw(v, in, out);				\
2176     default:								\
2177       return (unsigned) -1;						\
2178     }									\
2179 }
2180 
2181 #define CONVERSION_FUNCTION_WITHOUT_DESATURATED(from, to, from2)	\
2182 CFUNC									\
2183 generic_##from##_to_##to(const stp_vars_t *v,				\
2184 			 const unsigned char *in,			\
2185 			 unsigned short *out)				\
2186 {									\
2187   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));		\
2188   switch (lut->color_correction->correction)				\
2189     {									\
2190     case COLOR_CORRECTION_UNCORRECTED:					\
2191     case COLOR_CORRECTION_ACCURATE:					\
2192     case COLOR_CORRECTION_BRIGHT:					\
2193     case COLOR_CORRECTION_HUE:						\
2194     case COLOR_CORRECTION_DESATURATED:					\
2195       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2196 		  "Colorfunc: %s_to_%s\n", #from2, #to);		\
2197       return from2##_to_##to(v, in, out);				\
2198     case COLOR_CORRECTION_THRESHOLD:					\
2199     case COLOR_CORRECTION_PREDITHERED:					\
2200       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2201 		  "Colorfunc: %s_to_%s_threshold\n", #from2, #to);	\
2202       return from2##_to_##to##_threshold(v, in, out);			\
2203     case COLOR_CORRECTION_DENSITY:					\
2204     case COLOR_CORRECTION_RAW:						\
2205       stp_dprintf(STP_DBG_COLORFUNC, v,					\
2206 		  "Colorfunc: %s_to_%s_raw\n", #from2, #to);		\
2207       return from2##_to_##to##_raw(v, in, out);				\
2208     default:								\
2209       return (unsigned) -1;						\
2210     }									\
2211 }
2212 
2213 CONVERSION_FUNCTION_WITH_FAST(cmyk, color, CMYK) // generic_cmyk_to_color
2214 CONVERSION_FUNCTION_WITH_FAST(color, color, color) // generic_color_to_color
2215 CONVERSION_FUNCTION_WITH_FAST(color, kcmy, color) // generic_color_to_kcmy
2216 CONVERSION_FUNCTION_WITHOUT_FAST(cmyk, kcmy, CMYK) // generic_cmyk_to_kcmy
2217 CONVERSION_FUNCTION_WITHOUT_DESATURATED(cmyk, gray, CMYK) // generic_cmyk_to_gray
2218 CONVERSION_FUNCTION_WITHOUT_DESATURATED(color, gray, color) // generic_color_to_gray
2219 CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, gray, gray) // generic_gray_to_gray
2220 CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, color, gray) // generic_gray_to_color
2221 CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, kcmy, gray) // generic_gray_to_kcmy
2222 
2223 unsigned
2224 stpi_color_convert_to_gray(const stp_vars_t *v,
2225 			   const unsigned char *in,
2226 			   unsigned short *out)
2227 {
2228   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));
2229   switch (lut->input_color_description->color_id)
2230     {
2231     case COLOR_ID_GRAY:
2232     case COLOR_ID_WHITE:
2233       return generic_gray_to_gray(v, in, out);
2234     case COLOR_ID_RGB:
2235     case COLOR_ID_CMY:
2236       return generic_color_to_gray(v, in, out);
2237     case COLOR_ID_CMYK:
2238     case COLOR_ID_KCMY:
2239       return generic_cmyk_to_gray(v, in, out);
2240     default:
2241       return (unsigned) -1;
2242     }
2243 }
2244 
2245 unsigned
stpi_color_convert_to_color(const stp_vars_t * v,const unsigned char * in,unsigned short * out)2246 stpi_color_convert_to_color(const stp_vars_t *v,
2247 			    const unsigned char *in,
2248 			    unsigned short *out)
2249 {
2250   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));
2251   switch (lut->input_color_description->color_id)
2252     {
2253     case COLOR_ID_GRAY:
2254     case COLOR_ID_WHITE:
2255       return generic_gray_to_color(v, in, out);
2256     case COLOR_ID_RGB:
2257     case COLOR_ID_CMY:
2258       return generic_color_to_color(v, in, out);
2259     case COLOR_ID_CMYK:
2260     case COLOR_ID_KCMY:
2261       return generic_cmyk_to_color(v, in, out);
2262     default:
2263       return (unsigned) -1;
2264     }
2265 }
2266 
2267 unsigned
stpi_color_convert_to_kcmy(const stp_vars_t * v,const unsigned char * in,unsigned short * out)2268 stpi_color_convert_to_kcmy(const stp_vars_t *v,
2269 			   const unsigned char *in,
2270 			   unsigned short *out)
2271 {
2272   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));
2273   switch (lut->input_color_description->color_id)
2274     {
2275     case COLOR_ID_GRAY:
2276     case COLOR_ID_WHITE:
2277       return generic_gray_to_kcmy(v, in, out);
2278     case COLOR_ID_RGB:
2279     case COLOR_ID_CMY:
2280       return generic_color_to_kcmy(v, in, out);
2281     case COLOR_ID_CMYK:
2282     case COLOR_ID_KCMY:
2283       return generic_cmyk_to_kcmy(v, in, out);
2284     default:
2285       return (unsigned) -1;
2286     }
2287 }
2288 
2289 unsigned
stpi_color_convert_raw(const stp_vars_t * v,const unsigned char * in,unsigned short * out)2290 stpi_color_convert_raw(const stp_vars_t *v,
2291 		       const unsigned char *in,
2292 		       unsigned short *out)
2293 {
2294   lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color"));
2295   switch (lut->color_correction->correction)
2296     {
2297     case COLOR_CORRECTION_THRESHOLD:
2298     case COLOR_CORRECTION_PREDITHERED:
2299       stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_threshold\n");
2300       return raw_to_raw_threshold(v, in, out);
2301     case COLOR_CORRECTION_UNCORRECTED:
2302     case COLOR_CORRECTION_BRIGHT:
2303     case COLOR_CORRECTION_HUE:
2304     case COLOR_CORRECTION_ACCURATE:
2305     case COLOR_CORRECTION_DESATURATED:
2306       stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_desaturated\n");
2307       return raw_to_raw(v, in, out);
2308     case COLOR_CORRECTION_RAW:
2309     case COLOR_CORRECTION_DEFAULT:
2310     case COLOR_CORRECTION_DENSITY:
2311       stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_raw\n");
2312       return raw_to_raw_raw(v, in, out);
2313     default:
2314       return (unsigned) -1;
2315     }
2316 }
2317