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