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
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032 #include <gimp-print/gimp-print.h>
00033 #include "gimp-print-internal.h"
00034 #include <gimp-print/gimp-print-intl-internal.h>
00035 #include <math.h>
00036 #ifdef HAVE_LIMITS_H
00037 #include <limits.h>
00038 #endif
00039 #include <string.h>
00040 #include "module.h"
00041 #include "xml.h"
00042
00043 #ifdef __GNUC__
00044 #define inline __inline__
00045 #endif
00046
00047
00048 typedef unsigned (*stp_convert_t)(stp_const_vars_t vars,
00049 const unsigned char *in,
00050 unsigned short *out);
00051
00052 static void initialize_gcr_curve(stp_const_vars_t vars);
00053
00054
00055 typedef struct
00056 {
00057 unsigned steps;
00058 unsigned char *in_data;
00059 int image_bpp;
00060 int image_width;
00061 int out_channels;
00062 int channels_are_initialized;
00063 int input_color_model;
00064 int output_color_model;
00065 int output_type;
00066 stp_convert_t colorfunc;
00067 stp_curve_t composite;
00068 stp_curve_t black;
00069 stp_curve_t cyan;
00070 stp_curve_t magenta;
00071 stp_curve_t yellow;
00072 stp_curve_t hue_map;
00073 stp_curve_t lum_map;
00074 stp_curve_t sat_map;
00075 stp_curve_t gcr_curve;
00076 unsigned short *cmy_tmp;
00077 unsigned short *cmyk_lut;
00078 int linear_contrast_adjustment;
00079 double print_gamma;
00080 double app_gamma;
00081 double screen_gamma;
00082 double brightness;
00083 double contrast;
00084 } lut_t;
00085
00086 typedef struct
00087 {
00088 const stp_parameter_t param;
00089 double min;
00090 double max;
00091 double defval;
00092 int color_only;
00093 } float_param_t;
00094
00095 static const float_param_t float_parameters[] =
00096 {
00097 {
00098 {
00099 "ColorCorrection", N_("Color Correction"),
00100 N_("Color correction to be applied"),
00101 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_OUTPUT,
00102 STP_PARAMETER_LEVEL_ADVANCED, 1, 1, -1, 1
00103 }, 0.0, 0.0, 0.0, 0
00104 },
00105 {
00106 {
00107 "Brightness", N_("Brightness"),
00108 N_("Brightness of the print (0 is solid black, 2 is solid white)"),
00109 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00110 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1
00111 }, 0.0, 2.0, 1.0, 0
00112 },
00113 {
00114 {
00115 "Contrast", N_("Contrast"),
00116 N_("Contrast of the print (0 is solid gray)"),
00117 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00118 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1
00119 }, 0.0, 4.0, 1.0, 0
00120 },
00121 {
00122 {
00123 "LinearContrast", N_("Linear Contrast Adjustment"),
00124 N_("Use linear vs. fixed end point contrast adjustment"),
00125 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_OUTPUT,
00126 STP_PARAMETER_LEVEL_ADVANCED3, 1, 1, -1, 1
00127 }, 0.0, 0.0, 0.0, 0
00128 },
00129 {
00130 {
00131 "Gamma", N_("Gamma"),
00132 N_("Adjust the gamma of the print. Larger values will "
00133 "produce a generally brighter print, while smaller "
00134 "values will produce a generally darker print. "
00135 "Black and white will remain the same, unlike with "
00136 "the brightness adjustment."),
00137 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00138 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1
00139 }, 0.1, 4.0, 1.0, 0
00140 },
00141 {
00142 {
00143 "AppGamma", N_("AppGamma"),
00144 N_("Gamma value assumed by application"),
00145 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00146 STP_PARAMETER_LEVEL_ADVANCED5, 0, 1, -1, 1
00147 }, 0.1, 4.0, 1.0, 0
00148 },
00149 {
00150 {
00151 "CyanGamma", N_("Cyan"),
00152 N_("Adjust the cyan gamma"),
00153 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00154 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, 1, 1
00155 }, 0.0, 4.0, 1.0, 1
00156 },
00157 {
00158 {
00159 "MagentaGamma", N_("Magenta"),
00160 N_("Adjust the magenta gamma"),
00161 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00162 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, 2, 1
00163 }, 0.0, 4.0, 1.0, 1
00164 },
00165 {
00166 {
00167 "YellowGamma", N_("Yellow"),
00168 N_("Adjust the yellow gamma"),
00169 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00170 STP_PARAMETER_LEVEL_ADVANCED1, 1, 1, 3, 1
00171 }, 0.0, 4.0, 1.0, 1
00172 },
00173 {
00174 {
00175 "Saturation", N_("Saturation"),
00176 N_("Adjust the saturation (color balance) of the print\n"
00177 "Use zero saturation to produce grayscale output "
00178 "using color and black inks"),
00179 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00180 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1
00181 }, 0.0, 9.0, 1.0, 1
00182 },
00183
00184 {
00185 {
00186 "InkLimit", N_("Ink Limit"),
00187 N_("Limit the total ink printed to the page"),
00188 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00189 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 0
00190 }, 0.0, 32.0, 32.0, 1
00191 },
00192 {
00193 {
00194 "BlackGamma", N_("GCR Transition"),
00195 N_("Adjust the gray component transition rate"),
00196 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00197 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1
00198 }, 0.0, 1.0, 1.0, 1
00199 },
00200 {
00201 {
00202 "GCRLower", N_("GCR Lower Bound"),
00203 N_("Lower bound of gray component reduction"),
00204 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00205 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1
00206 }, 0.0, 1.0, 0.2, 1
00207 },
00208 {
00209 {
00210 "GCRUpper", N_("GCR Upper Bound"),
00211 N_("Upper bound of gray component reduction"),
00212 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00213 STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, 0, 1
00214 }, 0.0, 5.0, 0.5, 1
00215 },
00216 };
00217
00218 static const int float_parameter_count =
00219 sizeof(float_parameters) / sizeof(float_param_t);
00220
00221 typedef struct
00222 {
00223 stp_parameter_t param;
00224 stp_curve_t *defval;
00225 int color_only;
00226 int hsl_only;
00227 } curve_param_t;
00228
00229 static int standard_curves_initialized = 0;
00230
00231 static stp_curve_t hue_map_bounds = NULL;
00232 static stp_curve_t lum_map_bounds = NULL;
00233 static stp_curve_t sat_map_bounds = NULL;
00234 static stp_curve_t color_curve_bounds = NULL;
00235 static stp_curve_t gcr_curve_bounds = NULL;
00236
00237 static curve_param_t curve_parameters[] =
00238 {
00239 {
00240 {
00241 "CompositeCurve", N_("Composite Curve"),
00242 N_("Composite (Grayscale) curve"),
00243 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00244 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, -1, 1
00245 }, &color_curve_bounds, 0, 0
00246 },
00247 {
00248 {
00249 "CyanCurve", N_("Cyan Curve"),
00250 N_("Cyan curve"),
00251 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00252 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, 1, 1
00253 }, &color_curve_bounds, 1, 0
00254 },
00255 {
00256 {
00257 "MagentaCurve", N_("Magenta Curve"),
00258 N_("Magenta curve"),
00259 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00260 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, 2, 1
00261 }, &color_curve_bounds, 1, 0
00262 },
00263 {
00264 {
00265 "YellowCurve", N_("Yellow Curve"),
00266 N_("Yellow curve"),
00267 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00268 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, 3, 1
00269 }, &color_curve_bounds, 1, 0
00270 },
00271 {
00272 {
00273 "BlackCurve", N_("Black Curve"),
00274 N_("Black curve"),
00275 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00276 STP_PARAMETER_LEVEL_ADVANCED2, 0, 1, 0, 1
00277 }, &color_curve_bounds, 1, 0
00278 },
00279 {
00280 {
00281 "HueMap", N_("Hue Map"),
00282 N_("Hue adjustment curve"),
00283 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00284 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, -1, 1
00285 }, &hue_map_bounds, 1, 1
00286 },
00287 {
00288 {
00289 "SatMap", N_("Saturation Map"),
00290 N_("Saturation adjustment curve"),
00291 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00292 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, -1, 1
00293 }, &sat_map_bounds, 1, 1
00294 },
00295 {
00296 {
00297 "LumMap", N_("Luminosity Map"),
00298 N_("Luminosity adjustment curve"),
00299 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00300 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, -1, 1
00301 }, &lum_map_bounds, 1, 1
00302 },
00303 {
00304 {
00305 "GCRCurve", N_("Gray Component Reduction"),
00306 N_("Gray component reduction curve"),
00307 STP_PARAMETER_TYPE_CURVE, STP_PARAMETER_CLASS_OUTPUT,
00308 STP_PARAMETER_LEVEL_ADVANCED3, 0, 1, 0, 1
00309 }, &gcr_curve_bounds, 1, 0
00310 },
00311 };
00312
00313 static const int curve_parameter_count =
00314 sizeof(curve_parameters) / sizeof(curve_param_t);
00315
00316 static stp_curve_t compute_gcr_curve(stp_const_vars_t vars);
00317
00318
00319
00320
00321
00322 #define LUM_RED 31
00323 #define LUM_GREEN 61
00324 #define LUM_BLUE 8
00325
00326
00327
00328 #define FMAX(a, b) ((a) > (b) ? (a) : (b))
00329 #define FMIN(a, b) ((a) < (b) ? (a) : (b))
00330
00331
00332
00333 static inline void
00334 calc_rgb_to_hsl(unsigned short *rgb, double *hue, double *sat,
00335 double *lightness)
00336 {
00337 double red, green, blue;
00338 double h, s, l;
00339 double min, max;
00340 double delta;
00341 int maxval;
00342
00343 red = rgb[0] / 65535.0;
00344 green = rgb[1] / 65535.0;
00345 blue = rgb[2] / 65535.0;
00346
00347 if (red > green)
00348 {
00349 if (red > blue)
00350 {
00351 max = red;
00352 maxval = 0;
00353 }
00354 else
00355 {
00356 max = blue;
00357 maxval = 2;
00358 }
00359 min = FMIN(green, blue);
00360 }
00361 else
00362 {
00363 if (green > blue)
00364 {
00365 max = green;
00366 maxval = 1;
00367 }
00368 else
00369 {
00370 max = blue;
00371 maxval = 2;
00372 }
00373 min = FMIN(red, blue);
00374 }
00375
00376 l = (max + min) / 2.0;
00377 delta = max - min;
00378
00379 if (delta < .000001)
00380 {
00381 s = 0.0;
00382 h = 0.0;
00383 }
00384 else
00385 {
00386 if (l <= .5)
00387 s = delta / (max + min);
00388 else
00389 s = delta / (2 - max - min);
00390
00391 if (maxval == 0)
00392 h = (green - blue) / delta;
00393 else if (maxval == 1)
00394 h = 2 + (blue - red) / delta;
00395 else
00396 h = 4 + (red - green) / delta;
00397
00398 if (h < 0.0)
00399 h += 6.0;
00400 else if (h > 6.0)
00401 h -= 6.0;
00402 }
00403
00404 *hue = h;
00405 *sat = s;
00406 *lightness = l;
00407 }
00408
00409 static inline double
00410 hsl_value(double n1, double n2, double hue)
00411 {
00412 if (hue < 0)
00413 hue += 6.0;
00414 else if (hue > 6)
00415 hue -= 6.0;
00416 if (hue < 1.0)
00417 return (n1 + (n2 - n1) * hue);
00418 else if (hue < 3.0)
00419 return (n2);
00420 else if (hue < 4.0)
00421 return (n1 + (n2 - n1) * (4.0 - hue));
00422 else
00423 return (n1);
00424 }
00425
00426 static inline void
00427 calc_hsl_to_rgb(unsigned short *rgb, double h, double s, double l)
00428 {
00429 if (s < .0000001)
00430 {
00431 if (l > 1)
00432 l = 1;
00433 else if (l < 0)
00434 l = 0;
00435 rgb[0] = l * 65535;
00436 rgb[1] = l * 65535;
00437 rgb[2] = l * 65535;
00438 }
00439 else
00440 {
00441 double m1, m2;
00442 double h1, h2;
00443 h1 = h + 2;
00444 h2 = h - 2;
00445
00446 if (l < .5)
00447 m2 = l * (1 + s);
00448 else
00449 m2 = l + s - (l * s);
00450 m1 = (l * 2) - m2;
00451 rgb[0] = 65535 * hsl_value(m1, m2, h1);
00452 rgb[1] = 65535 * hsl_value(m1, m2, h);
00453 rgb[2] = 65535 * hsl_value(m1, m2, h2);
00454 }
00455 }
00456
00457 static inline double
00458 update_saturation(double sat, double adjust, double isat)
00459 {
00460 if (adjust < 1)
00461 sat *= adjust;
00462 else
00463 {
00464 double s1 = sat * adjust;
00465 double s2 = 1.0 - ((1.0 - adjust) * isat);
00466 sat = FMIN(s1, s2);
00467 }
00468 if (sat > 1)
00469 sat = 1.0;
00470 return sat;
00471 }
00472
00473 static inline void
00474 update_saturation_from_rgb(unsigned short *rgb, double adjust, double isat)
00475 {
00476 double h, s, l;
00477 calc_rgb_to_hsl(rgb, &h, &s, &l);
00478 s = update_saturation(s, adjust, isat);
00479 calc_hsl_to_rgb(rgb, h, s, l);
00480 }
00481
00482 static inline double
00483 adjust_hue(stp_curve_t hue_map, double hue, size_t points)
00484 {
00485 if (hue_map)
00486 {
00487 double adjust;
00488 if (stp_curve_interpolate_value(hue_map, hue * points / 6.0, &adjust))
00489 {
00490 hue += adjust;
00491 if (hue < 0.0)
00492 hue += 6.0;
00493 else if (hue >= 6.0)
00494 hue -= 6.0;
00495 }
00496 }
00497 return hue;
00498 }
00499
00500 static inline void
00501 adjust_hsl(unsigned short *rgbout, lut_t *lut, double ssat,
00502 double isat, size_t h_points, size_t s_points, size_t l_points,
00503 int split_saturation)
00504 {
00505 if ((split_saturation || lut->hue_map || lut->lum_map ||
00506 lut->sat_map) &&
00507 (rgbout[0] != rgbout[1] || rgbout[0] != rgbout[2]))
00508 {
00509 double h, s, l;
00510 rgbout[0] ^= 65535;
00511 rgbout[1] ^= 65535;
00512 rgbout[2] ^= 65535;
00513 calc_rgb_to_hsl(rgbout, &h, &s, &l);
00514 s = update_saturation(s, ssat, isat);
00515 h = adjust_hue(lut->hue_map, h, h_points);
00516 if (lut->lum_map && l > 0.0001 && l < .9999)
00517 {
00518 double nh = h * l_points / 6.0;
00519 double el;
00520 if (stp_curve_interpolate_value(lut->lum_map, nh, &el))
00521 {
00522 double sreflection = .8 - ((1.0 - el) / 1.3) ;
00523 double isreflection = 1.0 - sreflection;
00524 double sadj = l - sreflection;
00525 double isadj = 1;
00526 double sisadj = 1;
00527 if (sadj > 0)
00528 {
00529 isadj = (1.0 / isreflection) * (isreflection - sadj);
00530 sisadj = sqrt(isadj);
00531
00532
00533
00534 s *= sqrt(isadj * sisadj);
00535 }
00536 if (el < .9999)
00537 {
00538 double es = s;
00539 es = 1 - es;
00540 es *= es * es;
00541 es = 1 - es;
00542 el = 1.0 + (es * (el - 1.0));
00543 l *= el;
00544 }
00545 else if (el > 1.0001)
00546 l = 1.0 - pow(1.0 - l, el);
00547 if (sadj > 0)
00548 {
00549
00550 l = 1.0 - ((1.0 - l) * sqrt(sqrt(sisadj)));
00551 }
00552 }
00553 }
00554 if (lut->sat_map)
00555 {
00556 double tmp;
00557 double nh = h * s_points / 6.0;
00558 if (stp_curve_interpolate_value(lut->sat_map, nh, &tmp) &&
00559 (tmp < .9999 || tmp > 1.0001))
00560 {
00561 s = update_saturation(s, tmp, tmp > 1.0 ? 1.0 / tmp : 1.0);
00562 }
00563 }
00564 calc_hsl_to_rgb(rgbout, h, s, l);
00565 rgbout[0] ^= 65535;
00566 rgbout[1] ^= 65535;
00567 rgbout[2] ^= 65535;
00568 }
00569 }
00570
00571 static inline void
00572 adjust_hsl_bright(unsigned short *rgbout, lut_t *lut, double ssat,
00573 double isat, size_t h_points, size_t s_points, size_t l_points,
00574 int split_saturation)
00575 {
00576 if ((split_saturation || lut->hue_map || lut->lum_map) &&
00577 (rgbout[0] != rgbout[1] || rgbout[0] != rgbout[2]))
00578 {
00579 double h, s, l;
00580 rgbout[0] ^= 65535;
00581 rgbout[1] ^= 65535;
00582 rgbout[2] ^= 65535;
00583 calc_rgb_to_hsl(rgbout, &h, &s, &l);
00584 s = update_saturation(s, ssat, isat);
00585 h = adjust_hue(lut->hue_map, h, h_points);
00586 if (lut->lum_map && l > 0.0001 && l < .9999)
00587 {
00588 double nh = h * l_points / 6.0;
00589 double el;
00590 if (stp_curve_interpolate_value(lut->lum_map, nh, &el))
00591 {
00592 el = 1.0 + (s * (el - 1.0));
00593 l = 1.0 - pow(1.0 - l, el);
00594 }
00595 }
00596 calc_hsl_to_rgb(rgbout, h, s, l);
00597 rgbout[0] ^= 65535;
00598 rgbout[1] ^= 65535;
00599 rgbout[2] ^= 65535;
00600 }
00601 }
00602
00603 static inline void
00604 lookup_rgb(lut_t *lut, unsigned short *rgbout,
00605 const unsigned short *red, const unsigned short *green,
00606 const unsigned short *blue)
00607 {
00608 if (lut->steps == 65536)
00609 {
00610 rgbout[0] = red[rgbout[0]];
00611 rgbout[1] = green[rgbout[1]];
00612 rgbout[2] = blue[rgbout[2]];
00613 }
00614 else
00615 {
00616 rgbout[0] = red[rgbout[0] / 256];
00617 rgbout[1] = green[rgbout[1] / 256];
00618 rgbout[2] = blue[rgbout[2] / 256];
00619 }
00620 }
00621
00622 static unsigned
00623 generic_cmy_to_kcmy(stp_const_vars_t vars, const unsigned short *in,
00624 unsigned short *out)
00625 {
00626 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
00627 int width = lut->image_width;
00628 int step = 65535 / (lut->steps - 1);
00629
00630 const unsigned short *gcr_lookup;
00631 const unsigned short *black_lookup;
00632 size_t points;
00633 int i;
00634 int j;
00635 int nz[4];
00636 unsigned retval = 0;
00637
00638 initialize_gcr_curve(vars);
00639 gcr_lookup = stp_curve_get_ushort_data(lut->gcr_curve, &points);
00640 stp_curve_resample(lut->black, lut->steps);
00641 black_lookup = stp_curve_get_ushort_data(lut->black, &points);
00642 memset(nz, 0, sizeof(nz));
00643
00644 for (i = 0; i < width; i++, out += 4, in += 3)
00645 {
00646 int c = in[0];
00647 int m = in[1];
00648 int y = in[2];
00649 int k = FMIN(c, FMIN(m, y));
00650 for (j = 0; j < 3; j++)
00651 out[j + 1] = in[j];
00652 if (k == 0)
00653 out[0] = 0;
00654 else
00655 {
00656 int where, resid;
00657 int kk;
00658 if (lut->steps == 65536)
00659 kk = gcr_lookup[k];
00660 else
00661 {
00662 where = k / step;
00663 resid = k % step;
00664 if (resid == 0)
00665 kk = gcr_lookup[where];
00666 else
00667 kk = gcr_lookup[where] +
00668 (gcr_lookup[where + 1] - gcr_lookup[where]) * resid / step;
00669 }
00670 if (kk > k)
00671 kk = k;
00672 if (lut->steps == 65536)
00673 out[0] = black_lookup[kk];
00674 else
00675 {
00676 where = kk / step;
00677 resid = kk % step;
00678 if (resid)
00679 out[0] = black_lookup[where] +
00680 (black_lookup[where + 1] - black_lookup[where]) * resid /
00681 step;
00682 else
00683 out[0] = black_lookup[where];
00684 }
00685 for (j = 1; j < 4; j++)
00686 out[j] -= kk;
00687 }
00688 for (j = 0; j < 4; j++)
00689 nz[j] |= out[j];
00690 }
00691 for (j = 0; j < 4; j++)
00692 if (nz[j] == 0)
00693 retval |= (1 << j);
00694 return retval;
00695 }
00696
00697
00698
00699
00700
00701 #define RGB_TO_RGB_FUNC(T, bits) \
00702 static unsigned \
00703 rgb_##bits##_to_rgb(stp_const_vars_t vars, const unsigned char *in, \
00704 unsigned short *out) \
00705 { \
00706 int i; \
00707 double isat = 1.0; \
00708 double ssat = stp_get_float_parameter(vars, "Saturation"); \
00709 size_t count; \
00710 int i0 = -1; \
00711 int i1 = -1; \
00712 int i2 = -1; \
00713 int o0 = 0; \
00714 int o1 = 0; \
00715 int o2 = 0; \
00716 int nz0 = 0; \
00717 int nz1 = 0; \
00718 int nz2 = 0; \
00719 const T *s_in = (const T *) in; \
00720 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
00721 int compute_saturation = ssat <= .99999 || ssat >= 1.00001; \
00722 int split_saturation = ssat > 1.4; \
00723 const unsigned short *red = \
00724 stp_curve_get_ushort_data(lut->cyan, &count); \
00725 const unsigned short *green = \
00726 stp_curve_get_ushort_data(lut->magenta, &count); \
00727 const unsigned short *blue = \
00728 stp_curve_get_ushort_data(lut->yellow, &count); \
00729 size_t h_points = 0; \
00730 size_t l_points = 0; \
00731 size_t s_points = 0; \
00732 int bright_color_adjustment = 0; \
00733 \
00734 if (strcmp(stp_get_string_parameter(vars, "ColorCorrection"), \
00735 "Bright") == 0) \
00736 bright_color_adjustment = 1; \
00737 \
00738 if (lut->hue_map) \
00739 h_points = stp_curve_count_points(lut->hue_map); \
00740 if (lut->lum_map) \
00741 l_points = stp_curve_count_points(lut->lum_map); \
00742 if (lut->sat_map) \
00743 s_points = stp_curve_count_points(lut->sat_map); \
00744 \
00745 if (split_saturation) \
00746 ssat = sqrt(ssat); \
00747 if (ssat > 1) \
00748 isat = 1.0 / ssat; \
00749 for (i = 0; i < lut->image_width; i++) \
00750 { \
00751 if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2]) \
00752 { \
00753 out[0] = o0; \
00754 out[1] = o1; \
00755 out[2] = o2; \
00756 } \
00757 else \
00758 { \
00759 i0 = s_in[0]; \
00760 i1 = s_in[1]; \
00761 i2 = s_in[2]; \
00762 out[0] = i0 * (65535u / (unsigned) ((1 << bits) - 1)); \
00763 out[1] = i1 * (65535u / (unsigned) ((1 << bits) - 1)); \
00764 out[2] = i2 * (65535u / (unsigned) ((1 << bits) - 1)); \
00765 if ((compute_saturation) && (out[0] != out[1] || out[0] != out[2])) \
00766 update_saturation_from_rgb(out, ssat, isat); \
00767 if (bright_color_adjustment) \
00768 adjust_hsl_bright(out, lut, ssat, isat, h_points, \
00769 s_points, l_points, split_saturation); \
00770 else \
00771 adjust_hsl(out, lut, ssat, isat, h_points, \
00772 s_points, l_points, split_saturation); \
00773 lookup_rgb(lut, out, red, green, blue); \
00774 o0 = out[0]; \
00775 o1 = out[1]; \
00776 o2 = out[2]; \
00777 nz0 |= o0; \
00778 nz1 |= o1; \
00779 nz2 |= o2; \
00780 } \
00781 s_in += 3; \
00782 out += 3; \
00783 } \
00784 return (nz0 ? 1 : 0) + (nz1 ? 2 : 0) + (nz2 ? 4 : 0); \
00785 }
00786
00787 RGB_TO_RGB_FUNC(unsigned char, 8)
00788 RGB_TO_RGB_FUNC(unsigned short, 16)
00789
00790
00791
00792
00793
00794 #define FAST_RGB_TO_RGB_FUNC(T, bits) \
00795 static unsigned \
00796 fast_rgb_##bits##_to_rgb(stp_const_vars_t vars, const unsigned char *in, \
00797 unsigned short *out) \
00798 { \
00799 int i; \
00800 int i0 = -1; \
00801 int i1 = -1; \
00802 int i2 = -1; \
00803 int o0 = 0; \
00804 int o1 = 0; \
00805 int o2 = 0; \
00806 int nz0 = 0; \
00807 int nz1 = 0; \
00808 int nz2 = 0; \
00809 const T *s_in = (const T *) in; \
00810 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
00811 size_t count; \
00812 const unsigned short *red; \
00813 const unsigned short *green; \
00814 const unsigned short *blue; \
00815 double isat = 1.0; \
00816 double saturation = stp_get_float_parameter(vars, "Saturation"); \
00817 \
00818 stp_curve_resample(lut->cyan, 1 << bits); \
00819 stp_curve_resample(lut->magenta, 1 << bits); \
00820 stp_curve_resample(lut->yellow, 1 << bits); \
00821 red = stp_curve_get_ushort_data(lut->cyan, &count); \
00822 green = stp_curve_get_ushort_data(lut->magenta, &count); \
00823 blue = stp_curve_get_ushort_data(lut->yellow, &count); \
00824 \
00825 if (saturation > 1) \
00826 isat = 1.0 / saturation; \
00827 for (i = 0; i < lut->image_width; i++) \
00828 { \
00829 if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2]) \
00830 { \
00831 out[0] = o0; \
00832 out[1] = o1; \
00833 out[2] = o2; \
00834 } \
00835 else \
00836 { \
00837 i0 = s_in[0]; \
00838 i1 = s_in[1]; \
00839 i2 = s_in[2]; \
00840 out[0] = red[s_in[0]]; \
00841 out[1] = green[s_in[1]]; \
00842 out[2] = blue[s_in[2]]; \
00843 if (saturation != 1.0) \
00844 update_saturation_from_rgb(out, saturation, isat); \
00845 o0 = out[0]; \
00846 o1 = out[1]; \
00847 o2 = out[2]; \
00848 nz0 |= o0; \
00849 nz1 |= o1; \
00850 nz2 |= o2; \
00851 } \
00852 s_in += 3; \
00853 out += 3; \
00854 } \
00855 return (nz0 ? 1 : 0) + (nz1 ? 2 : 0) + (nz2 ? 4 : 0); \
00856 }
00857
00858 FAST_RGB_TO_RGB_FUNC(unsigned char, 8)
00859 FAST_RGB_TO_RGB_FUNC(unsigned short, 16)
00860
00861
00862
00863
00864
00865 #define GRAY_TO_RGB_FUNC(T, bits) \
00866 static unsigned \
00867 gray_##bits##_to_rgb(stp_const_vars_t vars, const unsigned char *in, \
00868 unsigned short *out) \
00869 { \
00870 int i; \
00871 int i0 = -1; \
00872 int o0 = 0; \
00873 int o1 = 0; \
00874 int o2 = 0; \
00875 int nz0 = 0; \
00876 int nz1 = 0; \
00877 int nz2 = 0; \
00878 const T *s_in = (const T *) in; \
00879 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
00880 size_t count; \
00881 const unsigned short *red; \
00882 const unsigned short *green; \
00883 const unsigned short *blue; \
00884 \
00885 stp_curve_resample(lut->cyan, 1 << bits); \
00886 stp_curve_resample(lut->magenta, 1 << bits); \
00887 stp_curve_resample(lut->yellow, 1 << bits); \
00888 red = stp_curve_get_ushort_data(lut->cyan, &count); \
00889 green = stp_curve_get_ushort_data(lut->magenta, &count); \
00890 blue = stp_curve_get_ushort_data(lut->yellow, &count); \
00891 \
00892 for (i = 0; i < lut->image_width; i++) \
00893 { \
00894 if (i0 == s_in[0]) \
00895 { \
00896 out[0] = o0; \
00897 out[1] = o1; \
00898 out[2] = o2; \
00899 } \
00900 else \
00901 { \
00902 i0 = s_in[0]; \
00903 out[0] = red[s_in[0]]; \
00904 out[1] = green[s_in[0]]; \
00905 out[2] = blue[s_in[0]]; \
00906 o0 = out[0]; \
00907 o1 = out[1]; \
00908 o2 = out[2]; \
00909 nz0 |= o0; \
00910 nz1 |= o1; \
00911 nz2 |= o2; \
00912 } \
00913 s_in += 1; \
00914 out += 3; \
00915 } \
00916 return (nz0 ? 1 : 0) + (nz1 ? 2 : 0) + (nz2 ? 4 : 0); \
00917 }
00918
00919 GRAY_TO_RGB_FUNC(unsigned char, 8)
00920 GRAY_TO_RGB_FUNC(unsigned short, 16)
00921
00922 #define RGB_TO_KCMY_FUNC(name, bits) \
00923 static unsigned \
00924 name##_##bits##_to_kcmy(stp_const_vars_t vars, const unsigned char *in, \
00925 unsigned short *out) \
00926 { \
00927 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
00928 if (!lut->cmy_tmp) \
00929 lut->cmy_tmp = stpi_malloc(4 * 2 * lut->image_width); \
00930 name##_##bits##_to_rgb(vars, in, lut->cmy_tmp); \
00931 return generic_cmy_to_kcmy(vars, lut->cmy_tmp, out); \
00932 }
00933
00934 RGB_TO_KCMY_FUNC(gray, 8)
00935 RGB_TO_KCMY_FUNC(rgb, 8)
00936 RGB_TO_KCMY_FUNC(fast_rgb, 8)
00937 RGB_TO_KCMY_FUNC(gray, 16)
00938 RGB_TO_KCMY_FUNC(rgb, 16)
00939 RGB_TO_KCMY_FUNC(fast_rgb, 16)
00940
00941 #define RGB_TO_KCMY_LINE_ART_FUNC(T, name) \
00942 static unsigned \
00943 name##_to_kcmy_line_art(stp_const_vars_t vars, \
00944 const unsigned char *in, \
00945 unsigned short *out) \
00946 { \
00947 int i; \
00948 int z = 15; \
00949 const T *s_in = (const T *) in; \
00950 unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1))); \
00951 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
00952 int width = lut->image_width; \
00953 unsigned mask = 0; \
00954 memset(out, 0, width * 4 * sizeof(unsigned short)); \
00955 if (lut->output_color_model != lut->input_color_model) \
00956 mask = (1 << (sizeof(T) * 8)) - 1; \
00957 \
00958 for (i = 0; i < width; i++, out += 4, s_in += 3) \
00959 { \
00960 unsigned c = s_in[0] ^ mask; \
00961 unsigned m = s_in[1] ^ mask; \
00962 unsigned y = s_in[2] ^ mask; \
00963 unsigned k = (c < m ? (c < y ? c : y) : (m < y ? m : y)); \
00964 if (k >= high_bit) \
00965 { \
00966 c -= k; \
00967 m -= k; \
00968 y -= k; \
00969 } \
00970 if (k >= high_bit) \
00971 { \
00972 z &= 0xe; \
00973 out[0] = 65535; \
00974 } \
00975 if (c >= high_bit) \
00976 { \
00977 z &= 0xd; \
00978 out[1] = 65535; \
00979 } \
00980 if (m >= high_bit) \
00981 { \
00982 z &= 0xb; \
00983 out[2] = 65535; \
00984 } \
00985 if (y >= high_bit) \
00986 { \
00987 z &= 0x7; \
00988 out[3] = 65535; \
00989 } \
00990 } \
00991 return z; \
00992 }
00993
00994 RGB_TO_KCMY_LINE_ART_FUNC(unsigned char, rgb_8)
00995 RGB_TO_KCMY_LINE_ART_FUNC(unsigned short, rgb_16)
00996
00997 #define CMYK_TO_KCMY_LINE_ART_FUNC(T, name) \
00998 static unsigned \
00999 name##_to_kcmy_line_art(stp_const_vars_t vars, \
01000 const unsigned char *in, \
01001 unsigned short *out) \
01002 { \
01003 int i; \
01004 int z = 15; \
01005 const T *s_in = (const T *) in; \
01006 unsigned desired_high_bit = 0; \
01007 unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \
01008 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01009 int width = lut->image_width; \
01010 memset(out, 0, width * 4 * sizeof(unsigned short)); \
01011 if (lut->output_color_model == lut->input_color_model) \
01012 desired_high_bit = high_bit; \
01013 \
01014 for (i = 0; i < width; i++, out += 4, s_in += 4) \
01015 { \
01016 if ((s_in[3] & high_bit) == desired_high_bit) \
01017 { \
01018 z &= 0xe; \
01019 out[0] = 65535; \
01020 } \
01021 if ((s_in[0] & high_bit) == desired_high_bit) \
01022 { \
01023 z &= 0xd; \
01024 out[1] = 65535; \
01025 } \
01026 if ((s_in[1] & high_bit) == desired_high_bit) \
01027 { \
01028 z &= 0xb; \
01029 out[2] = 65535; \
01030 } \
01031 if ((s_in[2] & high_bit) == desired_high_bit) \
01032 { \
01033 z &= 0x7; \
01034 out[3] = 65535; \
01035 } \
01036 } \
01037 return z; \
01038 }
01039
01040 CMYK_TO_KCMY_LINE_ART_FUNC(unsigned char, cmyk_8)
01041 CMYK_TO_KCMY_LINE_ART_FUNC(unsigned short, cmyk_16)
01042
01043 #define GRAY_TO_COLOR_LINE_ART_FUNC(T, name, bits, channels) \
01044 static unsigned \
01045 gray_##bits##_to_##name##_line_art(stp_const_vars_t vars, \
01046 const unsigned char *in, \
01047 unsigned short *out) \
01048 { \
01049 int i; \
01050 int z = (1 << channels) - 1; \
01051 int desired_high_bit = 0; \
01052 unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \
01053 const T *s_in = (const T *) in; \
01054 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01055 int width = lut->image_width; \
01056 memset(out, 0, width * channels * sizeof(unsigned short)); \
01057 if (lut->output_color_model == lut->input_color_model) \
01058 desired_high_bit = high_bit; \
01059 \
01060 for (i = 0; i < width; i++, out += channels, s_in++) \
01061 { \
01062 if ((s_in[0] & high_bit) == desired_high_bit) \
01063 { \
01064 int j; \
01065 z = 0; \
01066 for (j = 0; j < channels; j++) \
01067 out[j] = 65535; \
01068 } \
01069 } \
01070 return z; \
01071 }
01072
01073 GRAY_TO_COLOR_LINE_ART_FUNC(unsigned char, rgb, 8, 3)
01074 GRAY_TO_COLOR_LINE_ART_FUNC(unsigned short, rgb, 16, 3)
01075 GRAY_TO_COLOR_LINE_ART_FUNC(unsigned char, kcmy, 8, 4)
01076 GRAY_TO_COLOR_LINE_ART_FUNC(unsigned short, kcmy, 16, 4)
01077
01078 #define RGB_TO_RGB_LINE_ART_FUNC(T, name) \
01079 static unsigned \
01080 name##_to_rgb_line_art(stp_const_vars_t vars, \
01081 const unsigned char *in, \
01082 unsigned short *out) \
01083 { \
01084 int i; \
01085 int z = 7; \
01086 int desired_high_bit = 0; \
01087 unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)) * 4); \
01088 const T *s_in = (const T *) in; \
01089 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01090 int width = lut->image_width; \
01091 memset(out, 0, width * 3 * sizeof(unsigned short)); \
01092 if (lut->input_color_model == lut->output_color_model) \
01093 desired_high_bit = high_bit; \
01094 \
01095 for (i = 0; i < width; i++, out += 3, s_in += 3) \
01096 { \
01097 if ((s_in[0] & high_bit) == desired_high_bit) \
01098 { \
01099 z &= 6; \
01100 out[0] = 65535; \
01101 } \
01102 if ((s_in[1] & high_bit) == desired_high_bit) \
01103 { \
01104 z &= 5; \
01105 out[1] = 65535; \
01106 } \
01107 if ((s_in[1] & high_bit) == desired_high_bit) \
01108 { \
01109 z &= 3; \
01110 out[2] = 65535; \
01111 } \
01112 } \
01113 return z; \
01114 }
01115
01116 RGB_TO_RGB_LINE_ART_FUNC(unsigned char, rgb_8)
01117 RGB_TO_RGB_LINE_ART_FUNC(unsigned short, rgb_16)
01118
01119 #define COLOR_TO_GRAY_LINE_ART_FUNC(T, name, channels, max_channels) \
01120 static unsigned \
01121 name##_to_gray_line_art(stp_const_vars_t vars, \
01122 const unsigned char *in, \
01123 unsigned short *out) \
01124 { \
01125 int i; \
01126 int z = 1; \
01127 int desired_high_bit = 0; \
01128 unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)) * max_channels); \
01129 const T *s_in = (const T *) in; \
01130 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01131 int width = lut->image_width; \
01132 memset(out, 0, width * sizeof(unsigned short)); \
01133 if (lut->output_color_model == lut->input_color_model) \
01134 desired_high_bit = high_bit; \
01135 \
01136 for (i = 0; i < width; i++, out++, s_in += channels) \
01137 { \
01138 unsigned gval = \
01139 (max_channels - channels) * (1 << ((sizeof(T) * 8) - 1)); \
01140 int j; \
01141 for (j = 0; j < channels; j++) \
01142 gval += s_in[j]; \
01143 if ((gval & high_bit) == desired_high_bit) \
01144 { \
01145 out[0] = 65535; \
01146 z = 0; \
01147 } \
01148 } \
01149 return z; \
01150 }
01151
01152 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned char, cmyk_8, 4, 4)
01153 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned short, cmyk_16, 4, 4)
01154 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned char, color_8, 3, 4)
01155 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned short, color_16, 3, 4)
01156 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned char, gray_8, 1, 1)
01157 COLOR_TO_GRAY_LINE_ART_FUNC(unsigned short, gray_16, 1, 1)
01158
01159 #define CMYK_TO_KCMY_FUNC(T, size) \
01160 static unsigned \
01161 cmyk_##size##_to_kcmy(stp_const_vars_t vars, \
01162 const unsigned char *in, \
01163 unsigned short *out) \
01164 { \
01165 int i; \
01166 unsigned retval = 0; \
01167 int j; \
01168 int nz[4]; \
01169 const T *s_in = (const T *) in; \
01170 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01171 \
01172 memset(nz, 0, sizeof(nz)); \
01173 \
01174 for (i = 0; i < lut->image_width; i++, out += 4) \
01175 { \
01176 for (j = 0; j < 4; j++) \
01177 { \
01178 int outpos = (j + 1) & 3; \
01179 int inval = *s_in++; \
01180 nz[outpos] |= j; \
01181 out[outpos] = lut->cmyk_lut[inval]; \
01182 } \
01183 } \
01184 for (j = 0; j < 4; j++) \
01185 if (nz[j] == 0) \
01186 retval |= (1 << j); \
01187 return retval; \
01188 }
01189
01190 CMYK_TO_KCMY_FUNC(unsigned char, 8)
01191 CMYK_TO_KCMY_FUNC(unsigned short, 16)
01192
01193
01194
01195
01196
01197
01198
01199 #define GRAY_TO_GRAY_FUNC(T, bits) \
01200 static unsigned \
01201 gray_##bits##_to_gray(stp_const_vars_t vars, \
01202 const unsigned char *in, \
01203 unsigned short *out) \
01204 { \
01205 int i; \
01206 int i0 = -1; \
01207 int o0 = 0; \
01208 int nz = 0; \
01209 const T *s_in = (const T *) in; \
01210 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01211 int width = lut->image_width; \
01212 size_t count; \
01213 const unsigned short *composite; \
01214 \
01215 stp_curve_resample(lut->composite, 1 << bits); \
01216 composite = stp_curve_get_ushort_data(lut->composite, &count); \
01217 \
01218 memset(out, 0, width * sizeof(unsigned short)); \
01219 \
01220 for (i = 0; i < lut->image_width; i++) \
01221 { \
01222 if (i0 != s_in[0]) \
01223 { \
01224 i0 = s_in[0]; \
01225 o0 = composite[i0]; \
01226 nz |= o0; \
01227 } \
01228 out[0] = o0; \
01229 s_in ++; \
01230 out ++; \
01231 } \
01232 return nz == 0; \
01233 }
01234
01235 GRAY_TO_GRAY_FUNC(unsigned char, 8)
01236 GRAY_TO_GRAY_FUNC(unsigned short, 16)
01237
01238
01239
01240
01241
01242 #define COLOR_TO_GRAY_FUNC(T, bits) \
01243 static unsigned \
01244 color_##bits##_to_gray(stp_const_vars_t vars, \
01245 const unsigned char *in, \
01246 unsigned short *out) \
01247 { \
01248 int i; \
01249 int i0 = -1; \
01250 int i1 = -1; \
01251 int i2 = -1; \
01252 int o0 = 0; \
01253 int nz = 0; \
01254 const T *s_in = (const T *) in; \
01255 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01256 size_t count; \
01257 const unsigned short *composite; \
01258 int l_red = LUM_RED; \
01259 int l_green = LUM_GREEN; \
01260 int l_blue = LUM_BLUE; \
01261 \
01262 stp_curve_resample(lut->composite, 1 << bits); \
01263 composite = stp_curve_get_ushort_data(lut->composite, &count); \
01264 \
01265 if (lut->input_color_model == COLOR_MODEL_CMY) \
01266 { \
01267 l_red = 100 - l_red; \
01268 l_green = 100 - l_green; \
01269 l_blue = 100 - l_blue; \
01270 } \
01271 \
01272 for (i = 0; i < lut->image_width; i++) \
01273 { \
01274 if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2]) \
01275 { \
01276 i0 = s_in[0]; \
01277 i1 = s_in[1]; \
01278 i2 = s_in[2]; \
01279 o0 = composite[(i0 * l_red + i1 * l_green + i2 * l_blue) / 100]; \
01280 nz |= o0; \
01281 } \
01282 out[0] = o0; \
01283 s_in += 3; \
01284 out ++; \
01285 } \
01286 return nz == 0; \
01287 }
01288
01289 COLOR_TO_GRAY_FUNC(unsigned char, 8)
01290 COLOR_TO_GRAY_FUNC(unsigned short, 16)
01291
01292
01293 #define CMYK_TO_GRAY_FUNC(T, size) \
01294 static unsigned \
01295 cmyk_##size##_to_gray(stp_const_vars_t vars, \
01296 const unsigned char *in, \
01297 unsigned short *out) \
01298 { \
01299 int i; \
01300 int j; \
01301 int nz = 0; \
01302 const T *s_in = (const T *) in; \
01303 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color")); \
01304 \
01305 for (i = 0; i < lut->image_width; i++, s_in += 4, out ++) \
01306 { \
01307 for (j = 0; j < 4; j++) \
01308 { \
01309 nz |= s_in[0]; \
01310 out[0] = lut->cmyk_lut[s_in[0]]; \
01311 } \
01312 } \
01313 return nz ? 1 : 0; \
01314 }
01315
01316 CMYK_TO_GRAY_FUNC(unsigned char, 8)
01317 CMYK_TO_GRAY_FUNC(unsigned short, 16)
01318
01319 static unsigned
01320 cmyk_16_to_gray_raw(stp_const_vars_t vars, const unsigned char *in,
01321 unsigned short *out)
01322 {
01323 int i;
01324 int nz[4];
01325 const unsigned short *usin = (const unsigned short *) in;
01326 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01327
01328 memset(nz, 0, sizeof(nz));
01329 for (i = 0; i < lut->image_width; i++)
01330 {
01331 nz[0] |= usin[0];
01332 out[0] = usin[0];
01333 usin += 4;
01334 out += 1;
01335 }
01336 return nz[0] ? 1 : 0;
01337 }
01338
01339 static unsigned
01340 cmyk_16_to_kcmy_raw(stp_const_vars_t vars, const unsigned char *in,
01341 unsigned short *out)
01342 {
01343 int i;
01344 int j;
01345 unsigned retval = 0;
01346 int nz[4];
01347 const unsigned short *usin = (const unsigned short *) in;
01348 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01349
01350 memset(nz, 0, sizeof(nz));
01351 for (i = 0; i < lut->image_width; i++)
01352 {
01353 out[0] = usin[3];
01354 out[1] = usin[0];
01355 out[2] = usin[1];
01356 out[3] = usin[2];
01357 for (j = 0; j < 4; j++)
01358 nz[j] |= out[j];
01359 usin += 4;
01360 out += 4;
01361 }
01362 for (j = 0; j < 4; j++)
01363 if (nz[j] == 0)
01364 retval |= (1 << j);
01365 return retval;
01366 }
01367
01368 static unsigned
01369 raw_to_raw(stp_const_vars_t vars, const unsigned char *in,
01370 unsigned short *out)
01371 {
01372 int i;
01373 int j;
01374 unsigned retval = 0;
01375 int nz[STP_CHANNEL_LIMIT];
01376 int colors;
01377 const unsigned short *usin = (const unsigned short *) in;
01378 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01379 colors = lut->image_bpp / 2;
01380
01381 memset(nz, 0, sizeof(nz));
01382 for (i = 0; i < lut->image_width; i++)
01383 {
01384 for (j = 0; j < colors; j++)
01385 {
01386 nz[j] |= usin[j];
01387 out[j] = usin[j];
01388 }
01389 usin += colors;
01390 out += colors;
01391 }
01392 for (j = 0; j < colors; j++)
01393 if (nz[j] == 0)
01394 retval |= (1 << j);
01395 return retval;
01396 }
01397
01398
01399 static void
01400 initialize_channels(stp_vars_t v, stp_image_t *image)
01401 {
01402 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
01403 if (stp_check_float_parameter(v, "InkLimit", STP_PARAMETER_ACTIVE))
01404 stpi_channel_set_ink_limit(v, stp_get_float_parameter(v, "InkLimit"));
01405 stpi_channel_initialize(v, image, lut->out_channels);
01406 lut->channels_are_initialized = 1;
01407 }
01408
01409 static int
01410 stpi_color_traditional_get_row(stp_vars_t v,
01411 stp_image_t *image,
01412 int row,
01413 unsigned *zero_mask)
01414 {
01415 const lut_t *lut = (const lut_t *)(stpi_get_component_data(v, "Color"));
01416 unsigned zero;
01417 if (stpi_image_get_row(image, lut->in_data,
01418 lut->image_width * lut->image_bpp, row)
01419 != STP_IMAGE_STATUS_OK)
01420 return 2;
01421 if (!lut->channels_are_initialized)
01422 initialize_channels(v, image);
01423 zero = (lut->colorfunc)(v, lut->in_data, stpi_channel_get_input(v));
01424 if (zero_mask)
01425 *zero_mask = zero;
01426 stpi_channel_convert(v, zero_mask);
01427 return 0;
01428 }
01429
01430 static lut_t *
01431 allocate_lut(void)
01432 {
01433 lut_t *ret = stpi_malloc(sizeof(lut_t));
01434 ret->composite = stp_curve_create(STP_CURVE_WRAP_NONE);
01435 ret->black = stp_curve_create(STP_CURVE_WRAP_NONE);
01436 ret->cyan = stp_curve_create(STP_CURVE_WRAP_NONE);
01437 ret->magenta = stp_curve_create(STP_CURVE_WRAP_NONE);
01438 ret->yellow = stp_curve_create(STP_CURVE_WRAP_NONE);
01439 stp_curve_set_bounds(ret->composite, 0, 65535);
01440 stp_curve_set_bounds(ret->black, 0, 65535);
01441 stp_curve_set_bounds(ret->cyan, 0, 65535);
01442 stp_curve_set_bounds(ret->magenta, 0, 65535);
01443 stp_curve_set_bounds(ret->yellow, 0, 65535);
01444 ret->hue_map = NULL;
01445 ret->lum_map = NULL;
01446 ret->sat_map = NULL;
01447 ret->gcr_curve = NULL;
01448 ret->steps = 0;
01449 ret->image_bpp = 0;
01450 ret->image_width = 0;
01451 ret->in_data = NULL;
01452 ret->colorfunc = NULL;
01453 ret->cmy_tmp = NULL;
01454 ret->cmyk_lut = NULL;
01455 ret->channels_are_initialized = 0;
01456 return ret;
01457 }
01458
01459 static void *
01460 copy_lut(void *vlut)
01461 {
01462 const lut_t *src = (const lut_t *)vlut;
01463 lut_t *dest;
01464 if (!src)
01465 return NULL;
01466 dest = allocate_lut();
01467 dest->composite = stp_curve_create_copy(src->composite);
01468 dest->cyan = stp_curve_create_copy(src->cyan);
01469 dest->magenta = stp_curve_create_copy(src->magenta);
01470 dest->yellow = stp_curve_create_copy(src->yellow);
01471 if (src->hue_map)
01472 dest->hue_map = stp_curve_create_copy(src->hue_map);
01473 if (src->lum_map)
01474 dest->lum_map = stp_curve_create_copy(src->lum_map);
01475 if (src->sat_map)
01476 dest->sat_map = stp_curve_create_copy(src->sat_map);
01477 if (src->gcr_curve)
01478 dest->gcr_curve = stp_curve_create_copy(src->gcr_curve);
01479 dest->steps = src->steps;
01480 dest->colorfunc = src->colorfunc;
01481 dest->image_bpp = src->image_bpp;
01482 dest->image_width = src->image_width;
01483 dest->input_color_model = src->input_color_model;
01484 dest->output_color_model = src->output_color_model;
01485 dest->cmy_tmp = NULL;
01486 if (src->in_data)
01487 {
01488 dest->in_data = stpi_malloc(src->image_width * src->image_bpp);
01489 memset(dest->in_data, 0, src->image_width * src->image_bpp);
01490 }
01491 else
01492 dest->in_data = NULL;
01493 return dest;
01494 }
01495
01496 static void
01497 free_lut(void *vlut)
01498 {
01499 lut_t *lut = (lut_t *)vlut;
01500 if (lut->composite)
01501 stp_curve_free(lut->composite);
01502 if (lut->black)
01503 stp_curve_free(lut->black);
01504 if (lut->cyan)
01505 stp_curve_free(lut->cyan);
01506 if (lut->magenta)
01507 stp_curve_free(lut->magenta);
01508 if (lut->yellow)
01509 stp_curve_free(lut->yellow);
01510 if (lut->hue_map)
01511 stp_curve_free(lut->hue_map);
01512 if (lut->lum_map)
01513 stp_curve_free(lut->lum_map);
01514 if (lut->sat_map)
01515 stp_curve_free(lut->sat_map);
01516 if (lut->gcr_curve)
01517 stp_curve_free(lut->gcr_curve);
01518 SAFE_FREE(lut->in_data);
01519 SAFE_FREE(lut->cmy_tmp);
01520 SAFE_FREE(lut->cmyk_lut);
01521 memset(lut, 0, sizeof(lut_t));
01522 stpi_free(lut);
01523 }
01524
01525 static stp_curve_t
01526 compute_gcr_curve(stp_const_vars_t vars)
01527 {
01528 stp_curve_t curve;
01529 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01530 double k_lower = 0.0;
01531 double k_upper = 1.0;
01532 double k_gamma = 1.0;
01533 double i_k_gamma = 1.0;
01534 double *tmp_data = stpi_malloc(sizeof(double) * lut->steps);
01535 int i;
01536
01537 if (stp_check_float_parameter(vars, "GCRUpper", STP_PARAMETER_DEFAULTED))
01538 k_upper = stp_get_float_parameter(vars, "GCRUpper");
01539 if (stp_check_float_parameter(vars, "GCRLower", STP_PARAMETER_DEFAULTED))
01540 k_lower = stp_get_float_parameter(vars, "GCRLower");
01541 if (stp_check_float_parameter(vars, "BlackGamma", STP_PARAMETER_DEFAULTED))
01542 k_gamma = stp_get_float_parameter(vars, "BlackGamma");
01543 k_upper *= lut->steps;
01544 k_lower *= lut->steps;
01545
01546 if (k_lower > lut->steps)
01547 k_lower = lut->steps;
01548 if (k_upper < k_lower)
01549 k_upper = k_lower + 1;
01550 i_k_gamma = 1.0 / k_gamma;
01551
01552 for (i = 0; i < k_lower; i ++)
01553 tmp_data[i] = 0;
01554 if (k_upper < lut->steps)
01555 {
01556 for (i = ceil(k_lower); i < k_upper; i ++)
01557 {
01558 double where = (i - k_lower) / (k_upper - k_lower);
01559 double g1 = pow(where, i_k_gamma);
01560 double g2 = 1.0 - pow(1.0 - where, k_gamma);
01561 double value = (g1 > g2 ? g1 : g2);
01562 tmp_data[i] = 65535.0 * k_upper * value / (double) (lut->steps - 1);
01563 tmp_data[i] = floor(tmp_data[i] + .5);
01564 }
01565 for (i = ceil(k_upper); i < lut->steps; i ++)
01566 tmp_data[i] = 65535.0 * i / (double) (lut->steps - 1);
01567 }
01568 else if (k_lower < lut->steps)
01569 for (i = ceil(k_lower); i < lut->steps; i ++)
01570 {
01571 double where = (i - k_lower) / (k_upper - k_lower);
01572 double g1 = pow(where, i_k_gamma);
01573 double g2 = 1.0 - pow(1.0 - where, k_gamma);
01574 double value = (g1 > g2 ? g1 : g2);
01575 tmp_data[i] = 65535.0 * lut->steps * value / (double) (lut->steps - 1);
01576 tmp_data[i] = floor(tmp_data[i] + .5);
01577 }
01578 curve = stp_curve_create(STP_CURVE_WRAP_NONE);
01579 stp_curve_set_bounds(curve, 0, 65535);
01580 if (! stp_curve_set_data(curve, lut->steps, tmp_data))
01581 {
01582 stpi_eprintf(vars, "set curve data failed!\n");
01583 stpi_abort();
01584 }
01585 stpi_free(tmp_data);
01586 return curve;
01587 }
01588
01589 static stp_curve_t
01590 compute_a_curve(stp_curve_t curve, double c_gamma, lut_t *lut)
01591 {
01592 double *tmp = stpi_malloc(sizeof(double) * lut->steps);
01593 double pivot = .25;
01594 double ipivot = 1.0 - pivot;
01595 double xcontrast = pow(lut->contrast, lut->contrast);
01596 double xgamma = pow(pivot, lut->screen_gamma);
01597 int i;
01598 int isteps = lut->steps;
01599 if (isteps > 256)
01600 isteps = 256;
01601 for (i = 0; i < isteps; i ++)
01602 {
01603 double temp_pixel, pixel;
01604 pixel = (double) i / (double) (isteps - 1);
01605
01606 if (lut->input_color_model == COLOR_MODEL_CMY)
01607 pixel = 1.0 - pixel;
01608
01609
01610
01611
01612 if (pixel >= .5)
01613 temp_pixel = 1.0 - pixel;
01614 else
01615 temp_pixel = pixel;
01616 if (lut->contrast > 3.99999)
01617 {
01618 if (temp_pixel < .5)
01619 temp_pixel = 0;
01620 else
01621 temp_pixel = 1;
01622 }
01623 if (temp_pixel <= .000001 && lut->contrast <= .0001)
01624 temp_pixel = .5;
01625 else if (temp_pixel > 1)
01626 temp_pixel = .5 * pow(2 * temp_pixel, xcontrast);
01627 else if (temp_pixel < 1)
01628 {
01629 if (lut->linear_contrast_adjustment)
01630 temp_pixel = 0.5 -
01631 ((0.5 - .5 * pow(2 * temp_pixel, lut->contrast)) * lut->contrast);
01632 else
01633 temp_pixel = 0.5 -
01634 ((0.5 - .5 * pow(2 * temp_pixel, lut->contrast)));
01635 }
01636 if (temp_pixel > .5)
01637 temp_pixel = .5;
01638 else if (temp_pixel < 0)
01639 temp_pixel = 0;
01640 if (pixel < .5)
01641 pixel = temp_pixel;
01642 else
01643 pixel = 1 - temp_pixel;
01644
01645
01646
01647
01648 if (lut->brightness < 1)
01649 pixel = pixel * lut->brightness;
01650 else
01651 pixel = 1 - ((1 - pixel) * (2 - lut->brightness));
01652
01653
01654
01655
01656
01657 pixel = 1.0 -
01658 (1.0 / (1.0 - xgamma)) *
01659 (pow(pivot + ipivot * pixel, lut->screen_gamma) - xgamma);
01660
01661
01662
01663
01664 if (pixel < 0.0)
01665 pixel = 0.0;
01666 else if (pixel > 1.0)
01667 pixel = 1.0;
01668
01669 if (pixel > .9999 && c_gamma < .00001)
01670 pixel = 0;
01671 else
01672 pixel = 1 - pow(1 - pixel, c_gamma);
01673
01674
01675
01676
01677
01678 pixel = 65535 * pow(pixel, lut->print_gamma);
01679 if (lut->output_color_model == COLOR_MODEL_RGB)
01680 pixel = 65535 - pixel;
01681
01682 if (pixel <= 0.0)
01683 tmp[i] = 0;
01684 else if (pixel >= 65535.0)
01685 tmp[i] = 65535;
01686 else
01687 tmp[i] = (pixel);
01688 tmp[i] = floor(tmp[i] + 0.5);
01689 }
01690 stp_curve_set_data(curve, isteps, tmp);
01691 if (isteps != lut->steps)
01692 stp_curve_resample(curve, lut->steps);
01693 stpi_free(tmp);
01694 return curve;
01695 }
01696
01697 static void
01698 invert_curve(stp_curve_t curve, int in_model, int out_model)
01699 {
01700 double lo, hi;
01701 int i;
01702 size_t count;
01703 const double *data = stp_curve_get_data(curve, &count);
01704 double f_gamma = stp_curve_get_gamma(curve);
01705 double *tmp_data;
01706
01707 stp_curve_get_bounds(curve, &lo, &hi);
01708
01709 if (f_gamma)
01710 stp_curve_set_gamma(curve, -f_gamma);
01711 else
01712 {
01713 tmp_data = stpi_malloc(sizeof(double) * count);
01714 for (i = 0; i < count; i++)
01715 tmp_data[i] = data[count - i - 1];
01716 stp_curve_set_data(curve, count, tmp_data);
01717 stpi_free(tmp_data);
01718 }
01719 if (in_model == out_model)
01720 {
01721 stp_curve_rescale(curve, -1, STP_CURVE_COMPOSE_MULTIPLY,
01722 STP_CURVE_BOUNDS_RESCALE);
01723 stp_curve_rescale(curve, lo + hi, STP_CURVE_COMPOSE_ADD,
01724 STP_CURVE_BOUNDS_RESCALE);
01725 }
01726 }
01727
01728 static void
01729 compute_one_lut(stp_curve_t lut_curve, stp_const_curve_t curve,
01730 double density, lut_t *lut)
01731 {
01732 if (curve)
01733 {
01734 stp_curve_copy(lut_curve, curve);
01735 invert_curve(lut_curve, lut->input_color_model, lut->output_color_model);
01736 stp_curve_rescale(lut_curve, 65535.0, STP_CURVE_COMPOSE_MULTIPLY,
01737 STP_CURVE_BOUNDS_RESCALE);
01738 stp_curve_resample(lut_curve, lut->steps);
01739 }
01740 else
01741 {
01742 compute_a_curve(lut_curve, density, lut);
01743 }
01744 }
01745
01746 static void
01747 initialize_cmyk_lut(stp_const_vars_t vars, size_t count)
01748 {
01749 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01750 if (!lut->cmyk_lut)
01751 {
01752 int i;
01753 double print_gamma = stp_get_float_parameter(vars, "Gamma");
01754 lut->cmyk_lut = stpi_malloc(sizeof(unsigned short) * 256);
01755
01756 for (i = 0; i < count; i ++)
01757 lut->cmyk_lut[i] =
01758 (65535.0 * pow((double)i / (double) (count - 1), print_gamma)) + 0.5;
01759 }
01760 }
01761
01762 static void
01763 initialize_gcr_curve(stp_const_vars_t vars)
01764 {
01765 lut_t *lut = (lut_t *)(stpi_get_component_data(vars, "Color"));
01766 if (!lut->gcr_curve)
01767 {
01768 if (stp_check_curve_parameter(vars, "GCRCurve", STP_PARAMETER_DEFAULTED))
01769 {
01770 double data;
01771 size_t count;
01772 int i;
01773 lut->gcr_curve =
01774 stp_curve_create_copy(stp_get_curve_parameter(vars, "GCRCurve"));
01775 stp_curve_resample(lut->gcr_curve, lut->steps);
01776 count = stp_curve_count_points(lut->gcr_curve);
01777 stp_curve_set_bounds(lut->gcr_curve, 0.0, 65535.0);
01778 for (i = 0; i < count; i++)
01779 {
01780 stp_curve_get_point(lut->gcr_curve, i, &data);
01781 data = 65535.0 * data * (double) i / (count - 1);
01782 stp_curve_set_point(lut->gcr_curve, i, data);
01783 }
01784 }
01785 else
01786 lut->gcr_curve = compute_gcr_curve(vars);
01787 }
01788 }
01789
01790 static void
01791 initialize_composite_curve(stp_const_vars_t v, size_t count)
01792 {
01793 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
01794 if (!lut->composite)
01795 {
01796 stp_const_curve_t composite_curve = NULL;
01797 if (stp_get_curve_parameter_active(v, "CompositeCurve") >=
01798 stp_get_float_parameter_active(v, "Gamma"))
01799 composite_curve = stp_get_curve_parameter(v, "CompositeCurve");
01800 compute_one_lut(lut->composite, composite_curve, 1.0, lut);
01801 }
01802 }
01803
01804 static void
01805 initialize_nothing(stp_const_vars_t v, size_t count)
01806 {
01807 }
01808
01809 static void
01810 initialize_color_curves(stp_const_vars_t v, size_t count)
01811 {
01812 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
01813 if (!lut->cyan)
01814 {
01815 stp_const_curve_t cyan_curve = NULL;
01816 stp_const_curve_t magenta_curve = NULL;
01817 stp_const_curve_t yellow_curve = NULL;
01818 double cyan = 1.0;
01819 double magenta = 1.0;
01820 double yellow = 1.0;
01821 stp_const_curve_t hue = NULL;
01822 stp_const_curve_t lum = NULL;
01823 stp_const_curve_t sat = NULL;
01824 stp_const_curve_t black_curve = NULL;
01825
01826 if (stp_check_float_parameter(v, "CyanGamma", STP_PARAMETER_DEFAULTED))
01827 cyan = stp_get_float_parameter(v, "CyanGamma");
01828 if (stp_check_float_parameter(v, "MagentaGamma", STP_PARAMETER_DEFAULTED))
01829 magenta = stp_get_float_parameter(v, "MagentaGamma");
01830 if (stp_check_float_parameter(v, "YellowGamma", STP_PARAMETER_DEFAULTED))
01831 yellow = stp_get_float_parameter(v, "YellowGamma");
01832
01833 if (stp_check_curve_parameter(v, "HueMap", STP_PARAMETER_DEFAULTED))
01834 hue = stp_get_curve_parameter(v, "HueMap");
01835 if (stp_check_curve_parameter(v, "LumMap", STP_PARAMETER_DEFAULTED))
01836 lum = stp_get_curve_parameter(v, "LumMap");
01837 if (stp_check_curve_parameter(v, "SatMap", STP_PARAMETER_DEFAULTED))
01838 sat = stp_get_curve_parameter(v, "SatMap");
01839 if (stp_get_curve_parameter_active(v, "CyanCurve") >=
01840 stp_get_float_parameter_active(v, "Cyan"))
01841 cyan_curve = stp_get_curve_parameter(v, "CyanCurve");
01842 if (stp_get_curve_parameter_active(v, "MagentaCurve") >=
01843 stp_get_float_parameter_active(v, "Magenta"))
01844 magenta_curve = stp_get_curve_parameter(v, "MagentaCurve");
01845 if (stp_get_curve_parameter_active(v, "YellowCurve") >=
01846 stp_get_float_parameter_active(v, "Yellow"))
01847 yellow_curve = stp_get_curve_parameter(v, "YellowCurve");
01848 if (stp_check_curve_parameter(v, "BlackCurve", STP_PARAMETER_DEFAULTED))
01849 black_curve = stp_get_curve_parameter(v, "BlackCurve");
01850
01851
01852
01853 if (hue)
01854 lut->hue_map = stp_curve_create_copy(hue);
01855 if (lum)
01856 lut->lum_map = stp_curve_create_copy(lum);
01857 if (sat)
01858 lut->sat_map = stp_curve_create_copy(sat);
01859 if (black_curve)
01860 stp_curve_copy(lut->black, black_curve);
01861 else
01862 stp_curve_copy(lut->black, color_curve_bounds);
01863 stp_curve_rescale(lut->black, 65535.0, STP_CURVE_COMPOSE_MULTIPLY,
01864 STP_CURVE_BOUNDS_RESCALE);
01865 stp_curve_resample(lut->black, count);
01866
01867 compute_one_lut(lut->cyan, cyan_curve, cyan, lut);
01868 compute_one_lut(lut->magenta, magenta_curve, magenta, lut);
01869 compute_one_lut(lut->yellow, yellow_curve, yellow, lut);
01870 }
01871 }
01872
01873 static void
01874 stpi_compute_lut(stp_vars_t v, size_t steps)
01875 {
01876 lut_t *lut = allocate_lut();
01877
01878 lut->input_color_model = stp_get_input_color_model(v);
01879 lut->output_color_model = stpi_get_output_color_model(v);
01880 lut->output_type = stp_get_output_type(v);
01881 lut->steps = steps;
01882 lut->linear_contrast_adjustment = 0;
01883 lut->print_gamma = 1.0;
01884 lut->app_gamma = 1.0;
01885 lut->contrast = 1.0;
01886 lut->brightness = 1.0;
01887
01888 if (stp_check_boolean_parameter(v, "LinearContrast", STP_PARAMETER_DEFAULTED))
01889 lut->linear_contrast_adjustment =
01890 stp_get_boolean_parameter(v, "LinearContrast");
01891 if (stp_check_float_parameter(v, "Gamma", STP_PARAMETER_DEFAULTED))
01892 lut->print_gamma = stp_get_float_parameter(v, "Gamma");
01893 if (stp_check_float_parameter(v, "Contrast", STP_PARAMETER_DEFAULTED))
01894 lut->contrast = stp_get_float_parameter(v, "Contrast");
01895 if (stp_check_float_parameter(v, "Brightness", STP_PARAMETER_DEFAULTED))
01896 lut->brightness = stp_get_float_parameter(v, "Brightness");
01897
01898 if (stp_check_float_parameter(v, "AppGamma", STP_PARAMETER_ACTIVE))
01899 lut->app_gamma = stp_get_float_parameter(v, "AppGamma");
01900 lut->screen_gamma = lut->app_gamma / 4.0;
01901 lut->steps = steps;
01902 stpi_allocate_component_data(v, "Color", copy_lut, free_lut, lut);
01903
01904 stpi_dprintf(STPI_DBG_LUT, v, "stpi_compute_lut\n");
01905 stpi_dprintf(STPI_DBG_LUT, v, " print_gamma %.3f\n", lut->print_gamma);
01906 stpi_dprintf(STPI_DBG_LUT, v, " contrast %.3f\n", lut->contrast);
01907 stpi_dprintf(STPI_DBG_LUT, v, " brightness %.3f\n", lut->brightness);
01908 stpi_dprintf(STPI_DBG_LUT, v, " screen_gamma %.3f\n", lut->screen_gamma);
01909 }
01910
01911 #define SET_COLORFUNC(cfunc, initfunc) \
01912 if (!cfunc) \
01913 stpi_erprintf("No colorfunc chosen "); \
01914 stpi_dprintf(STPI_DBG_COLORFUNC, v, \
01915 "at line %d stp_choose_colorfunc(type %d bpp %d) ==> %s, %d\n", \
01916 __LINE__, lut->output_type, image_bpp, #cfunc, \
01917 lut->out_channels); \
01918 lut->colorfunc = cfunc; \
01919 if (initfunc) \
01920 (initfunc)(v, steps); \
01921 break
01922
01923 static void
01924 setup_cmyk_output(stp_vars_t v, stp_image_t *image, size_t steps,
01925 int itype)
01926 {
01927 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
01928 int image_bpp = stpi_image_bpp(image);
01929 switch (image_bpp)
01930 {
01931 case 1:
01932 switch (itype)
01933 {
01934 case 3:
01935 SET_COLORFUNC(gray_8_to_kcmy_line_art, initialize_nothing);
01936 case 2:
01937 case 1:
01938 case 0:
01939 SET_COLORFUNC(gray_8_to_kcmy, initialize_color_curves);
01940 default:
01941 SET_COLORFUNC(NULL, initialize_nothing);
01942 }
01943 break;
01944 case 2:
01945 switch (itype)
01946 {
01947 case 3:
01948 SET_COLORFUNC(gray_16_to_kcmy_line_art, initialize_nothing);
01949 case 2:
01950 case 1:
01951 case 0:
01952 SET_COLORFUNC(gray_16_to_kcmy, initialize_color_curves);
01953 default:
01954 SET_COLORFUNC(NULL, initialize_nothing);
01955 }
01956 break;
01957 case 3:
01958 switch (itype)
01959 {
01960 case 3:
01961 SET_COLORFUNC(rgb_8_to_kcmy_line_art, initialize_nothing);
01962 case 2:
01963 case 1:
01964 SET_COLORFUNC(rgb_8_to_kcmy, initialize_color_curves);
01965 case 0:
01966 SET_COLORFUNC(fast_rgb_8_to_kcmy, initialize_color_curves);
01967 default:
01968 SET_COLORFUNC(NULL, initialize_nothing);
01969 }
01970 break;
01971 case 6:
01972 switch (itype)
01973 {
01974 case 3:
01975 SET_COLORFUNC(rgb_16_to_kcmy_line_art, initialize_nothing);
01976 case 2:
01977 case 1:
01978 SET_COLORFUNC(rgb_16_to_kcmy, initialize_color_curves);
01979 case 0:
01980 SET_COLORFUNC(fast_rgb_16_to_kcmy, initialize_color_curves);
01981 default:
01982 SET_COLORFUNC(NULL, initialize_nothing);
01983 }
01984 break;
01985 case 4:
01986 switch (itype)
01987 {
01988 case 3:
01989 SET_COLORFUNC(cmyk_8_to_kcmy_line_art, initialize_nothing);
01990 case 2:
01991 case 1:
01992 case 0:
01993 SET_COLORFUNC(cmyk_8_to_kcmy, initialize_cmyk_lut);
01994 default:
01995 SET_COLORFUNC(NULL, initialize_nothing);
01996 }
01997 break;
01998 case 8:
01999 switch (itype)
02000 {
02001 case 3:
02002 SET_COLORFUNC(cmyk_16_to_kcmy_line_art, initialize_nothing);
02003 case 2:
02004 case 1:
02005 case 0:
02006 SET_COLORFUNC(cmyk_16_to_kcmy_raw, initialize_nothing);
02007 default:
02008 SET_COLORFUNC(NULL, initialize_nothing);
02009 }
02010 break;
02011 default:
02012 SET_COLORFUNC(NULL, initialize_nothing);
02013 }
02014 }
02015
02016 static void
02017 setup_color_output(stp_vars_t v, stp_image_t *image, size_t steps,
02018 int itype)
02019 {
02020 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
02021 int image_bpp = stpi_image_bpp(image);
02022 switch (image_bpp)
02023 {
02024 case 1:
02025 switch (itype)
02026 {
02027 case 3:
02028 SET_COLORFUNC(gray_8_to_rgb_line_art, initialize_nothing);
02029 case 2:
02030 case 1:
02031 case 0:
02032 SET_COLORFUNC(gray_8_to_rgb, initialize_color_curves);
02033 default:
02034 SET_COLORFUNC(NULL, initialize_nothing);
02035 }
02036 break;
02037 case 2:
02038 switch (itype)
02039 {
02040 case 3:
02041 SET_COLORFUNC(gray_16_to_rgb_line_art, initialize_nothing);
02042 case 2:
02043 case 1:
02044 case 0:
02045 SET_COLORFUNC(gray_16_to_rgb, initialize_color_curves);
02046 default:
02047 SET_COLORFUNC(NULL, initialize_nothing);
02048 }
02049 break;
02050 case 3:
02051 switch (itype)
02052 {
02053 case 3:
02054 SET_COLORFUNC(rgb_8_to_rgb_line_art, initialize_nothing);
02055 case 2:
02056 case 1:
02057 SET_COLORFUNC(rgb_16_to_rgb, initialize_color_curves);
02058 case 0:
02059 SET_COLORFUNC(fast_rgb_16_to_rgb, initialize_color_curves);
02060 default:
02061 SET_COLORFUNC(NULL, initialize_nothing);
02062 }
02063 break;
02064 case 6:
02065 switch (itype)
02066 {
02067 case 3:
02068 SET_COLORFUNC(rgb_16_to_rgb_line_art, initialize_nothing);
02069 case 2:
02070 case 1:
02071 SET_COLORFUNC(rgb_16_to_rgb, initialize_color_curves);
02072 case 0:
02073 SET_COLORFUNC(fast_rgb_16_to_rgb, initialize_color_curves);
02074 default:
02075 SET_COLORFUNC(NULL, initialize_nothing);
02076 }
02077 break;
02078 default:
02079 SET_COLORFUNC(NULL, initialize_nothing);
02080 }
02081 }
02082
02083 static void
02084 setup_gray_output(stp_vars_t v, stp_image_t *image, size_t steps,
02085 int itype)
02086 {
02087 lut_t *lut = (lut_t *)(stpi_get_component_data(v, "Color"));
02088 int image_bpp = stpi_image_bpp(image);
02089 if (itype == 3)
02090 {
02091 switch (image_bpp)
02092 {
02093 case 1:
02094 SET_COLORFUNC(gray_8_to_gray_line_art, initialize_nothing);
02095 case 2:
02096 SET_COLORFUNC(gray_16_to_gray_line_art, initialize_nothing);
02097 case 3:
02098 SET_COLORFUNC(color_8_to_gray_line_art, initialize_nothing);
02099 case 6:
02100 SET_COLORFUNC(color_16_to_gray_line_art, initialize_nothing);
02101 case 4:
02102 SET_COLORFUNC(cmyk_8_to_gray_line_art, initialize_nothing);
02103 case 8:
02104 SET_COLORFUNC(cmyk_16_to_gray_line_art, initialize_nothing);
02105 default:
02106 SET_COLORFUNC(NULL, initialize_nothing);
02107 }
02108 }
02109 else if (itype >= 0 && itype <= 2)
02110 {
02111 switch (image_bpp)
02112 {
02113 case 1:
02114 SET_COLORFUNC(gray_8_to_gray, initialize_composite_curve);
02115 case 2:
02116 SET_COLORFUNC(gray_16_to_gray, initialize_composite_curve);
02117 case 3:
02118 SET_COLORFUNC(color_8_to_gray, initialize_composite_curve);
02119 case 6:
02120 SET_COLORFUNC(color_16_to_gray, initialize_composite_curve);
02121 case 4:
02122 SET_COLORFUNC(cmyk_8_to_gray, initialize_composite_curve);
02123 case 8:
02124 SET_COLORFUNC(cmyk_16_to_gray, initialize_composite_curve);
02125 default:
02126 SET_COLORFUNC(NULL, initialize_nothing);
02127 }
02128 }
02129 else
02130 {
02131 do
02132 {
02133 SET_COLORFUNC(NULL, initialize_nothing);
02134 }
02135 while (0);
02136 }
02137 }
02138
02139 static int
02140 stpi_color_traditional_init(stp_vars_t v,
02141 stp_image_t *image,
02142 size_t steps)
02143 {
02144 const char *image_type = stp_get_string_parameter(v, "ImageType");
02145 const char *color_correction = stp_get_string_parameter(v, "ColorCorrection");
02146 int itype = 0;
02147 int image_bpp = stpi_image_bpp(image);
02148 lut_t *lut;
02149 if (steps != 256 && steps != 65536)
02150 return -1;
02151
02152 stpi_compute_lut(v, steps);
02153 lut = (lut_t *)(stpi_get_component_data(v, "Color"));
02154 lut->image_bpp = image_bpp;
02155 lut->image_width = stpi_image_width(image);
02156 if (image_type && strcmp(image_type, "None") != 0)
02157 {
02158 if (strcmp(image_type, "Text") == 0)
02159 itype = 3;
02160 else
02161 itype = 2;
02162 }
02163 else if (color_correction)
02164 {
02165 if (strcmp(color_correction, "Uncorrected") == 0)
02166 itype = 0;
02167 else if (strcmp(color_correction, "Bright") == 0)
02168 itype = 1;
02169 else if (strcmp(color_correction, "Accurate") == 0)
02170 itype = 2;
02171 else if (strcmp(color_correction, "None") == 0)
02172 itype = 2;
02173 else if (strcmp(color_correction, "Threshold") == 0)
02174 itype = 3;
02175 }
02176 switch (lut->output_type)
02177 {
02178 case OUTPUT_RAW_CMYK:
02179 lut->out_channels = 4;
02180 setup_cmyk_output(v, image, steps, itype);
02181 break;
02182 case OUTPUT_COLOR:
02183 lut->out_channels = 3;
02184 setup_color_output(v, image, steps, itype);
02185 break;
02186 case OUTPUT_RAW_PRINTER:
02187 if ((image_bpp & 1) || image_bpp < 2 || image_bpp > 64)
02188 {
02189 SET_COLORFUNC(NULL, initialize_nothing);
02190 }
02191 lut->out_channels = image_bpp / 2;
02192 SET_COLORFUNC(raw_to_raw, initialize_nothing);
02193 case OUTPUT_GRAY:
02194 lut->out_channels = 1;
02195 setup_gray_output(v, image, steps, itype);
02196 break;
02197 default:
02198 SET_COLORFUNC(NULL, initialize_nothing);
02199 }
02200 lut->in_data = stpi_malloc(stpi_image_width(image) * image_bpp);
02201 memset(lut->in_data, 0, stpi_image_width(image) * image_bpp);
02202 return lut->out_channels;
02203 }
02204
02205 static void
02206 initialize_standard_curves(void)
02207 {
02208 if (!standard_curves_initialized)
02209 {
02210 int i;
02211 hue_map_bounds = stp_curve_create_from_string
02212 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
02213 "<gimp-print>\n"
02214 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
02215 "<sequence count=\"2\" lower-bound=\"-6\" upper-bound=\"6\">\n"
02216 "0 0\n"
02217 "</sequence>\n"
02218 "</curve>\n"
02219 "</gimp-print>");
02220 lum_map_bounds = stp_curve_create_from_string
02221 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
02222 "<gimp-print>\n"
02223 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
02224 "<sequence count=\"2\" lower-bound=\"0\" upper-bound=\"4\">\n"
02225 "1 1\n"
02226 "</sequence>\n"
02227 "</curve>\n"
02228 "</gimp-print>");
02229 sat_map_bounds = stp_curve_create_from_string
02230 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
02231 "<gimp-print>\n"
02232 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
02233 "<sequence count=\"2\" lower-bound=\"0\" upper-bound=\"4\">\n"
02234 "1 1\n"
02235 "</sequence>\n"
02236 "</curve>\n"
02237 "</gimp-print>");
02238 color_curve_bounds = stp_curve_create_from_string
02239 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
02240 "<gimp-print>\n"
02241 "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"1.0\">\n"
02242 "<sequence count=\"0\" lower-bound=\"0\" upper-bound=\"1\">\n"
02243 "</sequence>\n"
02244 "</curve>\n"
02245 "</gimp-print>");
02246 gcr_curve_bounds = stp_curve_create_from_string
02247 ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
02248 "<gimp-print>\n"
02249 "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"0.0\">\n"
02250 "<sequence count=\"2\" lower-bound=\"0\" upper-bound=\"1\">\n"
02251 "1 1\n"
02252 "</sequence>\n"
02253 "</curve>\n"
02254 "</gimp-print>");
02255 for (i = 0; i < curve_parameter_count; i++)
02256 curve_parameters[i].param.deflt.curve =
02257 *(curve_parameters[i].defval);
02258 standard_curves_initialized = 1;
02259 }
02260 }
02261
02262 static stp_parameter_list_t
02263 stpi_color_traditional_list_parameters(stp_const_vars_t v)
02264 {
02265 stpi_list_t *ret = stp_parameter_list_create();
02266 int i;
02267 initialize_standard_curves();
02268 for (i = 0; i < float_parameter_count; i++)
02269 stp_parameter_list_add_param(ret, &(float_parameters[i].param));
02270 for (i = 0; i < curve_parameter_count; i++)
02271 stp_parameter_list_add_param(ret, &(curve_parameters[i].param));
02272 return ret;
02273 }
02274
02275 static void
02276 stpi_color_traditional_describe_parameter(stp_const_vars_t v,
02277 const char *name,
02278 stp_parameter_t *description)
02279 {
02280 int i;
02281 description->p_type = STP_PARAMETER_TYPE_INVALID;
02282 initialize_standard_curves();
02283 if (name == NULL)
02284 return;
02285 for (i = 0; i < float_parameter_count; i++)
02286 {
02287 const float_param_t *param = &(float_parameters[i]);
02288 if (strcmp(name, param->param.name) == 0)
02289 {
02290 stpi_fill_parameter_settings(description, &(param->param));
02291 if (param->color_only && stp_get_output_type(v) == OUTPUT_GRAY)
02292 description->is_active = 0;
02293 if (stp_check_string_parameter(v, "ImageType", STP_PARAMETER_ACTIVE) &&
02294 strcmp(stp_get_string_parameter(v, "ImageType"), "None") != 0 &&
02295 description->p_level > STP_PARAMETER_LEVEL_BASIC)
02296 description->is_active = 0;
02297 switch (param->param.p_type)
02298 {
02299 case STP_PARAMETER_TYPE_BOOLEAN:
02300 description->deflt.boolean = (int) param->defval;
02301 case STP_PARAMETER_TYPE_DOUBLE:
02302 description->bounds.dbl.upper = param->max;
02303 description->bounds.dbl.lower = param->min;
02304 description->deflt.dbl = param->defval;
02305 if (strcmp(name, "InkLimit") == 0)
02306 {
02307 stp_parameter_t ink_limit_desc;
02308 stp_describe_parameter(v, "InkChannels", &ink_limit_desc);
02309 if (ink_limit_desc.p_type == STP_PARAMETER_TYPE_INT)
02310 {
02311 if (ink_limit_desc.deflt.integer > 1)
02312 {
02313 description->bounds.dbl.upper =
02314 ink_limit_desc.deflt.integer;
02315 description->deflt.dbl =
02316 ink_limit_desc.deflt.integer;
02317 }
02318 else
02319 description->is_active = 0;
02320 }
02321 stp_parameter_description_free(&ink_limit_desc);
02322 }
02323 break;
02324 case STP_PARAMETER_TYPE_STRING_LIST:
02325 if (!strcmp(param->param.name, "ColorCorrection"))
02326 {
02327 description->bounds.str = stp_string_list_create();
02328 stp_string_list_add_string
02329 (description->bounds.str, "None", _("Default"));
02330 stp_string_list_add_string
02331 (description->bounds.str, "Accurate", _("High Accuracy"));
02332 stp_string_list_add_string
02333 (description->bounds.str, "Bright", _("Bright"));
02334 stp_string_list_add_string
02335 (description->bounds.str, "Threshold", _("Threshold"));
02336 stp_string_list_add_string
02337 (description->bounds.str, "Uncorrected", _("Uncorrected"));
02338 description->deflt.str = "None";
02339 }
02340 break;
02341 default:
02342 break;
02343 }
02344 return;
02345 }
02346 }
02347 for (i = 0; i < curve_parameter_count; i++)
02348 {
02349 curve_param_t *param = &(curve_parameters[i]);
02350 if (strcmp(name, param->param.name) == 0)
02351 {
02352 description->is_active = 1;
02353 stpi_fill_parameter_settings(description, &(param->param));
02354 if (param->color_only && stp_get_output_type(v) == OUTPUT_GRAY)
02355 description->is_active = 0;
02356 if (stp_check_string_parameter(v, "ImageType", STP_PARAMETER_ACTIVE) &&
02357 strcmp(stp_get_string_parameter(v, "ImageType"), "None") != 0 &&
02358 description->p_level > STP_PARAMETER_LEVEL_BASIC)
02359 description->is_active = 0;
02360 if (param->hsl_only &&
02361 stp_check_string_parameter(v, "ColorCorrection",
02362 STP_PARAMETER_DEFAULTED) &&
02363 strcmp(stp_get_string_parameter(v, "ColorCorrection"),
02364 "Uncorrected") == 0)
02365 description->is_active = 0;
02366 switch (param->param.p_type)
02367 {
02368 case STP_PARAMETER_TYPE_CURVE:
02369 description->deflt.curve = *(param->defval);
02370 description->bounds.curve =
02371 stp_curve_create_copy(*(param->defval));
02372 break;
02373 default:
02374 break;
02375 }
02376 return;
02377 }
02378 }
02379 }
02380
02381
02382 static const stpi_colorfuncs_t stpi_color_traditional_colorfuncs =
02383 {
02384 &stpi_color_traditional_init,
02385 &stpi_color_traditional_get_row,
02386 &stpi_color_traditional_list_parameters,
02387 &stpi_color_traditional_describe_parameter
02388 };
02389
02390 static const stpi_internal_color_t stpi_color_traditional_module_data =
02391 {
02392 COOKIE_COLOR,
02393 "traditional",
02394 N_("Traditional Gimp-Print color conversion"),
02395 &stpi_color_traditional_colorfuncs
02396 };
02397
02398
02399 static int
02400 color_traditional_module_init(void)
02401 {
02402 return stpi_color_register(&stpi_color_traditional_module_data);
02403 }
02404
02405
02406 static int
02407 color_traditional_module_exit(void)
02408 {
02409 return stpi_color_unregister(&stpi_color_traditional_module_data);
02410 }
02411
02412
02413
02414 #define stpi_module_version color_traditional_LTX_stpi_module_version
02415 #define stpi_module_data color_traditional_LTX_stpi_module_data
02416
02417 stpi_module_version_t stpi_module_version = {0, 0};
02418
02419 stpi_module_t stpi_module_data =
02420 {
02421 "traditional",
02422 VERSION,
02423 "Traditional Gimp-Print color conversion",
02424 STPI_MODULE_CLASS_COLOR,
02425 NULL,
02426 color_traditional_module_init,
02427 color_traditional_module_exit,
02428 (void *) &stpi_color_traditional_module_data
02429 };