00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 #include <gimp-print/gimp-print.h>
00031 #include "gimp-print-internal.h"
00032 #include <gimp-print/gimp-print-intl-internal.h>
00033 #ifdef HAVE_LIMITS_H
00034 #include <limits.h>
00035 #endif
00036 #include <math.h>
00037 #include <string.h>
00038
00039 #ifdef __GNUC__
00040 #define inline __inline__
00041 #endif
00042
00043 typedef struct
00044 {
00045 double value;
00046 double lower;
00047 double upper;
00048 double cutoff;
00049 unsigned short s_density;
00050 } stpi_subchannel_t;
00051
00052 typedef struct
00053 {
00054 unsigned subchannel_count;
00055 stpi_subchannel_t *sc;
00056 unsigned short *lut;
00057 } stpi_channel_t;
00058
00059 typedef struct
00060 {
00061 unsigned channel_count;
00062 unsigned total_channels;
00063 unsigned input_channels;
00064 size_t width;
00065 int initialized;
00066 unsigned ink_limit;
00067 unsigned max_density;
00068 stpi_channel_t *c;
00069 unsigned short *input_data;
00070 unsigned short *data;
00071 int black_channel;
00072 } stpi_channel_group_t;
00073
00074
00075 static void
00076 clear_a_channel(stpi_channel_group_t *cg, int channel)
00077 {
00078 if (channel < cg->channel_count)
00079 {
00080 STP_SAFE_FREE(cg->c[channel].sc);
00081 STP_SAFE_FREE(cg->c[channel].lut);
00082 cg->c[channel].subchannel_count = 0;
00083 }
00084 }
00085
00086 static void
00087 stpi_channel_clear(void *vc)
00088 {
00089 stpi_channel_group_t *cg = (stpi_channel_group_t *) vc;
00090 int i;
00091 if (cg->channel_count > 0)
00092 for (i = 0; i < cg->channel_count; i++)
00093 clear_a_channel(cg, i);
00094 if (cg->data != cg->input_data)
00095 STP_SAFE_FREE(cg->data);
00096 STP_SAFE_FREE(cg->input_data);
00097 STP_SAFE_FREE(cg->c);
00098 cg->channel_count = 0;
00099 cg->total_channels = 0;
00100 cg->input_channels = 0;
00101 cg->initialized = 0;
00102 }
00103
00104 void
00105 stp_channel_reset(stp_vars_t *v)
00106 {
00107 stpi_channel_group_t *cg =
00108 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00109 if (cg)
00110 stpi_channel_clear(cg);
00111 }
00112
00113 void
00114 stp_channel_reset_channel(stp_vars_t *v, int channel)
00115 {
00116 stpi_channel_group_t *cg =
00117 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00118 if (cg)
00119 clear_a_channel(cg, channel);
00120 }
00121
00122 static void
00123 stpi_channel_free(void *vc)
00124 {
00125 stpi_channel_clear(vc);
00126 stp_free(vc);
00127 }
00128
00129 static stpi_subchannel_t *
00130 get_channel(stp_vars_t *v, unsigned channel, unsigned subchannel)
00131 {
00132 stpi_channel_group_t *cg =
00133 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00134 if (!cg)
00135 return NULL;
00136 if (channel >= cg->channel_count)
00137 return NULL;
00138 if (subchannel >= cg->c[channel].subchannel_count)
00139 return NULL;
00140 return &(cg->c[channel].sc[subchannel]);
00141 }
00142
00143 void
00144 stp_channel_add(stp_vars_t *v, unsigned channel, unsigned subchannel,
00145 double value)
00146 {
00147 stpi_channel_group_t *cg =
00148 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00149 stpi_channel_t *chan;
00150 if (!cg)
00151 {
00152 cg = stp_zalloc(sizeof(stpi_channel_group_t));
00153 cg->black_channel = -1;
00154 stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
00155 }
00156 if (channel >= cg->channel_count)
00157 {
00158 unsigned oc = cg->channel_count;
00159 cg->c = stp_realloc(cg->c, sizeof(stpi_channel_t) * (channel + 1));
00160 memset(cg->c + oc, 0, sizeof(stpi_channel_t) * (channel + 1 - oc));
00161 if (channel >= cg->channel_count)
00162 cg->channel_count = channel + 1;
00163 }
00164 chan = cg->c + channel;
00165 if (subchannel >= chan->subchannel_count)
00166 {
00167 unsigned oc = chan->subchannel_count;
00168 chan->sc =
00169 stp_realloc(chan->sc, sizeof(stpi_subchannel_t) * (subchannel + 1));
00170 (void) memset
00171 (chan->sc + oc, 0, sizeof(stpi_subchannel_t) * (subchannel + 1 - oc));
00172 chan->sc[subchannel].value = value;
00173 if (subchannel >= chan->subchannel_count)
00174 chan->subchannel_count = subchannel + 1;
00175 }
00176 chan->sc[subchannel].value = value;
00177 chan->sc[subchannel].s_density = 65535;
00178 chan->sc[subchannel].cutoff = 0.75;
00179 }
00180
00181 void
00182 stp_channel_set_density_adjustment(stp_vars_t *v, int color, int subchannel,
00183 double adjustment)
00184 {
00185 stpi_subchannel_t *sch = get_channel(v, color, subchannel);
00186 if ((strcmp(stp_get_string_parameter(v, "STPIOutputType"), "Raw") == 0 &&
00187 strcmp(stp_get_string_parameter(v, "ColorCorrection"), "None") == 0) ||
00188 strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Raw") == 0 ||
00189 strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Predithered") == 0)
00190 {
00191 stp_dprintf(STP_DBG_INK, v,
00192 "Ignoring channel_density channel %d subchannel %d adjustment %f\n",
00193 color, subchannel, adjustment);
00194 }
00195 else
00196 {
00197 stp_dprintf(STP_DBG_INK, v,
00198 "channel_density channel %d subchannel %d adjustment %f\n",
00199 color, subchannel, adjustment);
00200 if (sch && adjustment >= 0 && adjustment <= 1)
00201 sch->s_density = adjustment * 65535;
00202 }
00203 }
00204
00205 void
00206 stp_channel_set_ink_limit(stp_vars_t *v, double limit)
00207 {
00208 stpi_channel_group_t *cg =
00209 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00210 stp_dprintf(STP_DBG_INK, v, "ink_limit %f\n", limit);
00211 if (limit > 0)
00212 cg->ink_limit = 65535 * limit;
00213 }
00214
00215 void
00216 stp_channel_set_black_channel(stp_vars_t *v, int channel)
00217 {
00218 stpi_channel_group_t *cg =
00219 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00220 stp_dprintf(STP_DBG_INK, v, "black_channel %d\n", channel);
00221 cg->black_channel = channel;
00222 }
00223
00224 void
00225 stp_channel_set_cutoff_adjustment(stp_vars_t *v, int color, int subchannel,
00226 double adjustment)
00227 {
00228 stpi_subchannel_t *sch = get_channel(v, color, subchannel);
00229 stp_dprintf(STP_DBG_INK, v,
00230 "channel_cutoff channel %d subchannel %d adjustment %f\n",
00231 color, subchannel, adjustment);
00232 if (sch && adjustment >= 0)
00233 sch->cutoff = adjustment;
00234 }
00235
00236 static int
00237 input_needs_splitting(const stp_vars_t *v)
00238 {
00239 const stpi_channel_group_t *cg =
00240 ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00241 #if 1
00242 return cg->total_channels != cg->input_channels;
00243 #else
00244 int i;
00245 if (!cg || cg->channel_count <= 0)
00246 return 0;
00247 for (i = 0; i < cg->channel_count; i++)
00248 {
00249 if (cg->c[i].subchannel_count > 1)
00250 return 1;
00251 }
00252 return 0;
00253 #endif
00254 }
00255
00256 void
00257 stp_channel_initialize(stp_vars_t *v, stp_image_t *image,
00258 int input_channel_count)
00259 {
00260 stpi_channel_group_t *cg =
00261 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00262 int width = stp_image_width(image);
00263 int i, j, k;
00264 if (!cg)
00265 {
00266 cg = stp_zalloc(sizeof(stpi_channel_group_t));
00267 cg->black_channel = -1;
00268 stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
00269 }
00270 if (cg->initialized)
00271 return;
00272 cg->initialized = 1;
00273 cg->max_density = 0;
00274 if (cg->black_channel < -1 || cg->black_channel >= cg->channel_count)
00275 cg->black_channel = -1;
00276 for (i = 0; i < cg->channel_count; i++)
00277 {
00278 stpi_channel_t *c = &(cg->c[i]);
00279 int sc = c->subchannel_count;
00280 if (sc > 1)
00281 {
00282 int val = 0;
00283 int next_breakpoint;
00284 c->lut = stp_zalloc(sizeof(unsigned short) * sc * 65536);
00285 next_breakpoint = c->sc[0].value * 65535 * c->sc[0].cutoff;
00286 if (next_breakpoint > 65535)
00287 next_breakpoint = 65535;
00288 while (val <= next_breakpoint)
00289 {
00290 int value = (int) ((double) val / c->sc[0].value);
00291 c->lut[val * sc + sc - 1] = value;
00292 val++;
00293 }
00294
00295 for (k = 0; k < sc - 1; k++)
00296 {
00297 double this_val = c->sc[k].value;
00298 double next_val = c->sc[k + 1].value;
00299 double this_cutoff = c->sc[k].cutoff;
00300 double next_cutoff = c->sc[k + 1].cutoff;
00301 int range;
00302 int base = val;
00303 double cutoff = sqrt(this_cutoff * next_cutoff);
00304 next_breakpoint = next_val * 65535 * cutoff;
00305 if (next_breakpoint > 65535)
00306 next_breakpoint = 65535;
00307 range = next_breakpoint - val;
00308 while (val <= next_breakpoint)
00309 {
00310 double where = ((double) val - base) / (double) range;
00311 double lower_val = base * (1.0 - where);
00312 double lower_amount = lower_val / this_val;
00313 double upper_amount = (val - lower_val) / next_val;
00314 c->lut[val * sc + sc - k - 2] = upper_amount;
00315 c->lut[val * sc + sc - k - 1] = lower_amount;
00316 val++;
00317 }
00318 }
00319 while (val <= 65535)
00320 {
00321 c->lut[val * sc] = val / c->sc[sc - 1].value;
00322 val++;
00323 }
00324 }
00325 cg->total_channels += c->subchannel_count;
00326 for (j = 0; j < c->subchannel_count; j++)
00327 cg->max_density += c->sc[j].s_density;
00328 }
00329 cg->input_channels = input_channel_count;
00330 cg->width = width;
00331 cg->data = stp_malloc(sizeof(unsigned short) * cg->total_channels * width);
00332 if (!input_needs_splitting(v))
00333 {
00334 cg->input_data = cg->data;
00335 return;
00336 }
00337 cg->input_data =
00338 stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
00339 }
00340
00341 static void
00342 clear_channel(unsigned short *data, unsigned width, unsigned depth)
00343 {
00344 int i;
00345 width *= depth;
00346 for (i = 0; i < width; i += depth)
00347 data[i] = 0;
00348 }
00349
00350 static int
00351 scale_channel(unsigned short *data, unsigned width, unsigned depth,
00352 unsigned short density)
00353 {
00354 int i;
00355 int retval = 0;
00356 unsigned short previous_data = 0;
00357 unsigned short previous_value = 0;
00358 if (density > 65535)
00359 density = 65535;
00360 width *= depth;
00361 for (i = 0; i < width; i += depth)
00362 {
00363 if (data[i] == previous_data)
00364 data[i] = previous_value;
00365 else if (data[i] == (unsigned short) 65535)
00366 {
00367 data[i] = density;
00368 retval = 1;
00369 }
00370 else if (data[i] > 0)
00371 {
00372 unsigned short tval = (32767u + data[i] * density) / 65535u;
00373 previous_data = data[i];
00374 if (tval)
00375 retval = 1;
00376 previous_value = (unsigned short) tval;
00377 data[i] = (unsigned short) tval;
00378 }
00379 }
00380 return retval;
00381 }
00382
00383 static int
00384 scan_channel(unsigned short *data, unsigned width, unsigned depth)
00385 {
00386 int i;
00387 width *= depth;
00388 for (i = 0; i < width; i += depth)
00389 {
00390 if (data[i])
00391 return 1;
00392 }
00393 return 0;
00394 }
00395
00396 static inline unsigned
00397 ink_sum(const unsigned short *data, int total_channels)
00398 {
00399 int j;
00400 unsigned total_ink = 0;
00401 for (j = 0; j < total_channels; j++)
00402 total_ink += data[j];
00403 return total_ink;
00404 }
00405
00406 static int
00407 limit_ink(const stp_vars_t *v)
00408 {
00409 int i;
00410 int retval = 0;
00411 stpi_channel_group_t *cg =
00412 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00413 unsigned short *ptr = cg->data;
00414 if (cg->ink_limit == 0 || cg->ink_limit >= cg->max_density)
00415 return 0;
00416 for (i = 0; i < cg->width; i++)
00417 {
00418 int total_ink = ink_sum(ptr, cg->total_channels);
00419 if (total_ink > cg->ink_limit)
00420 {
00421 int j;
00422
00423
00424
00425 double ratio = (double) cg->ink_limit / (double) total_ink;
00426 for (j = 0; j < cg->total_channels; j++)
00427 ptr[j] *= ratio;
00428 retval = 1;
00429 }
00430 ptr += cg->total_channels;
00431 }
00432 return retval;
00433 }
00434
00435 static inline int
00436 mem_eq(const unsigned short *i1, const unsigned short *i2, int count)
00437 {
00438 int i;
00439 for (i = 0; i < count; i++)
00440 if (i1[i] != i2[i])
00441 return 0;
00442 return 1;
00443 }
00444
00445 void
00446 stp_channel_convert(const stp_vars_t *v, unsigned *zero_mask)
00447 {
00448 stpi_channel_group_t *cg =
00449 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00450 int i, j, k;
00451 int nz[STP_CHANNEL_LIMIT];
00452 int outbytes = cg->total_channels * sizeof(unsigned short);
00453 const unsigned short *input_cache = NULL;
00454 const unsigned short *output_cache = NULL;
00455 unsigned black_value = 0;
00456 unsigned l_val = 0;
00457 unsigned i_val = 0;
00458 unsigned o_val = 0;
00459 unsigned offset = 0;
00460 unsigned virtual_black = 0;
00461 memset(nz, 0, sizeof(nz));
00462 if (input_needs_splitting(v))
00463 {
00464 const unsigned short *input = cg->input_data;
00465 unsigned short *output = cg->data;
00466 const unsigned short *o_output;
00467 for (i = 0; i < cg->width; i++)
00468 {
00469 int zero_ptr = 0;
00470 if (input_cache && mem_eq(input_cache, input, cg->input_channels))
00471 {
00472 memcpy(output, output_cache, outbytes);
00473 input += cg->input_channels;
00474 output += cg->total_channels;
00475 }
00476 else
00477 {
00478 input_cache = input;
00479 black_value = 0;
00480 o_output = output;
00481 if (cg->black_channel >= 0)
00482 black_value = input[cg->black_channel];
00483 virtual_black = 65535;
00484 for (j = 0; j < cg->channel_count; j++)
00485 {
00486 if (input[j] < virtual_black && j != cg->black_channel)
00487 virtual_black = input[j];
00488 }
00489 black_value += virtual_black / 4;
00490 for (j = 0; j < cg->channel_count; j++)
00491 {
00492 stpi_channel_t *c = &(cg->c[j]);
00493 int s_count = c->subchannel_count;
00494 if (s_count >= 1)
00495 {
00496 i_val = *input++;
00497 if (i_val == 0)
00498 {
00499 for (k = 0; k < s_count; k++)
00500 *(output++) = 0;
00501 }
00502 else if (s_count == 1)
00503 {
00504 if (c->sc[0].s_density < 65535)
00505 i_val = i_val * c->sc[0].s_density / 65535;
00506 nz[zero_ptr++] |= *(output++) = i_val;
00507 }
00508 else
00509 {
00510 l_val = i_val;
00511 if (i_val > 0 && black_value &&
00512 j != cg->black_channel)
00513 {
00514 l_val += black_value;
00515 if (l_val > 65535)
00516 l_val = 65535;
00517 }
00518 offset = l_val * s_count;
00519 for (k = 0; k < s_count; k++)
00520 {
00521 if (c->sc[k].s_density > 0)
00522 {
00523 o_val = c->lut[offset + k];
00524 if (i_val != l_val)
00525 o_val = o_val * i_val / l_val;
00526 if (c->sc[k].s_density < 65535)
00527 o_val = o_val * c->sc[k].s_density / 65535;
00528 }
00529 else
00530 o_val = 0;
00531 *output++ = o_val;
00532 nz[zero_ptr++] |= o_val;
00533 }
00534 }
00535 }
00536 }
00537 output_cache = o_output;
00538 }
00539 }
00540 if (zero_mask)
00541 {
00542 *zero_mask = 0;
00543 for (i = 0; i < cg->total_channels; i++)
00544 if (!nz[i])
00545 *zero_mask |= 1 << i;
00546 }
00547 }
00548 else
00549 {
00550 int physical_channel = 0;
00551 if (zero_mask)
00552 *zero_mask = 0;
00553 for (i = 0; i < cg->channel_count; i++)
00554 {
00555 stpi_channel_t *ch = &(cg->c[i]);
00556 if (ch->subchannel_count > 0)
00557 for (j = 0; j < ch->subchannel_count; j++)
00558 {
00559 stpi_subchannel_t *sch = &(ch->sc[j]);
00560 unsigned density = sch->s_density;
00561 unsigned short *output = cg->data + physical_channel;
00562 if (density == 0)
00563 {
00564 clear_channel(output, cg->width, cg->total_channels);
00565 if (zero_mask)
00566 *zero_mask |= 1 << physical_channel;
00567 }
00568 else if (density != 65535)
00569 {
00570 if (scale_channel(output, cg->width, cg->total_channels,
00571 density) == 0)
00572 if (zero_mask)
00573 *zero_mask |= 1 << physical_channel;
00574 }
00575 else if (zero_mask)
00576 {
00577 if (scan_channel(output, cg->width, cg->total_channels) == 0)
00578 *zero_mask |= 1 << physical_channel;
00579 }
00580 physical_channel++;
00581 }
00582 }
00583 }
00584 (void) limit_ink(v);
00585 }
00586
00587 unsigned short *
00588 stp_channel_get_input(const stp_vars_t *v)
00589 {
00590 stpi_channel_group_t *cg =
00591 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00592 return (unsigned short *) cg->input_data;
00593 }
00594
00595 unsigned short *
00596 stp_channel_get_output(const stp_vars_t *v)
00597 {
00598 stpi_channel_group_t *cg =
00599 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00600 return cg->data;
00601 }