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 {
00190 stp_dprintf(STP_DBG_INK, v,
00191 "Ignoring channel_density channel %d subchannel %d adjustment %f\n",
00192 color, subchannel, adjustment);
00193 }
00194 else
00195 {
00196 stp_dprintf(STP_DBG_INK, v,
00197 "channel_density channel %d subchannel %d adjustment %f\n",
00198 color, subchannel, adjustment);
00199 if (sch && adjustment >= 0 && adjustment <= 1)
00200 sch->s_density = adjustment * 65535;
00201 }
00202 }
00203
00204 void
00205 stp_channel_set_ink_limit(stp_vars_t *v, double limit)
00206 {
00207 stpi_channel_group_t *cg =
00208 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00209 stp_dprintf(STP_DBG_INK, v, "ink_limit %f\n", limit);
00210 if (limit > 0)
00211 cg->ink_limit = 65535 * limit;
00212 }
00213
00214 void
00215 stp_channel_set_black_channel(stp_vars_t *v, int channel)
00216 {
00217 stpi_channel_group_t *cg =
00218 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00219 stp_dprintf(STP_DBG_INK, v, "black_channel %d\n", channel);
00220 cg->black_channel = channel;
00221 }
00222
00223 void
00224 stp_channel_set_cutoff_adjustment(stp_vars_t *v, int color, int subchannel,
00225 double adjustment)
00226 {
00227 stpi_subchannel_t *sch = get_channel(v, color, subchannel);
00228 stp_dprintf(STP_DBG_INK, v,
00229 "channel_cutoff channel %d subchannel %d adjustment %f\n",
00230 color, subchannel, adjustment);
00231 if (sch && adjustment >= 0)
00232 sch->cutoff = adjustment;
00233 }
00234
00235 static int
00236 input_needs_splitting(const stp_vars_t *v)
00237 {
00238 const stpi_channel_group_t *cg =
00239 ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00240 #if 1
00241 return cg->total_channels != cg->input_channels;
00242 #else
00243 int i;
00244 if (!cg || cg->channel_count <= 0)
00245 return 0;
00246 for (i = 0; i < cg->channel_count; i++)
00247 {
00248 if (cg->c[i].subchannel_count > 1)
00249 return 1;
00250 }
00251 return 0;
00252 #endif
00253 }
00254
00255 void
00256 stp_channel_initialize(stp_vars_t *v, stp_image_t *image,
00257 int input_channel_count)
00258 {
00259 stpi_channel_group_t *cg =
00260 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00261 int width = stp_image_width(image);
00262 int i, j, k;
00263 if (!cg)
00264 {
00265 cg = stp_zalloc(sizeof(stpi_channel_group_t));
00266 cg->black_channel = -1;
00267 stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
00268 }
00269 if (cg->initialized)
00270 return;
00271 cg->initialized = 1;
00272 cg->max_density = 0;
00273 if (cg->black_channel < -1 || cg->black_channel >= cg->channel_count)
00274 cg->black_channel = -1;
00275 for (i = 0; i < cg->channel_count; i++)
00276 {
00277 stpi_channel_t *c = &(cg->c[i]);
00278 int sc = c->subchannel_count;
00279 if (sc > 1)
00280 {
00281 int val = 0;
00282 int next_breakpoint;
00283 c->lut = stp_zalloc(sizeof(unsigned short) * sc * 65536);
00284 next_breakpoint = c->sc[0].value * 65535 * c->sc[0].cutoff;
00285 if (next_breakpoint > 65535)
00286 next_breakpoint = 65535;
00287 while (val <= next_breakpoint)
00288 {
00289 int value = (int) ((double) val / c->sc[0].value);
00290 c->lut[val * sc + sc - 1] = value;
00291 val++;
00292 }
00293
00294 for (k = 0; k < sc - 1; k++)
00295 {
00296 double this_val = c->sc[k].value;
00297 double next_val = c->sc[k + 1].value;
00298 double this_cutoff = c->sc[k].cutoff;
00299 double next_cutoff = c->sc[k + 1].cutoff;
00300 int range;
00301 int base = val;
00302 double cutoff = sqrt(this_cutoff * next_cutoff);
00303 next_breakpoint = next_val * 65535 * cutoff;
00304 if (next_breakpoint > 65535)
00305 next_breakpoint = 65535;
00306 range = next_breakpoint - val;
00307 while (val <= next_breakpoint)
00308 {
00309 double where = ((double) val - base) / (double) range;
00310 double lower_val = base * (1.0 - where);
00311 double lower_amount = lower_val / this_val;
00312 double upper_amount = (val - lower_val) / next_val;
00313 c->lut[val * sc + sc - k - 2] = upper_amount;
00314 c->lut[val * sc + sc - k - 1] = lower_amount;
00315 val++;
00316 }
00317 }
00318 while (val <= 65535)
00319 {
00320 c->lut[val * sc] = val / c->sc[sc - 1].value;
00321 val++;
00322 }
00323 }
00324 cg->total_channels += c->subchannel_count;
00325 for (j = 0; j < c->subchannel_count; j++)
00326 cg->max_density += c->sc[j].s_density;
00327 }
00328 cg->input_channels = input_channel_count;
00329 cg->width = width;
00330 cg->data = stp_malloc(sizeof(unsigned short) * cg->total_channels * width);
00331 if (!input_needs_splitting(v))
00332 {
00333 cg->input_data = cg->data;
00334 return;
00335 }
00336 cg->input_data =
00337 stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
00338 }
00339
00340 static void
00341 clear_channel(unsigned short *data, unsigned width, unsigned depth)
00342 {
00343 int i;
00344 width *= depth;
00345 for (i = 0; i < width; i += depth)
00346 data[i] = 0;
00347 }
00348
00349 static int
00350 scale_channel(unsigned short *data, unsigned width, unsigned depth,
00351 unsigned short density)
00352 {
00353 int i;
00354 int retval = 0;
00355 unsigned short previous_data = 0;
00356 unsigned short previous_value = 0;
00357 if (density > 65535)
00358 density = 65535;
00359 width *= depth;
00360 for (i = 0; i < width; i += depth)
00361 {
00362 if (data[i] == previous_data)
00363 data[i] = previous_value;
00364 else if (data[i] == (unsigned short) 65535)
00365 {
00366 data[i] = density;
00367 retval = 1;
00368 }
00369 else if (data[i] > 0)
00370 {
00371 unsigned short tval = (32767u + data[i] * density) / 65535u;
00372 previous_data = data[i];
00373 if (tval)
00374 retval = 1;
00375 previous_value = (unsigned short) tval;
00376 data[i] = (unsigned short) tval;
00377 }
00378 }
00379 return retval;
00380 }
00381
00382 static int
00383 scan_channel(unsigned short *data, unsigned width, unsigned depth)
00384 {
00385 int i;
00386 width *= depth;
00387 for (i = 0; i < width; i += depth)
00388 {
00389 if (data[i])
00390 return 1;
00391 }
00392 return 0;
00393 }
00394
00395 static inline unsigned
00396 ink_sum(const unsigned short *data, int total_channels)
00397 {
00398 int j;
00399 unsigned total_ink = 0;
00400 for (j = 0; j < total_channels; j++)
00401 total_ink += data[j];
00402 return total_ink;
00403 }
00404
00405 static int
00406 limit_ink(const stp_vars_t *v)
00407 {
00408 int i;
00409 int retval = 0;
00410 stpi_channel_group_t *cg =
00411 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00412 unsigned short *ptr = cg->data;
00413 if (cg->ink_limit == 0 || cg->ink_limit >= cg->max_density)
00414 return 0;
00415 for (i = 0; i < cg->width; i++)
00416 {
00417 int total_ink = ink_sum(ptr, cg->total_channels);
00418 if (total_ink > cg->ink_limit)
00419 {
00420 int j;
00421
00422
00423
00424 double ratio = (double) cg->ink_limit / (double) total_ink;
00425 for (j = 0; j < cg->total_channels; j++)
00426 ptr[j] *= ratio;
00427 retval = 1;
00428 }
00429 ptr += cg->total_channels;
00430 }
00431 return retval;
00432 }
00433
00434 static inline int
00435 mem_eq(const unsigned short *i1, const unsigned short *i2, int count)
00436 {
00437 int i;
00438 for (i = 0; i < count; i++)
00439 if (i1[i] != i2[i])
00440 return 0;
00441 return 1;
00442 }
00443
00444 void
00445 stp_channel_convert(const stp_vars_t *v, unsigned *zero_mask)
00446 {
00447 stpi_channel_group_t *cg =
00448 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00449 int i, j, k;
00450 int nz[STP_CHANNEL_LIMIT];
00451 int outbytes = cg->total_channels * sizeof(unsigned short);
00452 const unsigned short *input_cache = NULL;
00453 const unsigned short *output_cache = NULL;
00454 unsigned black_value = 0;
00455 unsigned l_val = 0;
00456 unsigned i_val = 0;
00457 unsigned o_val = 0;
00458 unsigned offset = 0;
00459 unsigned virtual_black = 0;
00460 memset(nz, 0, sizeof(nz));
00461 if (input_needs_splitting(v))
00462 {
00463 const unsigned short *input = cg->input_data;
00464 unsigned short *output = cg->data;
00465 const unsigned short *o_output;
00466 for (i = 0; i < cg->width; i++)
00467 {
00468 int zero_ptr = 0;
00469 if (input_cache && mem_eq(input_cache, input, cg->input_channels))
00470 {
00471 memcpy(output, output_cache, outbytes);
00472 input += cg->input_channels;
00473 output += cg->total_channels;
00474 }
00475 else
00476 {
00477 input_cache = input;
00478 black_value = 0;
00479 o_output = output;
00480 if (cg->black_channel >= 0)
00481 black_value = input[cg->black_channel];
00482 virtual_black = 65535;
00483 for (j = 0; j < cg->channel_count; j++)
00484 {
00485 if (input[j] < virtual_black && j != cg->black_channel)
00486 virtual_black = input[j];
00487 }
00488 black_value += virtual_black / 4;
00489 for (j = 0; j < cg->channel_count; j++)
00490 {
00491 stpi_channel_t *c = &(cg->c[j]);
00492 int s_count = c->subchannel_count;
00493 if (s_count >= 1)
00494 {
00495 i_val = *input++;
00496 if (i_val == 0)
00497 {
00498 for (k = 0; k < s_count; k++)
00499 *(output++) = 0;
00500 }
00501 else if (s_count == 1)
00502 {
00503 if (c->sc[0].s_density < 65535)
00504 i_val = i_val * c->sc[0].s_density / 65535;
00505 nz[zero_ptr++] |= *(output++) = i_val;
00506 }
00507 else
00508 {
00509 l_val = i_val;
00510 if (i_val > 0 && black_value &&
00511 j != cg->black_channel)
00512 {
00513 l_val += black_value;
00514 if (l_val > 65535)
00515 l_val = 65535;
00516 }
00517 offset = l_val * s_count;
00518 for (k = 0; k < s_count; k++)
00519 {
00520 if (c->sc[k].s_density > 0)
00521 {
00522 o_val = c->lut[offset + k];
00523 if (i_val != l_val)
00524 o_val = o_val * i_val / l_val;
00525 if (c->sc[k].s_density < 65535)
00526 o_val = o_val * c->sc[k].s_density / 65535;
00527 }
00528 else
00529 o_val = 0;
00530 *output++ = o_val;
00531 nz[zero_ptr++] |= o_val;
00532 }
00533 }
00534 }
00535 }
00536 output_cache = o_output;
00537 }
00538 }
00539 if (zero_mask)
00540 {
00541 *zero_mask = 0;
00542 for (i = 0; i < cg->total_channels; i++)
00543 if (!nz[i])
00544 *zero_mask |= 1 << i;
00545 }
00546 }
00547 else
00548 {
00549 int physical_channel = 0;
00550 if (zero_mask)
00551 *zero_mask = 0;
00552 for (i = 0; i < cg->channel_count; i++)
00553 {
00554 stpi_channel_t *ch = &(cg->c[i]);
00555 if (ch->subchannel_count > 0)
00556 for (j = 0; j < ch->subchannel_count; j++)
00557 {
00558 stpi_subchannel_t *sch = &(ch->sc[j]);
00559 unsigned density = sch->s_density;
00560 unsigned short *output = cg->data + physical_channel;
00561 if (density == 0)
00562 {
00563 clear_channel(output, cg->width, cg->total_channels);
00564 if (zero_mask)
00565 *zero_mask |= 1 << physical_channel;
00566 }
00567 else if (density != 65535)
00568 {
00569 if (scale_channel(output, cg->width, cg->total_channels,
00570 density) == 0)
00571 if (zero_mask)
00572 *zero_mask |= 1 << physical_channel;
00573 }
00574 else if (zero_mask)
00575 {
00576 if (scan_channel(output, cg->width, cg->total_channels) == 0)
00577 *zero_mask |= 1 << physical_channel;
00578 }
00579 physical_channel++;
00580 }
00581 }
00582 }
00583 (void) limit_ink(v);
00584 }
00585
00586 unsigned short *
00587 stp_channel_get_input(const stp_vars_t *v)
00588 {
00589 stpi_channel_group_t *cg =
00590 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00591 return (unsigned short *) cg->input_data;
00592 }
00593
00594 unsigned short *
00595 stp_channel_get_output(const stp_vars_t *v)
00596 {
00597 stpi_channel_group_t *cg =
00598 ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00599 return cg->data;
00600 }