Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/print-color-x.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: print-color.c,v 1.100 2003/09/29 03:06:28 rlk Exp $"
00003  *
00004  *   Gimp-Print color management module - traditional Gimp-Print algorithm.
00005  *
00006  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
00007  *      Robert Krawitz (rlk@alum.mit.edu)
00008  *
00009  *   This program is free software; you can redistribute it and/or modify it
00010  *   under the terms of the GNU General Public License as published by the Free
00011  *   Software Foundation; either version 2 of the License, or (at your option)
00012  *   any later version.
00013  *
00014  *   This program is distributed in the hope that it will be useful, but
00015  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00016  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017  *   for more details.
00018  *
00019  *   You should have received a copy of the GNU General Public License
00020  *   along with this program; if not, write to the Free Software
00021  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022  */
00023 
00024 /*
00025  * This file must include only standard C header files.  The core code must
00026  * compile on generic platforms that don't support glib, gimp, gtk, etc.
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 /* Color conversion function */
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   /* Need to think this through a bit more -- rlk 20030712 */
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  * RGB to grayscale luminance constants...
00313  */
00314 
00315 #define LUM_RED         31
00316 #define LUM_GREEN       61
00317 #define LUM_BLUE        8
00318 
00319 /* rgb/hsl conversions taken from Gimp common/autostretch_hsv.c */
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)  /* Suggested by Eugene Anikin <eugene@anikin.com> */
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  * 'gray_to_gray()' - Convert grayscale image data to grayscale (brightness
00451  *                    adjusted).
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  * 'rgb_to_gray()' - Convert RGB image data to grayscale.
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                       s *= isadj * sisadj;
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 /*                    s *= sqrt(isadj); */
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  * 'rgb_to_rgb()' - Convert rgb image data to RGB.
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  * 'gray_to_rgb()' - Convert gray image data to RGB.
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  * 'rgb_to_rgb()' - Convert rgb image data to RGB.
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  * 'gray_to_rgb()' - Convert gray image data to RGB.
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); /* 1 or 257 */
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;         /* Don't copy working storage */
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        * First, correct contrast
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        * Second, do brightness
01871        */
01872       if (l->brightness < 1)
01873         pixel = pixel * l->brightness;
01874       else
01875         pixel = 1 - ((1 - pixel) * (2 - l->brightness));
01876 
01877       /*
01878        * Third, correct for the screen gamma
01879        */
01880 
01881       pixel = 1.0 -
01882         (1.0 / (1.0 - xgamma)) *
01883         (pow(pivot + ipivot * pixel, l->screen_gamma) - xgamma);
01884 
01885       /*
01886        * Third, fix up cyan, magenta, yellow values
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        * Finally, fix up print gamma and scale
01900        */
01901 
01902       pixel = 65535 * pow(pixel, l->print_gamma);       /* was + 0.5 here */
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);                     /* rounding is done here */
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; /* "Empirical" */
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    * TODO check that these are wraparound curves and all that
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 /* Module header */
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   };

Generated on Wed May 12 20:21:30 2004 for libgimpprint API Reference by doxygen1.2.17