1/*
2 * "$Id: channel.c,v 1.34 2011/04/16 15:48:20 rlk Exp $"
3 *
4 *   Dither routine entrypoints
5 *
6 *   Copyright 2003 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, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * Revision History:
23 *
24 *   See ChangeLog
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#ifdef HAVE_LIMITS_H
34#include <limits.h>
35#endif
36#include <math.h>
37#include <string.h>
38
39#ifdef __GNUC__
40#define inline __inline__
41#endif
42
43#define FMAX(a, b) ((a) > (b) ? (a) : (b))
44#define FMIN(a, b) ((a) < (b) ? (a) : (b))
45
46typedef struct
47{
48  double value;
49  double lower;
50  double upper;
51  double cutoff;
52  unsigned short s_density;
53} stpi_subchannel_t;
54
55typedef struct
56{
57  unsigned subchannel_count;
58  stpi_subchannel_t *sc;
59  unsigned short *lut;
60  const double *hue_map;
61  size_t h_count;
62  stp_curve_t *curve;
63} stpi_channel_t;
64
65typedef struct
66{
67  unsigned channel_count;
68  unsigned total_channels;
69  unsigned input_channels;
70  unsigned gcr_channels;
71  unsigned aux_output_channels;
72  size_t width;
73  int initialized;
74  unsigned ink_limit;
75  unsigned max_density;
76  stpi_channel_t *c;
77  stp_curve_t *gcr_curve;
78  unsigned curve_count;
79  unsigned gloss_limit;
80  unsigned short *input_data;
81  unsigned short *multi_tmp;
82  unsigned short *gcr_data;
83  unsigned short *split_input;
84  unsigned short *output_data;
85  unsigned short *alloc_data_1;
86  unsigned short *alloc_data_2;
87  unsigned short *alloc_data_3;
88  int black_channel;
89  int gloss_channel;
90  int gloss_physical_channel;
91  double cyan_balance;
92  double magenta_balance;
93  double yellow_balance;
94} stpi_channel_group_t;
95
96
97static stpi_channel_group_t *
98get_channel_group(const stp_vars_t *v)
99{
100  stpi_channel_group_t *cg =
101    ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
102  return cg;
103}
104
105static void
106clear_a_channel(stpi_channel_group_t *cg, int channel)
107{
108  if (channel < cg->channel_count)
109    {
110      STP_SAFE_FREE(cg->c[channel].sc);
111      STP_SAFE_FREE(cg->c[channel].lut);
112      if (cg->c[channel].curve)
113	{
114	  stp_curve_destroy(cg->c[channel].curve);
115	  cg->c[channel].curve = NULL;
116	}
117      cg->c[channel].subchannel_count = 0;
118    }
119}
120
121static void
122stpi_channel_clear(void *vc)
123{
124  stpi_channel_group_t *cg = (stpi_channel_group_t *) vc;
125  int i;
126  if (cg->channel_count > 0)
127    for (i = 0; i < cg->channel_count; i++)
128      clear_a_channel(cg, i);
129
130  STP_SAFE_FREE(cg->alloc_data_1);
131  STP_SAFE_FREE(cg->alloc_data_2);
132  STP_SAFE_FREE(cg->alloc_data_3);
133  STP_SAFE_FREE(cg->c);
134  if (cg->gcr_curve)
135    {
136      stp_curve_destroy(cg->gcr_curve);
137      cg->gcr_curve = NULL;
138    }
139  cg->channel_count = 0;
140  cg->curve_count = 0;
141  cg->aux_output_channels = 0;
142  cg->total_channels = 0;
143  cg->input_channels = 0;
144  cg->initialized = 0;
145}
146
147void
148stp_channel_reset(stp_vars_t *v)
149{
150  stpi_channel_group_t *cg = get_channel_group(v);
151  if (cg)
152    stpi_channel_clear(cg);
153}
154
155void
156stp_channel_reset_channel(stp_vars_t *v, int channel)
157{
158  stpi_channel_group_t *cg = get_channel_group(v);
159  if (cg)
160    clear_a_channel(cg, channel);
161}
162
163static void
164stpi_channel_free(void *vc)
165{
166  stpi_channel_clear(vc);
167  stp_free(vc);
168}
169
170static stpi_subchannel_t *
171get_channel(stp_vars_t *v, unsigned channel, unsigned subchannel)
172{
173  stpi_channel_group_t *cg = get_channel_group(v);
174  if (!cg)
175    return NULL;
176  if (channel >= cg->channel_count)
177    return NULL;
178  if (subchannel >= cg->c[channel].subchannel_count)
179    return NULL;
180  return &(cg->c[channel].sc[subchannel]);
181}
182
183void
184stp_channel_add(stp_vars_t *v, unsigned channel, unsigned subchannel,
185		double value)
186{
187  stpi_channel_group_t *cg = get_channel_group(v);
188  stpi_channel_t *chan;
189  stp_dprintf(STP_DBG_INK, v, "Add channel %d, %d, %f\n",
190	      channel, subchannel, value);
191  if (!cg)
192    {
193      cg = stp_zalloc(sizeof(stpi_channel_group_t));
194      cg->black_channel = -1;
195      cg->gloss_channel = -1;
196      stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
197      stp_dprintf(STP_DBG_INK, v, "*** Set up channel data ***\n");
198    }
199  if (channel >= cg->channel_count)
200    {
201      unsigned oc = cg->channel_count;
202      cg->c = stp_realloc(cg->c, sizeof(stpi_channel_t) * (channel + 1));
203      memset(cg->c + oc, 0, sizeof(stpi_channel_t) * (channel + 1 - oc));
204      stp_dprintf(STP_DBG_INK, v, "*** Increment channel count from %d to %d\n",
205		  oc, channel + 1);
206      if (channel >= cg->channel_count)
207	cg->channel_count = channel + 1;
208    }
209  chan = cg->c + channel;
210  if (subchannel >= chan->subchannel_count)
211    {
212      unsigned oc = chan->subchannel_count;
213      chan->sc =
214	stp_realloc(chan->sc, sizeof(stpi_subchannel_t) * (subchannel + 1));
215      (void) memset
216	(chan->sc + oc, 0, sizeof(stpi_subchannel_t) * (subchannel + 1 - oc));
217      chan->sc[subchannel].value = value;
218      stp_dprintf(STP_DBG_INK, v,
219		  "*** Increment subchannel count for %d from %d to %d\n",
220		  channel, oc, subchannel + 1);
221      if (subchannel >= chan->subchannel_count)
222	chan->subchannel_count = subchannel + 1;
223    }
224  chan->sc[subchannel].value = value;
225  chan->sc[subchannel].s_density = 65535;
226  chan->sc[subchannel].cutoff = 0.75;
227}
228
229double
230stp_channel_get_value(stp_vars_t *v, unsigned color, unsigned subchannel)
231{
232  stpi_subchannel_t *sch = get_channel(v, color, subchannel);
233  if (sch)
234    return sch->value;
235  else
236    return -1;
237}
238
239void
240stp_channel_set_density_adjustment(stp_vars_t *v, int color, int subchannel,
241				   double adjustment)
242{
243  stpi_subchannel_t *sch = get_channel(v, color, subchannel);
244  if ((strcmp(stp_get_string_parameter(v, "STPIOutputType"), "Raw") == 0 &&
245       strcmp(stp_get_string_parameter(v, "ColorCorrection"), "None") == 0) ||
246      strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Raw") == 0 ||
247      strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Predithered") == 0)
248    {
249      stp_dprintf(STP_DBG_INK, v,
250		  "Ignoring channel_density channel %d subchannel %d adjustment %f\n",
251		  color, subchannel, adjustment);
252    }
253  else
254    {
255      stp_dprintf(STP_DBG_INK, v,
256		  "channel_density channel %d subchannel %d adjustment %f\n",
257		  color, subchannel, adjustment);
258      if (sch && adjustment >= 0 && adjustment <= 1)
259	sch->s_density = adjustment * 65535;
260    }
261}
262
263double
264stp_channel_get_density_adjustment(stp_vars_t *v, int color, int subchannel)
265{
266  stpi_subchannel_t *sch = get_channel(v, color, subchannel);
267  if (sch)
268    return sch->s_density / 65535.0;
269  else
270    return -1;
271}
272
273void
274stp_channel_set_ink_limit(stp_vars_t *v, double limit)
275{
276  stpi_channel_group_t *cg = get_channel_group(v);
277  stp_dprintf(STP_DBG_INK, v, "ink_limit %f\n", limit);
278  if (cg && limit > 0)
279    cg->ink_limit = 65535 * limit;
280}
281
282double
283stp_channel_get_ink_limit(stp_vars_t *v)
284{
285  stpi_channel_group_t *cg = get_channel_group(v);
286  if (!cg)
287    return 0.0;
288  return cg->ink_limit / 65535.0;
289}
290
291void
292stp_channel_set_black_channel(stp_vars_t *v, int channel)
293{
294  stpi_channel_group_t *cg = get_channel_group(v);
295  stp_dprintf(STP_DBG_INK, v, "black_channel %d\n", channel);
296  if (cg)
297    cg->black_channel = channel;
298}
299
300int
301stp_channel_get_black_channel(stp_vars_t *v)
302{
303  stpi_channel_group_t *cg = get_channel_group(v);
304  if (cg)
305    return cg->black_channel;
306  else
307    return -1;
308}
309
310void
311stp_channel_set_gloss_channel(stp_vars_t *v, int channel)
312{
313  stpi_channel_group_t *cg = get_channel_group(v);
314  stp_dprintf(STP_DBG_INK, v, "gloss_channel %d\n", channel);
315  if (cg)
316    cg->gloss_channel = channel;
317}
318
319int
320stp_channel_get_gloss_channel(stp_vars_t *v)
321{
322  stpi_channel_group_t *cg = get_channel_group(v);
323  if (cg)
324    return cg->gloss_channel;
325  else
326    return -1;
327}
328
329void
330stp_channel_set_gloss_limit(stp_vars_t *v, double limit)
331{
332  stpi_channel_group_t *cg = get_channel_group(v);
333  stp_dprintf(STP_DBG_INK, v, "gloss_limit %f\n", limit);
334  if (cg && limit > 0)
335    cg->gloss_limit = 65535 * limit;
336}
337
338double
339stp_channel_get_gloss_limit(stp_vars_t *v)
340{
341  stpi_channel_group_t *cg = get_channel_group(v);
342  if (cg)
343    return cg->gloss_limit / 65535.0;
344  else
345    return 0;
346}
347
348void
349stp_channel_set_cutoff_adjustment(stp_vars_t *v, int color, int subchannel,
350				  double adjustment)
351{
352  stpi_subchannel_t *sch = get_channel(v, color, subchannel);
353  stp_dprintf(STP_DBG_INK, v,
354	      "channel_cutoff channel %d subchannel %d adjustment %f\n",
355	      color, subchannel, adjustment);
356  if (sch && adjustment >= 0)
357    sch->cutoff = adjustment;
358}
359
360double
361stp_channel_get_cutoff_adjustment(stp_vars_t *v, int color, int subchannel)
362{
363  stpi_subchannel_t *sch = get_channel(v, color, subchannel);
364  if (sch)
365    return sch->cutoff;
366  else
367    return -1.0;
368}
369
370void
371stp_channel_set_gcr_curve(stp_vars_t *v, const stp_curve_t *curve)
372{
373  stpi_channel_group_t *cg = get_channel_group(v);
374  if (!cg)
375    return;
376  stp_dprintf(STP_DBG_INK, v, "set_gcr_curve\n");
377  if (curve)
378    cg->gcr_curve = stp_curve_create_copy(curve);
379  else
380    cg->gcr_curve = NULL;
381}
382
383const stp_curve_t *
384stp_channel_get_gcr_curve(stp_vars_t *v)
385{
386  stpi_channel_group_t *cg = get_channel_group(v);
387  if (!cg)
388    return NULL;
389  stp_dprintf(STP_DBG_INK, v, "set_gcr_curve\n");
390  return cg->gcr_curve;
391}
392
393void
394stp_channel_set_curve(stp_vars_t *v, int color, const stp_curve_t *curve)
395{
396  stpi_channel_t *ch;
397  stpi_channel_group_t *cg = get_channel_group(v);
398  if (!cg || color >= cg->channel_count)
399    return;
400  ch = &(cg->c[color]);
401  stp_dprintf(STP_DBG_INK, v, "set_curve channel %d set curve\n", color);
402  if (ch)
403    {
404      if (curve)
405	ch->curve = stp_curve_create_copy(curve);
406      else
407	ch->curve = NULL;
408    }
409}
410
411const stp_curve_t *
412stp_channel_get_curve(stp_vars_t *v, int color)
413{
414  stpi_channel_t *ch;
415  stpi_channel_group_t *cg = get_channel_group(v);
416  if (!cg || color >= cg->channel_count)
417    return NULL;
418  ch = &(cg->c[color]);
419  if (ch)
420    return ch->curve;
421  else
422    return NULL;
423}
424
425static int
426input_has_special_channels(const stp_vars_t *v)
427{
428  const stpi_channel_group_t *cg =
429    ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
430  return (cg->curve_count > 0);
431}
432
433static int
434output_needs_gcr(const stp_vars_t *v)
435{
436  const stpi_channel_group_t *cg =
437    ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
438  return (cg->gcr_curve && cg->black_channel == 0);
439}
440
441static int
442output_has_gloss(const stp_vars_t *v)
443{
444  const stpi_channel_group_t *cg =
445    ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
446  return (cg->gloss_channel >= 0);
447}
448
449static int
450input_needs_splitting(const stp_vars_t *v)
451{
452  const stpi_channel_group_t *cg =
453    ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
454#if 0
455  return cg->total_channels != cg->aux_output_channels;
456#else
457  int i;
458  if (!cg || cg->channel_count <= 0)
459    return 0;
460  for (i = 0; i < cg->channel_count; i++)
461    {
462      if (cg->c[i].subchannel_count > 1)
463	return 1;
464    }
465  return 0;
466#endif
467}
468
469
470void
471stp_channel_initialize(stp_vars_t *v, stp_image_t *image,
472		       int input_channel_count)
473{
474  stpi_channel_group_t *cg = get_channel_group(v);
475  int width = stp_image_width(image);
476  int curve_count = 0;
477  int i, j, k;
478  if (!cg)
479    {
480      cg = stp_zalloc(sizeof(stpi_channel_group_t));
481      cg->black_channel = -1;
482      stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
483    }
484  if (cg->initialized)
485    return;
486  cg->initialized = 1;
487  cg->max_density = 0;
488  if (cg->black_channel < -1 || cg->black_channel >= cg->channel_count)
489    cg->black_channel = -1;
490  for (i = 0; i < cg->channel_count; i++)
491    {
492      stpi_channel_t *c = &(cg->c[i]);
493      int sc = c->subchannel_count;
494      if (c->curve)
495	{
496	  curve_count++;
497	  stp_curve_resample(c->curve, 4096);
498	  c->hue_map = stp_curve_get_data(c->curve, &(c->h_count));
499	  cg->curve_count++;
500	}
501      if (sc > 1)
502	{
503	  int val = 0;
504	  int next_breakpoint;
505	  c->lut = stp_zalloc(sizeof(unsigned short) * sc * 65536);
506	  next_breakpoint = c->sc[0].value * 65535 * c->sc[0].cutoff;
507	  if (next_breakpoint > 65535)
508	    next_breakpoint = 65535;
509	  while (val <= next_breakpoint)
510	    {
511	      int value = (int) ((double) val / c->sc[0].value);
512	      c->lut[val * sc + sc - 1] = value;
513	      val++;
514	    }
515
516	  for (k = 0; k < sc - 1; k++)
517	    {
518	      double this_val = c->sc[k].value;
519	      double next_val = c->sc[k + 1].value;
520	      double this_cutoff = c->sc[k].cutoff;
521	      double next_cutoff = c->sc[k + 1].cutoff;
522	      int range;
523	      int base = val;
524	      double cutoff = sqrt(this_cutoff * next_cutoff);
525	      next_breakpoint = next_val * 65535 * cutoff;
526	      if (next_breakpoint > 65535)
527		next_breakpoint = 65535;
528	      range = next_breakpoint - val;
529	      while (val <= next_breakpoint)
530		{
531		  double where = ((double) val - base) / (double) range;
532		  double lower_val = base * (1.0 - where);
533		  double lower_amount = lower_val / this_val;
534		  double upper_amount = (val - lower_val) / next_val;
535		  if (lower_amount > 65535.0)
536		    lower_amount = 65535.0;
537		  c->lut[val * sc + sc - k - 2] = upper_amount;
538		  c->lut[val * sc + sc - k - 1] = lower_amount;
539		  val++;
540		}
541	    }
542	  while (val <= 65535)
543	    {
544	      c->lut[val * sc] = val / c->sc[sc - 1].value;
545	      val++;
546	    }
547	}
548      if (cg->gloss_channel != i && c->subchannel_count > 0)
549	cg->aux_output_channels++;
550      cg->total_channels += c->subchannel_count;
551      for (j = 0; j < c->subchannel_count; j++)
552	cg->max_density += c->sc[j].s_density;
553    }
554  if (cg->gloss_channel >= 0)
555    {
556      for (i = 0; i < cg->channel_count; i++)
557	{
558	  if (cg->gloss_channel == i)
559	    break;
560	  cg->gloss_physical_channel += cg->c[i].subchannel_count;
561	}
562    }
563
564  cg->input_channels = input_channel_count;
565  cg->width = width;
566  cg->alloc_data_1 =
567    stp_malloc(sizeof(unsigned short) * cg->total_channels * width);
568  cg->output_data = cg->alloc_data_1;
569  if (curve_count == 0)
570    {
571      cg->gcr_channels = cg->input_channels;
572      if (input_needs_splitting(v))
573	{
574	  cg->alloc_data_2 =
575	    stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
576	  cg->input_data = cg->alloc_data_2;
577	  cg->split_input = cg->input_data;
578	  cg->gcr_data = cg->split_input;
579	}
580      else if (cg->gloss_channel != -1)
581	{
582	  cg->alloc_data_2 =
583	    stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
584	  cg->input_data = cg->alloc_data_2;
585	  cg->gcr_data = cg->output_data;
586	  cg->gcr_channels = cg->total_channels;
587	}
588      else
589	{
590	  cg->input_data = cg->output_data;
591	  cg->gcr_data = cg->output_data;
592	}
593      cg->aux_output_channels = cg->gcr_channels;
594    }
595  else
596    {
597      cg->alloc_data_2 =
598	stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
599      cg->input_data = cg->alloc_data_2;
600      if (input_needs_splitting(v))
601	{
602	  cg->alloc_data_3 =
603	    stp_malloc(sizeof(unsigned short) * cg->aux_output_channels * width);
604	  cg->multi_tmp = cg->alloc_data_3;
605	  cg->split_input = cg->multi_tmp;
606	  cg->gcr_data = cg->split_input;
607	}
608      else
609	{
610	  cg->multi_tmp = cg->alloc_data_1;
611	  cg->gcr_data = cg->output_data;
612	  cg->aux_output_channels = cg->total_channels;
613	}
614      cg->gcr_channels = cg->aux_output_channels;
615    }
616  cg->cyan_balance = stp_get_float_parameter(v, "CyanBalance");
617  cg->magenta_balance = stp_get_float_parameter(v, "MagentaBalance");
618  cg->yellow_balance = stp_get_float_parameter(v, "YellowBalance");
619  stp_dprintf(STP_DBG_INK, v, "stp_channel_initialize:\n");
620  stp_dprintf(STP_DBG_INK, v, "   channel_count  %d\n", cg->channel_count);
621  stp_dprintf(STP_DBG_INK, v, "   total_channels %d\n", cg->total_channels);
622  stp_dprintf(STP_DBG_INK, v, "   input_channels %d\n", cg->input_channels);
623  stp_dprintf(STP_DBG_INK, v, "   aux_channels   %d\n", cg->aux_output_channels);
624  stp_dprintf(STP_DBG_INK, v, "   gcr_channels   %d\n", cg->gcr_channels);
625  stp_dprintf(STP_DBG_INK, v, "   width          %ld\n", (long)cg->width);
626  stp_dprintf(STP_DBG_INK, v, "   ink_limit      %d\n", cg->ink_limit);
627  stp_dprintf(STP_DBG_INK, v, "   gloss_limit    %d\n", cg->gloss_limit);
628  stp_dprintf(STP_DBG_INK, v, "   max_density    %d\n", cg->max_density);
629  stp_dprintf(STP_DBG_INK, v, "   curve_count    %d\n", cg->curve_count);
630  stp_dprintf(STP_DBG_INK, v, "   black_channel  %d\n", cg->black_channel);
631  stp_dprintf(STP_DBG_INK, v, "   gloss_channel  %d\n", cg->gloss_channel);
632  stp_dprintf(STP_DBG_INK, v, "   gloss_physical %d\n", cg->gloss_physical_channel);
633  stp_dprintf(STP_DBG_INK, v, "   cyan           %.3f\n", cg->cyan_balance);
634  stp_dprintf(STP_DBG_INK, v, "   magenta        %.3f\n", cg->magenta_balance);
635  stp_dprintf(STP_DBG_INK, v, "   yellow         %.3f\n", cg->yellow_balance);
636  stp_dprintf(STP_DBG_INK, v, "   input_data     %p\n",
637	      (void *) cg->input_data);
638  stp_dprintf(STP_DBG_INK, v, "   multi_tmp      %p\n",
639	      (void *) cg->multi_tmp);
640  stp_dprintf(STP_DBG_INK, v, "   split_input    %p\n",
641	      (void *) cg->split_input);
642  stp_dprintf(STP_DBG_INK, v, "   output_data    %p\n",
643	      (void *) cg->output_data);
644  stp_dprintf(STP_DBG_INK, v, "   gcr_data       %p\n",
645	      (void *) cg->gcr_data);
646  stp_dprintf(STP_DBG_INK, v, "   alloc_data_1   %p\n",
647	      (void *) cg->alloc_data_1);
648  stp_dprintf(STP_DBG_INK, v, "   alloc_data_2   %p\n",
649	      (void *) cg->alloc_data_2);
650  stp_dprintf(STP_DBG_INK, v, "   alloc_data_3   %p\n",
651	      (void *) cg->alloc_data_3);
652  stp_dprintf(STP_DBG_INK, v, "   gcr_curve      %p\n",
653	      (void *) cg->gcr_curve);
654  for (i = 0; i < cg->channel_count; i++)
655    {
656      stp_dprintf(STP_DBG_INK, v, "   Channel %d:\n", i);
657      for (j = 0; j < cg->c[i].subchannel_count; j++)
658	{
659	  stpi_subchannel_t *sch = &(cg->c[i].sc[j]);
660	  stp_dprintf(STP_DBG_INK, v, "      Subchannel %d:\n", j);
661	  stp_dprintf(STP_DBG_INK, v, "         value   %.3f:\n", sch->value);
662	  stp_dprintf(STP_DBG_INK, v, "         lower   %.3f:\n", sch->lower);
663	  stp_dprintf(STP_DBG_INK, v, "         upper   %.3f:\n", sch->upper);
664	  stp_dprintf(STP_DBG_INK, v, "         cutoff  %.3f:\n", sch->cutoff);
665	  stp_dprintf(STP_DBG_INK, v, "         density %d:\n", sch->s_density);
666	}
667    }
668}
669
670static void
671clear_channel(unsigned short *data, unsigned width, unsigned depth)
672{
673  int i;
674  width *= depth;
675  for (i = 0; i < width; i += depth)
676    data[i] = 0;
677}
678
679static int
680scale_channel(unsigned short *data, unsigned width, unsigned depth,
681	      unsigned short density)
682{
683  int i;
684  int retval = 0;
685  unsigned short previous_data = 0;
686  unsigned short previous_value = 0;
687  width *= depth;
688  for (i = 0; i < width; i += depth)
689    {
690      if (data[i] == previous_data)
691	data[i] = previous_value;
692      else if (data[i] == (unsigned short) 65535)
693	{
694	  data[i] = density;
695	  retval = 1;
696	}
697      else if (data[i] > 0)
698	{
699	  unsigned short tval = (32767u + data[i] * density) / 65535u;
700	  previous_data = data[i];
701	  if (tval)
702	    retval = 1;
703	  previous_value = (unsigned short) tval;
704	  data[i] = (unsigned short) tval;
705	}
706    }
707  return retval;
708}
709
710static int
711scan_channel(unsigned short *data, unsigned width, unsigned depth)
712{
713  int i;
714  width *= depth;
715  for (i = 0; i < width; i += depth)
716    {
717      if (data[i])
718	return 1;
719    }
720  return 0;
721}
722
723static inline unsigned
724ink_sum(const unsigned short *data, int total_channels)
725{
726  int j;
727  unsigned total_ink = 0;
728  for (j = 0; j < total_channels; j++)
729    total_ink += data[j];
730  return total_ink;
731}
732
733static int
734limit_ink(const stp_vars_t *v)
735{
736  int i;
737  int retval = 0;
738  stpi_channel_group_t *cg = get_channel_group(v);
739  unsigned short *ptr;
740  if (!cg || cg->ink_limit == 0 || cg->ink_limit >= cg->max_density)
741    return 0;
742  ptr = cg->output_data;
743  for (i = 0; i < cg->width; i++)
744    {
745      int total_ink = ink_sum(ptr, cg->total_channels);
746      if (total_ink > cg->ink_limit) /* Need to limit ink? */
747	{
748	  int j;
749	  /*
750	   * FIXME we probably should first try to convert light ink to dark
751	   */
752	  double ratio = (double) cg->ink_limit / (double) total_ink;
753	  for (j = 0; j < cg->total_channels; j++)
754	    ptr[j] *= ratio;
755	  retval = 1;
756	}
757      ptr += cg->total_channels;
758   }
759  return retval;
760}
761
762static inline int
763short_eq(const unsigned short *i1, const unsigned short *i2, size_t count)
764{
765#if 1
766  int i;
767  for (i = 0; i < count; i++)
768    if (i1[i] != i2[i])
769      return 0;
770  return 1;
771#else
772  return !memcmp(i1, i2, count * sizeof(unsigned short));
773#endif
774}
775
776static inline void
777short_copy(unsigned short *out, const unsigned short *in, size_t count)
778{
779#if 1
780  int i;
781  for (i = 0; i < count; i++)
782    out[i] = in[i];
783#else
784  (void) memcpy(out, in, count * sizeof(unsigned short));
785#endif
786}
787
788static void
789copy_channels(const stp_vars_t *v)
790{
791  stpi_channel_group_t *cg = get_channel_group(v);
792  int i, j, k;
793  const unsigned short *input;
794  unsigned short *output;
795  if (!cg)
796    return;
797  input = cg->input_data;
798  output = cg->output_data;
799  for (i = 0; i < cg->width; i++)
800    {
801      for (j = 0; j < cg->channel_count; j++)
802	{
803	  stpi_channel_t *ch = &(cg->c[j]);
804	  for (k = 0; k < ch->subchannel_count; k++)
805	    {
806	      if (cg->gloss_channel != j)
807		{
808		  *output = *input++;
809		}
810	      output++;
811	    }
812	}
813    }
814}
815
816static inline double
817compute_hue(int c, int m, int y, int max)
818{
819  double h;
820  if (max == c)
821    h = (m - y) / (double) max;
822  else if (max == m)
823    h = 2 + ((y - c) / (double) max);
824  else
825    h = 4 + ((c - m) / (double) max);
826  if (h < 0)
827    h += 6;
828  else if (h >= 6)
829    h -= 6;
830  return h;
831}
832
833static inline double
834interpolate_value(const double *vec, double val)
835{
836  double base = floor(val);
837  double frac = val - base;
838  int ibase = (int) base;
839  double lval = vec[ibase];
840  if (frac > 0)
841    lval += (vec[ibase + 1] - lval) * frac;
842  return lval;
843}
844
845static void
846generate_special_channels(const stp_vars_t *v)
847{
848  stpi_channel_group_t *cg = get_channel_group(v);
849  int i, j;
850  const unsigned short *input_cache = NULL;
851  const unsigned short *output_cache = NULL;
852  const unsigned short *input;
853  unsigned short *output;
854  int offset;
855  int outbytes;
856  if (!cg)
857    return;
858  input = cg->input_data;
859  output = cg->multi_tmp;
860  offset = (cg->black_channel >= 0 ? 0 : -1);
861  outbytes = cg->aux_output_channels * sizeof(unsigned short);
862  for (i = 0; i < cg->width;
863       input += cg->input_channels, output += cg->aux_output_channels, i++)
864    {
865      if (input_cache && short_eq(input_cache, input, cg->input_channels))
866	{
867	  memcpy(output, output_cache, outbytes);
868	}
869      else
870	{
871	  int c = input[STP_ECOLOR_C + offset];
872	  int m = input[STP_ECOLOR_M + offset];
873	  int y = input[STP_ECOLOR_Y + offset];
874	  int min = FMIN(c, FMIN(m, y));
875	  int max = FMAX(c, FMAX(m, y));
876	  if (max > min)	/* Otherwise it's gray, and we don't care */
877	    {
878	      double hue;
879	      /*
880	       * We're only interested in converting color components
881	       * to special inks.  We want to compute the hue and
882	       * luminosity to determine what we want to convert.
883	       * Since we're eliminating all grayscale component, the
884	       * computations become simpler.
885	       */
886	      c -= min;
887	      m -= min;
888	      y -= min;
889	      max -= min;
890	      if (offset == 0)
891		output[STP_ECOLOR_K] = input[STP_ECOLOR_K];
892	      hue = compute_hue(c, m, y, max);
893	      for (j = 1; j < cg->aux_output_channels - offset; j++)
894		{
895		  stpi_channel_t *ch = &(cg->c[j]);
896		  if (ch->hue_map)
897		    output[j + offset] =
898		      max * interpolate_value(ch->hue_map,
899					      hue * ch->h_count / 6.0);
900		  else
901		    output[j + offset] = 0;
902		}
903	      output[STP_ECOLOR_C + offset] += min;
904	      output[STP_ECOLOR_M + offset] += min;
905	      output[STP_ECOLOR_Y + offset] += min;
906	    }
907	  else
908	    {
909	      for (j = 0; j < 4 + offset; j++)
910		output[j] = input[j];
911	      for (j = 4 + offset; j < cg->aux_output_channels; j++)
912		output[j] = 0;
913	    }
914	}
915      input_cache = input;
916      output_cache = output;
917    }
918}
919
920static void
921split_channels(const stp_vars_t *v, unsigned *zero_mask)
922{
923  stpi_channel_group_t *cg = get_channel_group(v);
924  int i, j, k;
925  int nz[STP_CHANNEL_LIMIT];
926  int outbytes;
927  const unsigned short *input_cache = NULL;
928  const unsigned short *output_cache = NULL;
929  const unsigned short *input;
930  unsigned short *output;
931  if (!cg)
932    return;
933  outbytes = cg->total_channels * sizeof(unsigned short);
934  input = cg->split_input;
935  output = cg->output_data;
936  for (i = 0; i < cg->total_channels; i++)
937    nz[i] = 0;
938  for (i = 0; i < cg->width; i++)
939    {
940      int zero_ptr = 0;
941      if (input_cache && short_eq(input_cache, input, cg->aux_output_channels))
942	{
943	  memcpy(output, output_cache, outbytes);
944	  input += cg->aux_output_channels;
945	  output += cg->total_channels;
946	}
947      else
948	{
949	  unsigned black_value = 0;
950	  unsigned virtual_black = 65535;
951	  input_cache = input;
952	  output_cache = output;
953	  if (cg->black_channel >= 0)
954	    black_value = input[cg->black_channel];
955	  for (j = 0; j < cg->aux_output_channels; j++)
956	    {
957	      if (input[j] < virtual_black && j != cg->black_channel)
958		virtual_black = input[j];
959	    }
960	  black_value += virtual_black / 4;
961	  for (j = 0; j < cg->channel_count; j++)
962	    {
963	      stpi_channel_t *c = &(cg->c[j]);
964	      int s_count = c->subchannel_count;
965	      if (s_count >= 1)
966		{
967		  unsigned i_val = *input++;
968		  if (i_val == 0)
969		    {
970		      for (k = 0; k < s_count; k++)
971			*(output++) = 0;
972		    }
973		  else if (s_count == 1)
974		    {
975		      if (c->sc[0].s_density < 65535)
976			i_val = i_val * c->sc[0].s_density / 65535;
977		      nz[zero_ptr++] |= *(output++) = i_val;
978		    }
979		  else
980		    {
981		      unsigned l_val = i_val;
982		      unsigned offset;
983		      if (i_val > 0 && black_value && j != cg->black_channel)
984			{
985			  l_val += black_value;
986			  if (l_val > 65535)
987			    l_val = 65535;
988			}
989		      offset = l_val * s_count;
990		      for (k = 0; k < s_count; k++)
991			{
992			  unsigned o_val;
993			  if (c->sc[k].s_density > 0)
994			    {
995			      o_val = c->lut[offset + k];
996			      if (i_val != l_val)
997				o_val = o_val * i_val / l_val;
998			      if (c->sc[k].s_density < 65535)
999				o_val = o_val * c->sc[k].s_density / 65535;
1000			    }
1001			  else
1002			    o_val = 0;
1003			  *output++ = o_val;
1004			  nz[zero_ptr++] |= o_val;
1005			}
1006		    }
1007		}
1008	    }
1009	}
1010    }
1011  if (zero_mask)
1012    {
1013      *zero_mask = 0;
1014      for (i = 0; i < cg->total_channels; i++)
1015	if (!nz[i])
1016	  *zero_mask |= 1 << i;
1017    }
1018}
1019
1020static void
1021scale_channels(const stp_vars_t *v, unsigned *zero_mask)
1022{
1023  stpi_channel_group_t *cg = get_channel_group(v);
1024  int i, j;
1025  int physical_channel = 0;
1026  if (!cg)
1027    return;
1028  if (zero_mask)
1029    *zero_mask = 0;
1030  for (i = 0; i < cg->channel_count; i++)
1031    {
1032      stpi_channel_t *ch = &(cg->c[i]);
1033      if (ch->subchannel_count > 0)
1034	for (j = 0; j < ch->subchannel_count; j++)
1035	  {
1036	    if (cg->gloss_channel != i)
1037	      {
1038		stpi_subchannel_t *sch = &(ch->sc[j]);
1039		unsigned density = sch->s_density;
1040		unsigned short *output = cg->output_data + physical_channel;
1041		if (density == 0)
1042		  {
1043		    clear_channel(output, cg->width, cg->total_channels);
1044		    if (zero_mask)
1045		      *zero_mask |= 1 << physical_channel;
1046		  }
1047		else if (density != 65535)
1048		  {
1049		    if (scale_channel(output, cg->width, cg->total_channels,
1050				      density) == 0)
1051		      if (zero_mask)
1052			*zero_mask |= 1 << physical_channel;
1053		  }
1054		else if (zero_mask)
1055		  {
1056		    if (scan_channel(output, cg->width, cg->total_channels)==0)
1057		      *zero_mask |= 1 << physical_channel;
1058		  }
1059	      }
1060	    physical_channel++;
1061	  }
1062    }
1063}
1064
1065static void
1066generate_gloss(const stp_vars_t *v, unsigned *zero_mask)
1067{
1068  stpi_channel_group_t *cg = get_channel_group(v);
1069  unsigned short *output;
1070  unsigned gloss_mask;
1071  int i, j, k;
1072  if (!cg || cg->gloss_channel == -1 || cg->gloss_limit <= 0)
1073    return;
1074  output = cg->output_data;
1075  gloss_mask = ~(1 << cg->gloss_physical_channel);
1076  for (i = 0; i < cg->width; i++)
1077    {
1078      int physical_channel = 0;
1079      unsigned channel_sum = 0;
1080      output[cg->gloss_physical_channel] = 0;
1081      for (j = 0; j < cg->channel_count; j++)
1082	{
1083	  stpi_channel_t *ch = &(cg->c[j]);
1084	  for (k = 0; k < ch->subchannel_count; k++)
1085	    {
1086	      if (cg->gloss_channel != j)
1087		{
1088		  channel_sum += (unsigned) output[physical_channel];
1089		  if (channel_sum >= cg->gloss_limit)
1090		    goto next;
1091		}
1092	      physical_channel++;
1093	    }
1094	}
1095      if (channel_sum < cg->gloss_limit)
1096	{
1097	  unsigned gloss_required = cg->gloss_limit - channel_sum;
1098	  if (gloss_required > 65535)
1099	    gloss_required = 65535;
1100	  output[cg->gloss_physical_channel] = gloss_required;
1101	  if (zero_mask)
1102	    *zero_mask &= gloss_mask;
1103	}
1104    next:
1105      output += cg->total_channels;
1106    }
1107}
1108
1109static void
1110do_gcr(const stp_vars_t *v)
1111{
1112  stpi_channel_group_t *cg = get_channel_group(v);
1113  const unsigned short *gcr_lookup;
1114  unsigned short *output;
1115  size_t count;
1116  int i;
1117
1118  if (!cg)
1119    return;
1120
1121  output = cg->gcr_data;
1122  stp_curve_resample(cg->gcr_curve, 65536);
1123  gcr_lookup = stp_curve_get_ushort_data(cg->gcr_curve, &count);
1124  for (i = 0; i < cg->width; i++)
1125    {
1126      unsigned k = output[0];
1127      if (k > 0)
1128	{
1129	  int kk = gcr_lookup[k];
1130	  int ck;
1131	  if (kk > k)
1132	    kk = k;
1133	  ck = k - kk;
1134	  output[0] = kk;
1135	  output[1] += ck * cg->cyan_balance;
1136	  output[2] += ck * cg->magenta_balance;
1137	  output[3] += ck * cg->yellow_balance;
1138	}
1139      output += cg->gcr_channels;
1140    }
1141}
1142
1143void
1144stp_channel_convert(const stp_vars_t *v, unsigned *zero_mask)
1145{
1146  if (input_has_special_channels(v))
1147    generate_special_channels(v);
1148  else if (output_has_gloss(v) && !input_needs_splitting(v))
1149    copy_channels(v);
1150  if (output_needs_gcr(v))
1151    do_gcr(v);
1152  if (input_needs_splitting(v))
1153    split_channels(v, zero_mask);
1154  else
1155    scale_channels(v, zero_mask);
1156  (void) limit_ink(v);
1157  (void) generate_gloss(v, zero_mask);
1158}
1159
1160unsigned short *
1161stp_channel_get_input(const stp_vars_t *v)
1162{
1163  stpi_channel_group_t *cg = get_channel_group(v);
1164  if (!cg)
1165    return NULL;
1166  return (unsigned short *) cg->input_data;
1167}
1168
1169unsigned short *
1170stp_channel_get_output(const stp_vars_t *v)
1171{
1172  stpi_channel_group_t *cg = get_channel_group(v);
1173  if (!cg)
1174    return NULL;
1175  return cg->output_data;
1176}
1177