void stp_dither_set_inks_full(stp_vars_t *v, int color, int nshades, const stp_shade_t *shades, double density, double darkness) { int i; int idx; stpi_dither_channel_t *dc; stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither"); stp_channel_reset_channel(v, color); for (i = nshades - 1; i >= 0; i--) { int subchannel = nshades - i - 1; idx = stpi_dither_translate_channel(v, color, subchannel); assert(idx >= 0); dc = &(CHANNEL(d, idx)); stp_channel_add(v, color, subchannel, shades[i].value); if (idx >= 0) stpi_dither_set_ranges(v, idx, &shades[i], density, shades[i].value * darkness); stp_dprintf(STP_DBG_INK, v, " shade %d value %f\n", i, shades[i].value); } }
void stp_channel_set_gloss_limit(stp_vars_t *v, double limit) { stpi_channel_group_t *cg = get_channel_group(v); stp_dprintf(STP_DBG_INK, v, "gloss_limit %f\n", limit); if (cg && limit > 0) cg->gloss_limit = 65535 * limit; }
void stp_channel_set_gloss_channel(stp_vars_t *v, int channel) { stpi_channel_group_t *cg = get_channel_group(v); stp_dprintf(STP_DBG_INK, v, "gloss_channel %d\n", channel); if (cg) cg->gloss_channel = channel; }
void stp_channel_add(stp_vars_t *v, unsigned channel, unsigned subchannel, double value) { stpi_channel_group_t *cg = get_channel_group(v); stpi_channel_t *chan; stp_dprintf(STP_DBG_INK, v, "Add channel %d, %d, %f\n", channel, subchannel, value); if (!cg) { cg = stp_zalloc(sizeof(stpi_channel_group_t)); cg->black_channel = -1; cg->gloss_channel = -1; stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg); stp_dprintf(STP_DBG_INK, v, "*** Set up channel data ***\n"); } if (channel >= cg->channel_count) { unsigned oc = cg->channel_count; cg->c = stp_realloc(cg->c, sizeof(stpi_channel_t) * (channel + 1)); memset(cg->c + oc, 0, sizeof(stpi_channel_t) * (channel + 1 - oc)); stp_dprintf(STP_DBG_INK, v, "*** Increment channel count from %d to %d\n", oc, channel + 1); if (channel >= cg->channel_count) cg->channel_count = channel + 1; } chan = cg->c + channel; if (subchannel >= chan->subchannel_count) { unsigned oc = chan->subchannel_count; chan->sc = stp_realloc(chan->sc, sizeof(stpi_subchannel_t) * (subchannel + 1)); (void) memset (chan->sc + oc, 0, sizeof(stpi_subchannel_t) * (subchannel + 1 - oc)); chan->sc[subchannel].value = value; stp_dprintf(STP_DBG_INK, v, "*** Increment subchannel count for %d from %d to %d\n", channel, oc, subchannel + 1); if (subchannel >= chan->subchannel_count) chan->subchannel_count = subchannel + 1; } chan->sc[subchannel].value = value; chan->sc[subchannel].s_density = 65535; chan->sc[subchannel].cutoff = 0.75; }
const stp_curve_t * stp_channel_get_gcr_curve(stp_vars_t *v) { stpi_channel_group_t *cg = get_channel_group(v); if (!cg) return NULL; stp_dprintf(STP_DBG_INK, v, "set_gcr_curve\n"); return cg->gcr_curve; }
void stp_channel_set_cutoff_adjustment(stp_vars_t *v, int color, int subchannel, double adjustment) { stpi_subchannel_t *sch = get_channel(v, color, subchannel); stp_dprintf(STP_DBG_INK, v, "channel_cutoff channel %d subchannel %d adjustment %f\n", color, subchannel, adjustment); if (sch && adjustment >= 0) sch->cutoff = adjustment; }
void stp_channel_set_gcr_curve(stp_vars_t *v, const stp_curve_t *curve) { stpi_channel_group_t *cg = get_channel_group(v); if (!cg) return; stp_dprintf(STP_DBG_INK, v, "set_gcr_curve\n"); if (curve) cg->gcr_curve = stp_curve_create_copy(curve); else cg->gcr_curve = NULL; }
void stp_channel_set_density_adjustment(stp_vars_t *v, int color, int subchannel, double adjustment) { stpi_subchannel_t *sch = get_channel(v, color, subchannel); if ((strcmp(stp_get_string_parameter(v, "STPIOutputType"), "Raw") == 0 && strcmp(stp_get_string_parameter(v, "ColorCorrection"), "None") == 0) || strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Raw") == 0 || strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Predithered") == 0) { stp_dprintf(STP_DBG_INK, v, "Ignoring channel_density channel %d subchannel %d adjustment %f\n", color, subchannel, adjustment); } else { stp_dprintf(STP_DBG_INK, v, "channel_density channel %d subchannel %d adjustment %f\n", color, subchannel, adjustment); if (sch && adjustment >= 0 && adjustment <= 1) sch->s_density = adjustment * 65535; } }
static void stpi_dither_finalize_ranges(stp_vars_t *v, stpi_dither_channel_t *dc) { stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither"); int i; unsigned lbit = dc->bit_max; dc->signif_bits = 0; while (lbit > 0) { dc->signif_bits++; lbit >>= 1; } for (i = 0; i < dc->nlevels; i++) { if (dc->ranges[i].lower->bits == dc->ranges[i].upper->bits) dc->ranges[i].is_same_ink = 1; else dc->ranges[i].is_same_ink = 0; if (dc->ranges[i].range_span > 0 && dc->ranges[i].value_span > 0) dc->ranges[i].is_equal = 0; else dc->ranges[i].is_equal = 1; stp_dprintf(STP_DBG_INK, v, " level %d value[0] %d value[1] %d range[0] %d range[1] %d\n", i, dc->ranges[i].lower->value, dc->ranges[i].upper->value, dc->ranges[i].lower->range, dc->ranges[i].upper->range); stp_dprintf(STP_DBG_INK, v, " bits[0] %d bits[1] %d\n", dc->ranges[i].lower->bits, dc->ranges[i].upper->bits); stp_dprintf(STP_DBG_INK, v, " rangespan %d valuespan %d same_ink %d equal %d\n", dc->ranges[i].range_span, dc->ranges[i].value_span, dc->ranges[i].is_same_ink, dc->ranges[i].is_equal); if (i > 0 && dc->ranges[i].lower->range >= d->adaptive_limit) { d->adaptive_limit = dc->ranges[i].lower->range + 1; if (d->adaptive_limit > 65535) d->adaptive_limit = 65535; stp_dprintf(STP_DBG_INK, v, "Setting adaptive limit to %d\n", d->adaptive_limit); } } for (i = 0; i <= dc->nlevels; i++) stp_dprintf(STP_DBG_INK, v, " ink_list[%d] range %d value %d bits %d\n", i, dc->ink_list[i].range, dc->ink_list[i].value, dc->ink_list[i].bits); if (dc->nlevels == 1 && dc->ranges[0].upper->bits == 1) dc->very_fast = 1; else dc->very_fast = 0; stp_dprintf(STP_DBG_INK, v, " bit_max %d signif_bits %d\n", dc->bit_max, dc->signif_bits); }
void stp_channel_set_curve(stp_vars_t *v, int color, const stp_curve_t *curve) { stpi_channel_t *ch; stpi_channel_group_t *cg = get_channel_group(v); if (!cg || color >= cg->channel_count) return; ch = &(cg->c[color]); stp_dprintf(STP_DBG_INK, v, "set_curve channel %d set curve\n", color); if (ch) { if (curve) ch->curve = stp_curve_create_copy(curve); else ch->curve = NULL; } }
void stp_channel_initialize(stp_vars_t *v, stp_image_t *image, int input_channel_count) { stpi_channel_group_t *cg = get_channel_group(v); int width = stp_image_width(image); int curve_count = 0; int i, j, k; if (!cg) { cg = stp_zalloc(sizeof(stpi_channel_group_t)); cg->black_channel = -1; stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg); } if (cg->initialized) return; cg->initialized = 1; cg->max_density = 0; if (cg->black_channel < -1 || cg->black_channel >= cg->channel_count) cg->black_channel = -1; for (i = 0; i < cg->channel_count; i++) { stpi_channel_t *c = &(cg->c[i]); int sc = c->subchannel_count; if (c->curve) { curve_count++; stp_curve_resample(c->curve, 4096); c->hue_map = stp_curve_get_data(c->curve, &(c->h_count)); cg->curve_count++; } if (sc > 1) { int val = 0; int next_breakpoint; c->lut = stp_zalloc(sizeof(unsigned short) * sc * 65536); next_breakpoint = c->sc[0].value * 65535 * c->sc[0].cutoff; if (next_breakpoint > 65535) next_breakpoint = 65535; while (val <= next_breakpoint) { int value = (int) ((double) val / c->sc[0].value); c->lut[val * sc + sc - 1] = value; val++; } for (k = 0; k < sc - 1; k++) { double this_val = c->sc[k].value; double next_val = c->sc[k + 1].value; double this_cutoff = c->sc[k].cutoff; double next_cutoff = c->sc[k + 1].cutoff; int range; int base = val; double cutoff = sqrt(this_cutoff * next_cutoff); next_breakpoint = next_val * 65535 * cutoff; if (next_breakpoint > 65535) next_breakpoint = 65535; range = next_breakpoint - val; while (val <= next_breakpoint) { double where = ((double) val - base) / (double) range; double lower_val = base * (1.0 - where); double lower_amount = lower_val / this_val; double upper_amount = (val - lower_val) / next_val; if (lower_amount > 65535.0) lower_amount = 65535.0; c->lut[val * sc + sc - k - 2] = upper_amount; c->lut[val * sc + sc - k - 1] = lower_amount; val++; } } while (val <= 65535) { c->lut[val * sc] = val / c->sc[sc - 1].value; val++; } } if (cg->gloss_channel != i && c->subchannel_count > 0) cg->aux_output_channels++; cg->total_channels += c->subchannel_count; for (j = 0; j < c->subchannel_count; j++) cg->max_density += c->sc[j].s_density; } if (cg->gloss_channel >= 0) { for (i = 0; i < cg->channel_count; i++) { if (cg->gloss_channel == i) break; cg->gloss_physical_channel += cg->c[i].subchannel_count; } } cg->input_channels = input_channel_count; cg->width = width; cg->alloc_data_1 = stp_malloc(sizeof(unsigned short) * cg->total_channels * width); cg->output_data = cg->alloc_data_1; if (curve_count == 0) { cg->gcr_channels = cg->input_channels; if (input_needs_splitting(v)) { cg->alloc_data_2 = stp_malloc(sizeof(unsigned short) * cg->input_channels * width); cg->input_data = cg->alloc_data_2; cg->split_input = cg->input_data; cg->gcr_data = cg->split_input; } else if (cg->gloss_channel != -1) { cg->alloc_data_2 = stp_malloc(sizeof(unsigned short) * cg->input_channels * width); cg->input_data = cg->alloc_data_2; cg->gcr_data = cg->output_data; cg->gcr_channels = cg->total_channels; } else { cg->input_data = cg->output_data; cg->gcr_data = cg->output_data; } cg->aux_output_channels = cg->gcr_channels; } else { cg->alloc_data_2 = stp_malloc(sizeof(unsigned short) * cg->input_channels * width); cg->input_data = cg->alloc_data_2; if (input_needs_splitting(v)) { cg->alloc_data_3 = stp_malloc(sizeof(unsigned short) * cg->aux_output_channels * width); cg->multi_tmp = cg->alloc_data_3; cg->split_input = cg->multi_tmp; cg->gcr_data = cg->split_input; } else { cg->multi_tmp = cg->alloc_data_1; cg->gcr_data = cg->output_data; cg->aux_output_channels = cg->total_channels; } cg->gcr_channels = cg->aux_output_channels; } cg->cyan_balance = stp_get_float_parameter(v, "CyanBalance"); cg->magenta_balance = stp_get_float_parameter(v, "MagentaBalance"); cg->yellow_balance = stp_get_float_parameter(v, "YellowBalance"); stp_dprintf(STP_DBG_INK, v, "stp_channel_initialize:\n"); stp_dprintf(STP_DBG_INK, v, " channel_count %d\n", cg->channel_count); stp_dprintf(STP_DBG_INK, v, " total_channels %d\n", cg->total_channels); stp_dprintf(STP_DBG_INK, v, " input_channels %d\n", cg->input_channels); stp_dprintf(STP_DBG_INK, v, " aux_channels %d\n", cg->aux_output_channels); stp_dprintf(STP_DBG_INK, v, " gcr_channels %d\n", cg->gcr_channels); stp_dprintf(STP_DBG_INK, v, " width %ld\n", (long)cg->width); stp_dprintf(STP_DBG_INK, v, " ink_limit %d\n", cg->ink_limit); stp_dprintf(STP_DBG_INK, v, " gloss_limit %d\n", cg->gloss_limit); stp_dprintf(STP_DBG_INK, v, " max_density %d\n", cg->max_density); stp_dprintf(STP_DBG_INK, v, " curve_count %d\n", cg->curve_count); stp_dprintf(STP_DBG_INK, v, " black_channel %d\n", cg->black_channel); stp_dprintf(STP_DBG_INK, v, " gloss_channel %d\n", cg->gloss_channel); stp_dprintf(STP_DBG_INK, v, " gloss_physical %d\n", cg->gloss_physical_channel); stp_dprintf(STP_DBG_INK, v, " cyan %.3f\n", cg->cyan_balance); stp_dprintf(STP_DBG_INK, v, " magenta %.3f\n", cg->magenta_balance); stp_dprintf(STP_DBG_INK, v, " yellow %.3f\n", cg->yellow_balance); stp_dprintf(STP_DBG_INK, v, " input_data %p\n", (void *) cg->input_data); stp_dprintf(STP_DBG_INK, v, " multi_tmp %p\n", (void *) cg->multi_tmp); stp_dprintf(STP_DBG_INK, v, " split_input %p\n", (void *) cg->split_input); stp_dprintf(STP_DBG_INK, v, " output_data %p\n", (void *) cg->output_data); stp_dprintf(STP_DBG_INK, v, " gcr_data %p\n", (void *) cg->gcr_data); stp_dprintf(STP_DBG_INK, v, " alloc_data_1 %p\n", (void *) cg->alloc_data_1); stp_dprintf(STP_DBG_INK, v, " alloc_data_2 %p\n", (void *) cg->alloc_data_2); stp_dprintf(STP_DBG_INK, v, " alloc_data_3 %p\n", (void *) cg->alloc_data_3); stp_dprintf(STP_DBG_INK, v, " gcr_curve %p\n", (void *) cg->gcr_curve); for (i = 0; i < cg->channel_count; i++) { stp_dprintf(STP_DBG_INK, v, " Channel %d:\n", i); for (j = 0; j < cg->c[i].subchannel_count; j++) { stpi_subchannel_t *sch = &(cg->c[i].sc[j]); stp_dprintf(STP_DBG_INK, v, " Subchannel %d:\n", j); stp_dprintf(STP_DBG_INK, v, " value %.3f:\n", sch->value); stp_dprintf(STP_DBG_INK, v, " lower %.3f:\n", sch->lower); stp_dprintf(STP_DBG_INK, v, " upper %.3f:\n", sch->upper); stp_dprintf(STP_DBG_INK, v, " cutoff %.3f:\n", sch->cutoff); stp_dprintf(STP_DBG_INK, v, " density %d:\n", sch->s_density); } } }
static void stpi_dither_set_ranges(stp_vars_t *v, int color, const stp_shade_t *shade, double density, double darkness) { stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither"); stpi_dither_channel_t *dc = &(CHANNEL(d, color)); const stp_dotsize_t *ranges = shade->dot_sizes; int nlevels = shade->numsizes; int i; STP_SAFE_FREE(dc->ranges); STP_SAFE_FREE(dc->ink_list); dc->nlevels = nlevels > 1 ? nlevels + 1 : nlevels; dc->ranges = (stpi_dither_segment_t *) stp_zalloc(dc->nlevels * sizeof(stpi_dither_segment_t)); dc->ink_list = (stpi_ink_defn_t *) stp_zalloc((dc->nlevels + 1) * sizeof(stpi_ink_defn_t)); dc->bit_max = 0; dc->density = density * 65535; dc->darkness = darkness; stp_init_debug_messages(v); stp_dprintf(STP_DBG_INK, v, "stpi_dither_set_ranges channel %d nlevels %d density %f darkness %f\n", color, nlevels, density, darkness); for (i = 0; i < nlevels; i++) stp_dprintf(STP_DBG_INK, v, " level %d value %f pattern %x\n", i, ranges[i].value, ranges[i].bit_pattern); dc->ranges[0].lower = &dc->ink_list[0]; dc->ranges[0].upper = &dc->ink_list[1]; dc->ink_list[0].range = 0; dc->ink_list[0].value = 0; dc->ink_list[0].bits = 0; if (nlevels == 1) dc->ink_list[1].range = 65535; else dc->ink_list[1].range = ranges[0].value * 65535.0 * density; if (dc->ink_list[1].range > 65535) dc->ink_list[1].range = 65535; dc->ink_list[1].value = ranges[0].value * 65535.0; if (dc->ink_list[1].value > 65535) dc->ink_list[1].value = 65535; dc->ink_list[1].bits = ranges[0].bit_pattern; if (ranges[0].bit_pattern > dc->bit_max) dc->bit_max = ranges[0].bit_pattern; dc->ranges[0].range_span = dc->ranges[0].upper->range; dc->ranges[0].value_span = dc->ranges[0].upper->value; if (dc->nlevels > 1) { for (i = 1; i < nlevels; i++) { int l = i + 1; dc->ranges[i].lower = &dc->ink_list[i]; dc->ranges[i].upper = &dc->ink_list[l]; dc->ink_list[l].range = (ranges[i].value + ranges[i].value) * 32768.0 * density; if (dc->ink_list[l].range > 65535) dc->ink_list[l].range = 65535; dc->ink_list[l].value = ranges[i].value * 65535.0; if (dc->ink_list[l].value > 65535) dc->ink_list[l].value = 65535; dc->ink_list[l].bits = ranges[i].bit_pattern; if (ranges[i].bit_pattern > dc->bit_max) dc->bit_max = ranges[i].bit_pattern; dc->ranges[i].range_span = dc->ink_list[l].range - dc->ink_list[i].range; dc->ranges[i].value_span = dc->ink_list[l].value - dc->ink_list[i].value; } dc->ranges[i].lower = &dc->ink_list[i]; dc->ranges[i].upper = &dc->ink_list[i+1]; dc->ink_list[i+1] = dc->ink_list[i]; dc->ink_list[i+1].range = 65535; dc->ranges[i].range_span = dc->ink_list[i+1].range - dc->ink_list[i].range; dc->ranges[i].value_span = dc->ink_list[i+1].value - dc->ink_list[i].value; } stpi_dither_finalize_ranges(v, dc); stp_flush_debug_messages(v); }