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