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