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