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