/* * * Gimp-Print color management module - traditional Gimp-Print algorithm. * * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and * Robert Krawitz (rlk@alum.mit.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * This file must include only standard C header files. The core code must * compile on generic platforms that don't support glib, gimp, gtk, etc. */ #ifdef HAVE_CONFIG_H #include #endif #include #include "gutenprint-internal.h" #include #include #include #ifdef HAVE_LIMITS_H #include #endif #include #include "color-conversion.h" #ifdef __GNUC__ #define inline __inline__ // There's no reason to inline the main loop with the dispatch // functions only to fail inlining of calls from the inner loop. // Also, inlining the main loop makes it hard to debug because we lose // context of which print function is called. #define NOINLINE __attribute__ ((noinline)) #else $define NOINLINE #endif #define CFUNC static unsigned NOINLINE /* * RGB to grayscale luminance constants... */ #define LUM_RED 31 #define LUM_GREEN 61 #define LUM_BLUE 8 /* rgb/hsl conversions taken from Gimp common/autostretch_hsv.c */ #define FMAX(a, b) ((a) > (b) ? (a) : (b)) #define FMIN(a, b) ((a) < (b) ? (a) : (b)) #define MAXB(bits) ((1 << (bits)) - 1) static inline void calc_rgb_to_hsl(unsigned short *rgb, double *hue, double *sat, double *lightness) { double red, green, blue; double h, s, l; double min, max; double delta; int maxval; red = rgb[0] / 65535.0; green = rgb[1] / 65535.0; blue = rgb[2] / 65535.0; if (red > green) { if (red > blue) { max = red; maxval = 0; } else { max = blue; maxval = 2; } min = FMIN(green, blue); } else { if (green > blue) { max = green; maxval = 1; } else { max = blue; maxval = 2; } min = FMIN(red, blue); } l = (max + min) / 2.0; delta = max - min; if (delta < .000001) /* Suggested by Eugene Anikin */ { s = 0.0; h = 0.0; } else { if (l <= .5) s = delta / (max + min); else s = delta / (2 - max - min); if (maxval == 0) h = (green - blue) / delta; else if (maxval == 1) h = 2 + (blue - red) / delta; else h = 4 + (red - green) / delta; if (h < 0.0) h += 6.0; else if (h > 6.0) h -= 6.0; } *hue = h; *sat = s; *lightness = l; } static inline double hsl_value(double n1, double n2, double hue) { if (hue < 0) hue += 6.0; else if (hue > 6) hue -= 6.0; if (hue < 1.0) return (n1 + (n2 - n1) * hue); else if (hue < 3.0) return (n2); else if (hue < 4.0) return (n1 + (n2 - n1) * (4.0 - hue)); else return (n1); } static inline void calc_hsl_to_rgb(unsigned short *rgb, double h, double s, double l) { if (s < .0000001) { if (l > 1) l = 1; else if (l < 0) l = 0; rgb[0] = l * 65535; rgb[1] = l * 65535; rgb[2] = l * 65535; } else { double m1, m2; double h1, h2; h1 = h + 2; h2 = h - 2; if (l < .5) m2 = l * (1 + s); else m2 = l + s - (l * s); m1 = (l * 2) - m2; rgb[0] = 65535 * hsl_value(m1, m2, h1); rgb[1] = 65535 * hsl_value(m1, m2, h); rgb[2] = 65535 * hsl_value(m1, m2, h2); } } static inline double update_saturation(double sat, double adjust, double isat, int bright_colors) { if (bright_colors || adjust < 1) sat *= adjust; else if (adjust > 1) { double s1 = sat * adjust; double s2 = 1.0 - ((1.0 - sat) * isat); sat = FMIN(s1, s2); } if (sat > 1) sat = 1.0; return sat; } static inline double interpolate_value(const double *vec, double val) { double base = (double)((int)(val)); double frac = val - base; int ibase = (int) base; double lval = vec[ibase]; if (frac > 0) lval += (vec[ibase + 1] - lval) * frac; return lval; } static inline void update_saturation_from_rgb(unsigned short *rgb, const unsigned short *brightness_lookup, double adjust, double isat, int do_usermap) { double h, s, l; calc_rgb_to_hsl(rgb, &h, &s, &l); if (do_usermap) { unsigned short ub = (unsigned short) (l * 65535); unsigned short val = brightness_lookup[ub]; l = ((double) val) / 65535; if (val < ub) s = s * (65535 - ub) / (65535 - val); } s = update_saturation(s, adjust, isat, 0); calc_hsl_to_rgb(rgb, h, s, l); } static inline double adjust_hue(const double *hue_map, double hue, size_t points) { if (hue_map) { hue += interpolate_value(hue_map, hue * points / 6.0); if (hue < 0.0) hue += 6.0; else if (hue >= 6.0) hue -= 6.0; } return hue; } static inline void adjust_hsl(unsigned short *rgbout, lut_t *lut, double ssat, double isat, int split_saturation, int adjust_hue_only, int bright_colors) { const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map)); const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map)); const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map)); size_t hue_count = CURVE_CACHE_FAST_COUNT(&(lut->hue_map)); size_t lum_count = CURVE_CACHE_FAST_COUNT(&(lut->lum_map)); size_t sat_count = CURVE_CACHE_FAST_COUNT(&(lut->sat_map)); double h, s, l; double oh; rgbout[0] ^= 65535; rgbout[1] ^= 65535; rgbout[2] ^= 65535; calc_rgb_to_hsl(rgbout, &h, &s, &l); s = update_saturation(s, ssat, isat, 0); if (!adjust_hue_only && lut->sat_map.d_cache) { double nh = h * sat_count / 6.0; double tmp = interpolate_value(sat_map, nh); if (tmp < .9999 || tmp > 1.0001) s = update_saturation(s, tmp, tmp > 1.0 ? 1.0 / tmp : 1.0, bright_colors); } oh = h; h = adjust_hue(hue_map, h, hue_count); calc_hsl_to_rgb(rgbout, h, s, l); if (!adjust_hue_only && s > 0.00001) { /* * Perform luminosity adjustment only on color component. * This way the luminosity of the gray component won't be affected. * We'll add the gray back at the end. */ unsigned gray = FMIN(rgbout[0], FMIN(rgbout[1], rgbout[2])); int i; /* * Scale the components by the amount of color left. * This way the luminosity calculations will come out right. */ if (gray > 0) for (i = 0; i < 3; i++) rgbout[i] = (rgbout[i] - gray) * 65535.0 / (65535 - gray); if (lut->lum_map.d_cache) { calc_rgb_to_hsl(rgbout, &h, &s, &l); if (lut->lum_map.d_cache && l > 0.00001 && l < .99999) { double nh = oh * lum_count / 6.0; double oel = interpolate_value(lum_map,nh); if (oel <= 1) l *= oel; else { double g1 = pow(l, 1.0 / oel); double g2 = 1.0 - pow(1.0 - l, oel); l = FMIN(g1, g2); } calc_hsl_to_rgb(rgbout, h, s, l); } } if (gray > 0) for (i = 0; i < 3; i++) rgbout[i] = gray + (rgbout[i] * (65535 - gray) / 65535.0); } rgbout[0] ^= 65535; rgbout[1] ^= 65535; rgbout[2] ^= 65535; } #define GENERIC_COLOR_FUNC(fromname, toname) \ CFUNC \ fromname##_to_##toname(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ if (!lut->printed_colorfunc) \ { \ lut->printed_colorfunc = 1; \ stp_dprintf(STP_DBG_COLORFUNC, vars, \ "Colorfunc is %s_%d_to_%s, %s, %s, %d, %d\n", \ #fromname, lut->channel_depth, #toname, \ lut->input_color_description->name, \ lut->output_color_description->name, \ lut->steps, lut->invert_output); \ } \ if (lut->channel_depth == 8) \ return fromname##_8_to_##toname(vars, in, out); \ else \ return fromname##_16_to_##toname(vars, in, out); \ } #define BD(bits) (65535u / (unsigned) MAXB(bits)) #define COLOR_TO_COLOR_FUNC(T, bits) \ CFUNC \ color_##bits##_to_color(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ double isat = 1.0; \ double ssat = stp_get_float_parameter(vars, "Saturation"); \ double sbright = stp_get_float_parameter(vars, "Brightness"); \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ unsigned short o0 = 0; \ unsigned short o1 = 0; \ unsigned short o2 = 0; \ unsigned short nz0 = 0; \ unsigned short nz1 = 0; \ unsigned short nz2 = 0; \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *brightness; \ const unsigned short *contrast; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int compute_saturation = ssat <= .99999 || ssat >= 1.00001; \ int split_saturation = ssat > 1.4; \ int bright_color_adjustment = 0; \ int hue_only_color_adjustment = 0; \ int do_user_adjustment = 0; \ if (lut->color_correction->correction == COLOR_CORRECTION_BRIGHT) \ bright_color_adjustment = 1; \ if (lut->color_correction->correction == COLOR_CORRECTION_HUE) \ hue_only_color_adjustment = 1; \ if (sbright != 1) \ do_user_adjustment = 1; \ compute_saturation |= do_user_adjustment; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(stp_curve_cache_get_curve(&(lut->channel_curves[i])), \ 1 << bits); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ brightness= \ stp_curve_cache_get_ushort_data(&(lut->brightness_correction)); \ contrast = \ stp_curve_cache_get_ushort_data(&(lut->contrast_correction)); \ (void) stp_curve_cache_get_double_data(&(lut->hue_map)); \ (void) stp_curve_cache_get_double_data(&(lut->lum_map)); \ (void) stp_curve_cache_get_double_data(&(lut->sat_map)); \ const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map)); \ const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map)); \ const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map)); \ \ if (split_saturation) \ ssat = sqrt(ssat); \ if (ssat > 1) \ isat = 1.0 / ssat; \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2]) \ { \ out[0] = o0; \ out[1] = o1; \ out[2] = o2; \ } \ else \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ out[0] = contrast[i0]; \ out[1] = contrast[i1]; \ out[2] = contrast[i2]; \ if ((compute_saturation)) \ update_saturation_from_rgb(out, brightness, ssat, isat, \ do_user_adjustment); \ if ((split_saturation || lum_map || hue_map || sat_map) && \ (out[0] != out[1] || out[0] != out[2])) \ adjust_hsl(out, lut, ssat, isat, split_saturation, \ hue_only_color_adjustment, bright_color_adjustment); \ out[0] = red[out[0] / BD(bits)]; \ out[1] = green[out[1] / BD(bits)]; \ out[2] = blue[out[2] / BD(bits)]; \ o0 = out[0]; \ o1 = out[1]; \ o2 = out[2]; \ nz0 |= o0; \ nz1 |= o1; \ nz2 |= o2; \ } \ s_in += 3; \ out += 3; \ } \ return (nz0 ? 0 : 1) + (nz1 ? 0 : 2) + (nz2 ? 0 : 4); \ } COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color GENERIC_COLOR_FUNC(color, color) #define COLOR_TO_KCMY_FUNC(T, bits) \ CFUNC \ color_##bits##_to_kcmy(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ double isat = 1.0; \ double ssat = stp_get_float_parameter(vars, "Saturation"); \ double sbright = stp_get_float_parameter(vars, "Brightness"); \ union { \ unsigned short nz[4]; \ unsigned long long nzl; \ } nzx; \ unsigned retval = 0; \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *brightness; \ const unsigned short *contrast; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int compute_saturation = ssat <= .99999 || ssat >= 1.00001; \ int split_saturation = ssat > 1.4; \ int bright_color_adjustment = 0; \ int hue_only_color_adjustment = 0; \ int do_user_adjustment = 0; \ if (lut->color_correction->correction == COLOR_CORRECTION_BRIGHT) \ bright_color_adjustment = 1; \ if (lut->color_correction->correction == COLOR_CORRECTION_HUE) \ hue_only_color_adjustment = 1; \ if (sbright != 1) \ do_user_adjustment = 1; \ compute_saturation |= do_user_adjustment; \ nzx.nzl = 0ull; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(stp_curve_cache_get_curve(&(lut->channel_curves[i])), \ 1 << bits); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ brightness= \ stp_curve_cache_get_ushort_data(&(lut->brightness_correction)); \ contrast = \ stp_curve_cache_get_ushort_data(&(lut->contrast_correction)); \ (void) stp_curve_cache_get_double_data(&(lut->hue_map)); \ (void) stp_curve_cache_get_double_data(&(lut->lum_map)); \ (void) stp_curve_cache_get_double_data(&(lut->sat_map)); \ const double *hue_map = CURVE_CACHE_FAST_DOUBLE(&(lut->hue_map)); \ const double *lum_map = CURVE_CACHE_FAST_DOUBLE(&(lut->lum_map)); \ const double *sat_map = CURVE_CACHE_FAST_DOUBLE(&(lut->sat_map)); \ \ if (split_saturation) \ ssat = sqrt(ssat); \ if (ssat > 1) \ isat = 1.0 / ssat; \ for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3) \ { \ out[1] = contrast[s_in[0]]; \ out[2] = contrast[s_in[1]]; \ out[3] = contrast[s_in[2]]; \ if ((compute_saturation)) \ update_saturation_from_rgb(out + 1, brightness, ssat, isat, \ do_user_adjustment); \ if ((split_saturation || lum_map || hue_map || sat_map) && \ (out[1] != out[2] || out[1] != out[3])) \ adjust_hsl(out + 1, lut, ssat, isat, split_saturation, \ hue_only_color_adjustment, bright_color_adjustment); \ out[1] = red[out[1] / BD(bits)]; \ out[2] = green[out[2] / BD(bits)]; \ out[3] = blue[out[3] / BD(bits)]; \ out[0] = FMIN(out[1], FMIN(out[2], out[3])); \ out[1] -= out[0]; \ out[2] -= out[0]; \ out[3] -= out[0]; \ nzx.nzl |= *(unsigned long long *) out; \ } \ for (i = 0; i < 4; i++) \ if (nzx.nz[i] == 0) \ retval |= (1 << i); \ return retval; \ } COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_kcmy GENERIC_COLOR_FUNC(color, kcmy) /* * 'rgb_to_rgb()' - Convert rgb image data to RGB. */ #define FAST_COLOR_TO_COLOR_FUNC(T, bits) \ CFUNC \ color_##bits##_to_color_fast(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int o0 = 0; \ int o1 = 0; \ int o2 = 0; \ int nz0 = 0; \ int nz1 = 0; \ int nz2 = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *brightness; \ const unsigned short *contrast; \ double isat = 1.0; \ double saturation = stp_get_float_parameter(vars, "Saturation"); \ double sbright = stp_get_float_parameter(vars, "Brightness"); \ int compute_saturation = saturation <= .99999 || saturation >= 1.00001; \ int do_user_adjustment = 0; \ if (sbright != 1) \ do_user_adjustment = 1; \ compute_saturation |= do_user_adjustment; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ brightness= \ stp_curve_cache_get_ushort_data(&(lut->brightness_correction)); \ contrast = \ stp_curve_cache_get_ushort_data(&(lut->contrast_correction)); \ \ if (saturation > 1) \ isat = 1.0 / saturation; \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 == s_in[0] && i1 == s_in[1] && i2 == s_in[2]) \ { \ out[0] = o0; \ out[1] = o1; \ out[2] = o2; \ } \ else \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ out[0] = contrast[s_in[0]]; \ out[1] = contrast[s_in[1]]; \ out[2] = contrast[s_in[2]]; \ if ((compute_saturation)) \ update_saturation_from_rgb(out, brightness, saturation, isat, 1); \ out[0] = red[out[0]]; \ out[1] = green[out[1]]; \ out[2] = blue[out[2]]; \ o0 = out[0]; \ o1 = out[1]; \ o2 = out[2]; \ nz0 |= o0; \ nz1 |= o1; \ nz2 |= o2; \ } \ s_in += 3; \ out += 3; \ } \ return (nz0 ? 0 : 1) + (nz1 ? 0 : 2) + (nz2 ? 0 : 4); \ } FAST_COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color_fast FAST_COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color_fast GENERIC_COLOR_FUNC(color, color_fast) #define FAST_COLOR_TO_KCMY_FUNC(T, bits) \ CFUNC \ color_##bits##_to_kcmy_fast(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ union { \ unsigned short nz[4]; \ unsigned long long nzl; \ } nzx; \ unsigned retval = 0; \ unsigned short c, m, y, k; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *brightness; \ const unsigned short *contrast; \ double isat = 1.0; \ double saturation = stp_get_float_parameter(vars, "Saturation"); \ double sbright = stp_get_float_parameter(vars, "Brightness"); \ int compute_saturation = saturation <= .99999 || saturation >= 1.00001; \ int do_user_adjustment = 0; \ if (sbright != 1) \ do_user_adjustment = 1; \ compute_saturation |= do_user_adjustment; \ nzx.nzl = 0ull; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->brightness_correction)), 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->contrast_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ brightness= \ stp_curve_cache_get_ushort_data(&(lut->brightness_correction)); \ contrast = \ stp_curve_cache_get_ushort_data(&(lut->contrast_correction)); \ \ if (saturation > 1) \ isat = 1.0 / saturation; \ for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3) \ { \ c = contrast[s_in[0]]; \ m = contrast[s_in[1]]; \ y = contrast[s_in[2]]; \ if (compute_saturation) \ { \ unsigned short tmp[3]; \ tmp[0] = c; \ tmp[1] = m; \ tmp[2] = y; \ update_saturation_from_rgb(tmp, brightness, saturation, \ isat, 1); \ c = tmp[0]; \ m = tmp[1]; \ y = tmp[2]; \ } \ c = red[c]; \ m = green[m]; \ y = blue[y]; \ k = FMIN(c, FMIN(m, y)); \ out[0] = k; \ out[1] = c - k; \ out[2] = m - k; \ out[3] = y - k; \ nzx.nzl |= *(unsigned long long *) out; \ } \ for (i = 0; i < 4; i++) \ if (nzx.nz[i] == 0) \ retval |= (1 << i); \ return retval; \ } FAST_COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy_fast FAST_COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_color_fast GENERIC_COLOR_FUNC(color, kcmy_fast) #define RAW_COLOR_TO_COLOR_FUNC(T, bits) \ CFUNC \ color_##bits##_to_color_raw(const stp_vars_t *vars, const unsigned char *in,\ unsigned short *out) \ { \ int i; \ int j; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned mask = 0; \ if (lut->invert_output) \ mask = 0xffff; \ \ for (i = 0; i < lut->image_width; i++) \ { \ unsigned bit = 1; \ for (j = 0; j < 3; j++, bit += bit) \ { \ out[j] = (s_in[j] * (65535 / ((1 << bits) - 1))) ^ mask; \ if (out[j]) \ nz |= bit; \ } \ s_in += 3; \ out += 3; \ } \ return nz; \ } RAW_COLOR_TO_COLOR_FUNC(unsigned char, 8) // color_8_to_color_raw RAW_COLOR_TO_COLOR_FUNC(unsigned short, 16) // color_16_to_color_raw GENERIC_COLOR_FUNC(color, color_raw) #define RAW_COLOR_TO_KCMY_FUNC(T, bits) \ CFUNC \ color_##bits##_to_kcmy_raw(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ union { \ unsigned short nz[4]; \ unsigned long long nzl; \ } nzx; \ unsigned retval = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned mask = 0; \ if (lut->invert_output) \ mask = 0xffff; \ nzx.nzl = 0ull; \ \ for (i = 0; i < lut->image_width; i++, out += 4, s_in += 3) \ { \ unsigned c = (s_in[0] * BD(bits)) ^ mask; \ unsigned m = (s_in[1] * BD(bits)) ^ mask; \ unsigned y = (s_in[2] * BD(bits)) ^ mask; \ unsigned k = FMIN(c, FMIN(m, y)); \ out[0] = k; \ out[1] = c - k; \ out[2] = m - k; \ out[3] = y - k; \ nzx.nzl |= *(unsigned long long *) out; \ } \ for (i = 0; i < 4; i++) \ if (nzx.nz[i] == 0) \ retval |= (1 << i); \ return retval; \ } RAW_COLOR_TO_KCMY_FUNC(unsigned char, 8) // color_8_to_kcmy_raw RAW_COLOR_TO_KCMY_FUNC(unsigned short, 16) // color_16_to_kcmy_raw GENERIC_COLOR_FUNC(color, kcmy_raw) /* * 'gray_to_rgb()' - Convert gray image data to RGB. */ #define GRAY_TO_COLOR_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_color(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int o0 = 0; \ int o1 = 0; \ int o2 = 0; \ int nz0 = 0; \ int nz1 = 0; \ int nz2 = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *user; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->user_color_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ user = \ stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 == s_in[0]) \ { \ out[0] = o0; \ out[1] = o1; \ out[2] = o2; \ } \ else \ { \ i0 = s_in[0]; \ out[0] = red[user[s_in[0]]]; \ out[1] = green[user[s_in[0]]]; \ out[2] = blue[user[s_in[0]]]; \ o0 = out[0]; \ o1 = out[1]; \ o2 = out[2]; \ nz0 |= o0; \ nz1 |= o1; \ nz2 |= o2; \ } \ s_in += 1; \ out += 3; \ } \ return (nz0 ? 0 : 1) + (nz1 ? 0 : 2) + (nz2 ? 0 : 4); \ } GRAY_TO_COLOR_FUNC(unsigned char, 8) // gray_8_to_color GRAY_TO_COLOR_FUNC(unsigned short, 16) // gray_16_to_color GENERIC_COLOR_FUNC(gray, color) #define GRAY_TO_KCMY_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_kcmy(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ union { \ unsigned short nz[4]; \ unsigned long long nzl; \ } nzx; \ unsigned retval = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *red; \ const unsigned short *green; \ const unsigned short *blue; \ const unsigned short *user; \ \ for (i = CHANNEL_C; i <= CHANNEL_Y; i++) \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->user_color_correction)), 1 << bits); \ red = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_C])); \ green = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_M])); \ blue = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_Y])); \ user = \ stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ for (i = 0; i < lut->image_width; i++, out += 4, s_in++) \ { \ out[1] = red[user[s_in[0]]]; \ out[2] = green[user[s_in[0]]]; \ out[3] = blue[user[s_in[0]]]; \ out[0] = FMIN(out[1], FMIN(out[2], out[3])); \ out[1] -= out[0]; \ out[2] -= out[0]; \ out[3] -= out[0]; \ nzx.nzl |= *(unsigned long long *) out; \ } \ for (i = 0; i < 4; i++) \ if (nzx.nz[i] == 0) \ retval |= (1 << i); \ return retval; \ } GRAY_TO_KCMY_FUNC(unsigned char, 8) // gray_8_to_kcmy GRAY_TO_KCMY_FUNC(unsigned short, 16) // gray_16_to_kcmy GENERIC_COLOR_FUNC(gray, kcmy) #define GRAY_TO_COLOR_RAW_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_color_raw(const stp_vars_t *vars, const unsigned char *in,\ unsigned short *out) \ { \ int i; \ int nz = 7; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned mask = 0; \ if (lut->invert_output) \ mask = 0xffff; \ \ for (i = 0; i < lut->image_width; i++) \ { \ unsigned outval = (s_in[0] * (65535 / (1 << bits))) ^ mask; \ out[0] = outval; \ out[1] = outval; \ out[2] = outval; \ if (outval) \ nz = 0; \ s_in++; \ out += 3; \ } \ return nz; \ } GRAY_TO_COLOR_RAW_FUNC(unsigned char, 8) // gray_8_to_color_raw GRAY_TO_COLOR_RAW_FUNC(unsigned short, 16) // gray_16_to_color_raw GENERIC_COLOR_FUNC(gray, color_raw) #define GRAY_TO_KCMY_RAW_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_kcmy_raw(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int nz = 7; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned mask = 0; \ if (lut->invert_output) \ mask = 0xffff; \ \ for (i = 0; i < lut->image_width; i++, out += 4, s_in++) \ { \ unsigned outval = (s_in[0] * (65535 / (1 << bits))) ^ mask; \ out[0] = outval; \ out[1] = 0; \ out[2] = 0; \ out[3] = 0; \ if (outval) \ nz = 0; \ } \ return nz; \ } GRAY_TO_KCMY_RAW_FUNC(unsigned char, 8) // gray_8_to_kcmy_raw GRAY_TO_KCMY_RAW_FUNC(unsigned short, 16) // gray_16_to_kcmy_raw GENERIC_COLOR_FUNC(gray, kcmy_raw) #define COLOR_TO_KCMY_THRESHOLD_FUNC(T, name) \ CFUNC \ name##_to_kcmy_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int z = 15; \ const T *s_in = (const T *) in; \ unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1))); \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ unsigned mask = 0; \ memset(out, 0, width * 4 * sizeof(unsigned short)); \ if (lut->invert_output) \ mask = (1 << (sizeof(T) * 8)) - 1; \ \ for (i = 0; i < width; i++, out += 4, s_in += 3) \ { \ unsigned c = s_in[0] ^ mask; \ unsigned m = s_in[1] ^ mask; \ unsigned y = s_in[2] ^ mask; \ unsigned k = (c < m ? (c < y ? c : y) : (m < y ? m : y)); \ if (k >= high_bit) \ { \ c -= k; \ m -= k; \ y -= k; \ } \ if (k >= high_bit) \ { \ z &= 0xe; \ out[0] = 65535; \ } \ if (c >= high_bit) \ { \ z &= 0xd; \ out[1] = 65535; \ } \ if (m >= high_bit) \ { \ z &= 0xb; \ out[2] = 65535; \ } \ if (y >= high_bit) \ { \ z &= 0x7; \ out[3] = 65535; \ } \ } \ return z; \ } COLOR_TO_KCMY_THRESHOLD_FUNC(unsigned char, color_8) // color_8_to_kcmy_threshold COLOR_TO_KCMY_THRESHOLD_FUNC(unsigned short, color_16) // color_16_to_kcmy_threshold GENERIC_COLOR_FUNC(color, kcmy_threshold) #define CMYK_TO_KCMY_THRESHOLD_FUNC(T, name) \ CFUNC \ name##_to_kcmy_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int z = 15; \ const T *s_in = (const T *) in; \ unsigned desired_high_bit = 0; \ unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ memset(out, 0, width * 4 * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ \ for (i = 0; i < width; i++, out += 4, s_in += 4) \ { \ if ((s_in[3] & high_bit) == desired_high_bit) \ { \ z &= 0xe; \ out[0] = 65535; \ } \ if ((s_in[0] & high_bit) == desired_high_bit) \ { \ z &= 0xd; \ out[1] = 65535; \ } \ if ((s_in[1] & high_bit) == desired_high_bit) \ { \ z &= 0xb; \ out[2] = 65535; \ } \ if ((s_in[2] & high_bit) == desired_high_bit) \ { \ z &= 0x7; \ out[3] = 65535; \ } \ } \ return z; \ } CMYK_TO_KCMY_THRESHOLD_FUNC(unsigned char, cmyk_8) // cmyk_8_to_kcmy_threshold CMYK_TO_KCMY_THRESHOLD_FUNC(unsigned short, cmyk_16) // cmyk_16_to_kcmy_threshodl GENERIC_COLOR_FUNC(cmyk, kcmy_threshold) #define KCMY_TO_KCMY_THRESHOLD_FUNC(T, name) \ CFUNC \ name##_to_kcmy_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int j; \ unsigned nz[4]; \ unsigned z = 0xf; \ const T *s_in = (const T *) in; \ unsigned desired_high_bit = 0; \ unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ memset(out, 0, width * 4 * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ for (i = 0; i < 4; i++) \ nz[i] = z & ~(1 << i); \ \ for (i = 0; i < width; i++) \ { \ for (j = 0; j < 4; j++) \ { \ if ((*s_in++ & high_bit) == desired_high_bit) \ { \ z &= nz[j]; \ *out = 65535; \ } \ out++; \ } \ } \ return z; \ } KCMY_TO_KCMY_THRESHOLD_FUNC(unsigned char, kcmy_8) // kcmy_8_to_kcmy_threshold KCMY_TO_KCMY_THRESHOLD_FUNC(unsigned short, kcmy_16) // kcmy_8_to_kcmy_threshold GENERIC_COLOR_FUNC(kcmy, kcmy_threshold) #define GRAY_TO_COLOR_THRESHOLD_FUNC(T, name, bits, channels) \ CFUNC \ gray_##bits##_to_##name##_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int z = (1 << channels) - 1; \ int desired_high_bit = 0; \ unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ memset(out, 0, width * channels * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ \ for (i = 0; i < width; i++, out += channels, s_in++) \ { \ if ((s_in[0] & high_bit) == desired_high_bit) \ { \ int j; \ z = 0; \ for (j = 0; j < channels; j++) \ out[j] = 65535; \ } \ } \ return z; \ } GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned char, color, 8, 3) // gray_8_to_color_threshold GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned short, color, 16, 3) // gray_16_to_color_threshold GENERIC_COLOR_FUNC(gray, color_threshold) GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned char, kcmy, 8, 4) // gray_8_to_kcmy_threshold GRAY_TO_COLOR_THRESHOLD_FUNC(unsigned short, kcmy, 16, 4) // gray_16_to_kcmy_threshold GENERIC_COLOR_FUNC(gray, kcmy_threshold) #define COLOR_TO_COLOR_THRESHOLD_FUNC(T, name) \ CFUNC \ name##_to_color_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int z = 7; \ int desired_high_bit = 0; \ unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1)) * 4); \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ memset(out, 0, width * 3 * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ \ for (i = 0; i < width; i++, out += 3, s_in += 3) \ { \ if ((s_in[0] & high_bit) == desired_high_bit) \ { \ z &= 6; \ out[0] = 65535; \ } \ if ((s_in[1] & high_bit) == desired_high_bit) \ { \ z &= 5; \ out[1] = 65535; \ } \ if ((s_in[1] & high_bit) == desired_high_bit) \ { \ z &= 3; \ out[2] = 65535; \ } \ } \ return z; \ } COLOR_TO_COLOR_THRESHOLD_FUNC(unsigned char, color_8) // color_8_to_color_threshold COLOR_TO_COLOR_THRESHOLD_FUNC(unsigned short, color_16) // color_8_to_color_threshold GENERIC_COLOR_FUNC(color, color_threshold) #define COLOR_TO_GRAY_THRESHOLD_FUNC(T, name, channels, max_channels) \ CFUNC \ name##_to_gray_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int z = 1; \ int desired_high_bit = 0; \ unsigned high_bit = ((1 << ((sizeof(T) * 8) - 1))); \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ memset(out, 0, width * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ \ for (i = 0; i < width; i++, out++, s_in += channels) \ { \ unsigned gval = \ (max_channels - channels) * (1 << ((sizeof(T) * 8) - 1)); \ int j; \ for (j = 0; j < channels; j++) \ gval += s_in[j]; \ gval /= channels; \ if ((gval & high_bit) == desired_high_bit) \ { \ out[0] = 65535; \ z = 0; \ } \ } \ return z; \ } COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, cmyk_8, 4, 4) // cmyk_8_to_gray_threshold COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, cmyk_16, 4, 4) // cmyk_16_to_gray_threshold GENERIC_COLOR_FUNC(cmyk, gray_threshold) COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, kcmy_8, 4, 4) // kcmy_8_to_gray_threshold COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, kcmy_16, 4, 4) // kcmy_16_to_gray_threshold GENERIC_COLOR_FUNC(kcmy, gray_threshold) COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, color_8, 3, 3) // color_8_to_gray_threshold COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, color_16, 3, 3) // color_16_to_gray_threshold GENERIC_COLOR_FUNC(color, gray_threshold) COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned char, gray_8, 1, 1) // gray_8_to_gray_threshold COLOR_TO_GRAY_THRESHOLD_FUNC(unsigned short, gray_16, 1, 1) // gray_16_to_gray_threshold GENERIC_COLOR_FUNC(gray, gray_threshold) #define CMYK_TO_COLOR_FUNC(namein, name2, T, bits, offset) \ static unsigned \ namein##_##bits##_to_##name2(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ int i; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned status; \ size_t real_steps = lut->steps; \ const T *s_in = (const T *) in; \ unsigned short *tmp; \ int width = lut->image_width; \ \ if (!lut->cmy_tmp) \ lut->cmy_tmp = stp_malloc(3 * 2 * lut->image_width); \ tmp = lut->cmy_tmp; \ memset(lut->cmy_tmp, 0, width * 3 * sizeof(unsigned short)); \ \ for (i = 0; i < width; i++, tmp += 3, s_in += 4) \ { \ unsigned c = (s_in[0 + offset] + s_in[(3 + offset) % 4]) * \ (65535 / MAXB(bits)); \ unsigned m = (s_in[1 + offset] + s_in[(3 + offset) % 4]) * \ (65535 / MAXB(bits)); \ unsigned y = (s_in[2 + offset] + s_in[(3 + offset) % 4]) * \ (65535 / MAXB(bits)); \ if (c > MAXB(16)) \ c = MAXB(16); \ if (m > MAXB(16)) \ m = MAXB(16); \ if (y > MAXB(16)) \ y = MAXB(16); \ tmp[0] = c; \ tmp[1] = m; \ tmp[2] = y; \ } \ lut->steps = 65536; \ status = \ color_16_to_##name2(vars, (const unsigned char *) lut->cmy_tmp, out); \ lut->steps = real_steps; \ return status; \ } CMYK_TO_COLOR_FUNC(cmyk, color, unsigned char, 8, 0) // cmyk_8_to_color CMYK_TO_COLOR_FUNC(cmyk, color, unsigned short, 16, 0) // cmyk_16_to_color GENERIC_COLOR_FUNC(cmyk, color) CMYK_TO_COLOR_FUNC(kcmy, color, unsigned char, 8, 1) // kcmy_8_to_color CMYK_TO_COLOR_FUNC(kcmy, color, unsigned short, 16, 1) // kcmy_16_to_color GENERIC_COLOR_FUNC(kcmy, color) CMYK_TO_COLOR_FUNC(cmyk, color_threshold, unsigned char, 8, 0) // cmyk_8_to_color_threshold CMYK_TO_COLOR_FUNC(cmyk, color_threshold, unsigned short, 16, 0) // cmyk_16_to_color_threshold GENERIC_COLOR_FUNC(cmyk, color_threshold) CMYK_TO_COLOR_FUNC(kcmy, color_threshold, unsigned char, 8, 1) // kcmy_8_to_color_threshold CMYK_TO_COLOR_FUNC(kcmy, color_threshold, unsigned short, 16, 1) // kcmy_16_to_color_threshold GENERIC_COLOR_FUNC(kcmy, color_threshold) CMYK_TO_COLOR_FUNC(cmyk, color_fast, unsigned char, 8, 0) // cmyk_8_to_color_fast CMYK_TO_COLOR_FUNC(cmyk, color_fast, unsigned short, 16, 0) // cmyk_16_to_color_fast GENERIC_COLOR_FUNC(cmyk, color_fast) CMYK_TO_COLOR_FUNC(kcmy, color_fast, unsigned char, 8, 1) // kcmy_8_to_color_fast CMYK_TO_COLOR_FUNC(kcmy, color_fast, unsigned short, 16, 1) // kcmy_16_to_color_fast GENERIC_COLOR_FUNC(kcmy, color_fast) CMYK_TO_COLOR_FUNC(cmyk, color_raw, unsigned char, 8, 0) // cmyk_8_to_color_raw CMYK_TO_COLOR_FUNC(cmyk, color_raw, unsigned short, 16, 0) // cmyk_16_to_color_raw GENERIC_COLOR_FUNC(cmyk, color_raw) CMYK_TO_COLOR_FUNC(kcmy, color_raw, unsigned char, 8, 1) // kcmy_8_to_color_raw CMYK_TO_COLOR_FUNC(kcmy, color_raw, unsigned short, 16, 1) // kcmy_16_to_color_raw GENERIC_COLOR_FUNC(kcmy, color_raw) #define CMYK_TO_KCMY_FUNC(T, size) \ CFUNC \ cmyk_##size##_to_kcmy(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ unsigned retval = 0; \ int j; \ int nz[4]; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *user; \ const unsigned short *maps[4]; \ \ for (i = 0; i < 4; i++) \ { \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \ } \ stp_curve_resample(lut->user_color_correction.curve, 1 << size); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ memset(nz, 0, sizeof(nz)); \ \ for (i = 0; i < lut->image_width; i++, out += 4) \ { \ for (j = 0; j < 4; j++) \ { \ int outpos = (j + 1) & 3; \ int inval = *s_in++; \ nz[outpos] |= inval; \ out[outpos] = maps[outpos][user[inval]]; \ } \ } \ for (j = 0; j < 4; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } CMYK_TO_KCMY_FUNC(unsigned char, 8) // cmyk_8_to_kcmy CMYK_TO_KCMY_FUNC(unsigned short, 16) // cmyk_16_to_kcmy GENERIC_COLOR_FUNC(cmyk, kcmy) #define KCMY_TO_KCMY_FUNC(T, size) \ CFUNC \ kcmy_##size##_to_kcmy(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ unsigned retval = 0; \ int j; \ int nz[4]; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *user; \ const unsigned short *maps[4]; \ \ for (i = 0; i < 4; i++) \ { \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \ } \ stp_curve_resample(lut->user_color_correction.curve, 1 << size); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ memset(nz, 0, sizeof(nz)); \ \ for (i = 0; i < lut->image_width; i++, out += 4) \ { \ for (j = 0; j < 4; j++) \ { \ int inval = *s_in++; \ nz[j] |= inval; \ out[j] = maps[j][user[inval]]; \ } \ } \ for (j = 0; j < 4; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } KCMY_TO_KCMY_FUNC(unsigned char, 8) // kcmy_8_to_kcmy KCMY_TO_KCMY_FUNC(unsigned short, 16) // kcmy_16_to_kcmy GENERIC_COLOR_FUNC(kcmy, kcmy) #define GRAY_TO_GRAY_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_gray(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ const unsigned short *composite; \ const unsigned short *user; \ \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536); \ composite = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K])); \ stp_curve_resample(lut->user_color_correction.curve, 1 << bits); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ memset(out, 0, width * sizeof(unsigned short)); \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0]) \ { \ i0 = s_in[0]; \ o0 = composite[user[i0]]; \ nz |= o0; \ } \ out[0] = o0; \ s_in ++; \ out ++; \ } \ return nz == 0; \ } GRAY_TO_GRAY_FUNC(unsigned char, 8) // gray_8_to_gray GRAY_TO_GRAY_FUNC(unsigned short, 16) // gray_16_to_gray GENERIC_COLOR_FUNC(gray, gray) #define COLOR_TO_GRAY_FUNC(T, bits) \ CFUNC \ color_##bits##_to_gray(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ const unsigned short *composite; \ const unsigned short *user; \ \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536); \ composite = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K])); \ stp_curve_resample(lut->user_color_correction.curve, 1 << bits); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 2; \ l_green = (100 - l_green) / 2; \ l_blue = (100 - l_blue) / 2; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ o0 = \ composite[user[(i0 * l_red + i1 * l_green + i2 * l_blue) / 100]]; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 3; \ out ++; \ } \ return nz == 0; \ } COLOR_TO_GRAY_FUNC(unsigned char, 8) // color_8_to_gray COLOR_TO_GRAY_FUNC(unsigned short, 16) // color_16_to_gray GENERIC_COLOR_FUNC(color, gray) #define CMYK_TO_GRAY_FUNC(T, bits) \ CFUNC \ cmyk_##bits##_to_gray(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int i3 = -4; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ int l_white = 0; \ const unsigned short *composite; \ const unsigned short *user; \ \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536); \ composite = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K])); \ stp_curve_resample(lut->user_color_correction.curve, 1 << bits); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 3; \ l_green = (100 - l_green) / 3; \ l_blue = (100 - l_blue) / 3; \ l_white = (100 - l_white) / 3; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ i3 = s_in[3]; \ o0 = composite[user[(i0 * l_red + i1 * l_green + \ i2 * l_blue + i3 * l_white) / 100]]; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 4; \ out ++; \ } \ return nz ? 0 : 1; \ } CMYK_TO_GRAY_FUNC(unsigned char, 8) // cmyk_8_to_gray CMYK_TO_GRAY_FUNC(unsigned short, 16) // cmyk_16_to_gray GENERIC_COLOR_FUNC(cmyk, gray) #define KCMY_TO_GRAY_FUNC(T, bits) \ CFUNC \ kcmy_##bits##_to_gray(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int i3 = -4; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ int l_white = 0; \ const unsigned short *composite; \ const unsigned short *user; \ \ stp_curve_resample \ (stp_curve_cache_get_curve(&(lut->channel_curves[CHANNEL_K])), 65536); \ composite = \ stp_curve_cache_get_ushort_data(&(lut->channel_curves[CHANNEL_K])); \ stp_curve_resample(lut->user_color_correction.curve, 1 << bits); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 3; \ l_green = (100 - l_green) / 3; \ l_blue = (100 - l_blue) / 3; \ l_white = (100 - l_white) / 3; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ i3 = s_in[3]; \ o0 = composite[user[(i0 * l_red + i1 * l_green + \ i2 * l_blue + i3 * l_white) / 100]]; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 4; \ out ++; \ } \ return nz ? 0 : 1; \ } KCMY_TO_GRAY_FUNC(unsigned char, 8) // kcmy_8_to_gray KCMY_TO_GRAY_FUNC(unsigned short, 16) // kcmy_16_to_gray GENERIC_COLOR_FUNC(kcmy, gray) #define GRAY_TO_GRAY_RAW_FUNC(T, bits) \ CFUNC \ gray_##bits##_to_gray_raw(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int width = lut->image_width; \ unsigned mask = 0; \ if (lut->invert_output) \ mask = 0xffff; \ \ memset(out, 0, width * sizeof(unsigned short)); \ \ for (i = 0; i < lut->image_width; i++) \ { \ out[0] = (s_in[0] * (65535 / ((1 << bits) - 1))) ^ mask; \ nz |= out[0]; \ s_in ++; \ out ++; \ } \ return nz == 0; \ } GRAY_TO_GRAY_RAW_FUNC(unsigned char, 8) // gray_8_to_gray_raw GRAY_TO_GRAY_RAW_FUNC(unsigned short, 16) // gray_16_to_gray_raw GENERIC_COLOR_FUNC(gray, gray_raw) #define COLOR_TO_GRAY_RAW_FUNC(T, bits, invertable, name2) \ CFUNC \ color_##bits##_to_gray_##name2(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ unsigned mask = 0; \ if (lut->invert_output && invertable) \ mask = 0xffff; \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 2; \ l_green = (100 - l_green) / 2; \ l_blue = (100 - l_blue) / 2; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_red + \ i1 * (65535 / ((1 << bits) - 1)) * l_green + \ i2 * (65535 / ((1 << bits) - 1)) * l_blue) / 100; \ o0 ^= mask; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 3; \ out ++; \ } \ return nz == 0; \ } COLOR_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // color_8_to_gray_raw COLOR_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // color_16_to_gray_raw GENERIC_COLOR_FUNC(color, gray_raw) COLOR_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // color_8_to_gray_noninvert COLOR_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // color_16_to_gray_noninvert // GENERIC_COLOR_FUNC(color, gray_noninvert) #define CMYK_TO_GRAY_RAW_FUNC(T, bits, invertable, name2) \ CFUNC \ cmyk_##bits##_to_gray_##name2(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int i3 = -4; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ int l_white = 0; \ unsigned mask = 0; \ if (lut->invert_output && invertable) \ mask = 0xffff; \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 3; \ l_green = (100 - l_green) / 3; \ l_blue = (100 - l_blue) / 3; \ l_white = (100 - l_white) / 3; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ i3 = s_in[3]; \ o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_red + \ i1 * (65535 / ((1 << bits) - 1)) * l_green + \ i2 * (65535 / ((1 << bits) - 1)) * l_blue + \ i3 * (65535 / ((1 << bits) - 1)) * l_white) / 100; \ o0 ^= mask; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 4; \ out ++; \ } \ return nz ? 0 : 1; \ } CMYK_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // cmyk_8_to_gray_raw CMYK_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // cmyk_16_to_gray_raw GENERIC_COLOR_FUNC(cmyk, gray_raw) CMYK_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // cmyk_8_to_gray_noninvert CMYK_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // cmyk_16_to_gray_noninvert // GENERIC_COLOR_FUNC(cmyk, gray_noninvert) #define KCMY_TO_GRAY_RAW_FUNC(T, bits, invertable, name2) \ CFUNC \ kcmy_##bits##_to_gray_##name2(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int i0 = -1; \ int i1 = -1; \ int i2 = -1; \ int i3 = -4; \ int o0 = 0; \ int nz = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int l_red = LUM_RED; \ int l_green = LUM_GREEN; \ int l_blue = LUM_BLUE; \ int l_white = 0; \ unsigned mask = 0; \ if (lut->invert_output && invertable) \ mask = 0xffff; \ \ if (lut->input_color_description->color_model == COLOR_BLACK) \ { \ l_red = (100 - l_red) / 3; \ l_green = (100 - l_green) / 3; \ l_blue = (100 - l_blue) / 3; \ l_white = (100 - l_white) / 3; \ } \ \ for (i = 0; i < lut->image_width; i++) \ { \ if (i0 != s_in[0] || i1 != s_in[1] || i2 != s_in[2] || i3 != s_in[3]) \ { \ i0 = s_in[0]; \ i1 = s_in[1]; \ i2 = s_in[2]; \ i3 = s_in[3]; \ o0 = (i0 * (65535 / ((1 << bits) - 1)) * l_white + \ i1 * (65535 / ((1 << bits) - 1)) * l_red + \ i2 * (65535 / ((1 << bits) - 1)) * l_green + \ i3 * (65535 / ((1 << bits) - 1)) * l_blue) / 100; \ o0 ^= mask; \ nz |= o0; \ } \ out[0] = o0; \ s_in += 4; \ out ++; \ } \ return nz ? 0 : 1; \ } KCMY_TO_GRAY_RAW_FUNC(unsigned char, 8, 1, raw) // kcmy_8_to_gray_raw KCMY_TO_GRAY_RAW_FUNC(unsigned short, 16, 1, raw) // kcmy_16_to_gray_raw GENERIC_COLOR_FUNC(kcmy, gray_raw) KCMY_TO_GRAY_RAW_FUNC(unsigned char, 8, 0, noninvert) // kcmy_8_to_gray_noninvert KCMY_TO_GRAY_RAW_FUNC(unsigned short, 16, 0, noninvert) // kcmy_16_to_gray_noninvert // GENERIC_COLOR_FUNC(kcmy, gray_noninvert) #define CMYK_TO_KCMY_RAW_FUNC(T, bits) \ CFUNC \ cmyk_##bits##_to_kcmy_raw(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int j; \ int nz[4]; \ unsigned retval = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ \ memset(nz, 0, sizeof(nz)); \ for (i = 0; i < lut->image_width; i++) \ { \ out[0] = s_in[3] * (65535 / ((1 << bits) - 1)); \ out[1] = s_in[0] * (65535 / ((1 << bits) - 1)); \ out[2] = s_in[1] * (65535 / ((1 << bits) - 1)); \ out[3] = s_in[2] * (65535 / ((1 << bits) - 1)); \ for (j = 0; j < 4; j++) \ nz[j] |= out[j]; \ s_in += 4; \ out += 4; \ } \ for (j = 0; j < 4; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } CMYK_TO_KCMY_RAW_FUNC(unsigned char, 8) // cmyk_8_to_kcmy_raw CMYK_TO_KCMY_RAW_FUNC(unsigned short, 16) // cmyk_16_to_kcmy_raw GENERIC_COLOR_FUNC(cmyk, kcmy_raw) #define KCMY_TO_KCMY_RAW_FUNC(T, bits) \ CFUNC \ kcmy_##bits##_to_kcmy_raw(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int j; \ int nz[4]; \ unsigned retval = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ \ memset(nz, 0, sizeof(nz)); \ for (i = 0; i < lut->image_width; i++) \ { \ for (j = 0; j < 4; j++) \ { \ out[j] = s_in[j] * (65535 / ((1 << bits) - 1)); \ nz[j] |= out[j]; \ } \ s_in += 4; \ out += 4; \ } \ for (j = 0; j < 4; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } KCMY_TO_KCMY_RAW_FUNC(unsigned char, 8) // kcmy_8_to_kcmy_raw KCMY_TO_KCMY_RAW_FUNC(unsigned short, 16) // kcmy_16_to_kcmy_raw GENERIC_COLOR_FUNC(kcmy, kcmy_raw) #define DESATURATED_FUNC(name, name2, bits) \ CFUNC \ name##_##bits##_to_##name2##_desaturated(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ size_t real_steps = lut->steps; \ unsigned status; \ if (!lut->gray_tmp) \ lut->gray_tmp = stp_malloc(2 * lut->image_width); \ name##_##bits##_to_gray_noninvert(vars, in, lut->gray_tmp); \ lut->steps = 65536; \ status = gray_16_to_##name2(vars, (unsigned char *) lut->gray_tmp, out); \ lut->steps = real_steps; \ return status; \ } DESATURATED_FUNC(color, color, 8) // color_8_to_color_desaturated DESATURATED_FUNC(color, color, 16) // color_16_to_color_desaturated GENERIC_COLOR_FUNC(color, color_desaturated) DESATURATED_FUNC(color, kcmy, 8) // color_8_to_kcmy_desaturated DESATURATED_FUNC(color, kcmy, 16) // color_8_to_kcmy_desaturated GENERIC_COLOR_FUNC(color, kcmy_desaturated) DESATURATED_FUNC(cmyk, color, 8) // cmyk_8_to_color_desaturated DESATURATED_FUNC(cmyk, color, 16) // cmyk_16_to_color_desaturated GENERIC_COLOR_FUNC(cmyk, color_desaturated) DESATURATED_FUNC(cmyk, kcmy, 8) // cmyk_8_to_kcmy_desaturated DESATURATED_FUNC(cmyk, kcmy, 16) // cmyk_16_to_kcmy_desaturated GENERIC_COLOR_FUNC(cmyk, kcmy_desaturated) DESATURATED_FUNC(kcmy, color, 8) // kcmy_8_to_color_desaturated DESATURATED_FUNC(kcmy, color, 16) // kcmy_16_to_kcmy_desaturated GENERIC_COLOR_FUNC(kcmy, color_desaturated) DESATURATED_FUNC(kcmy, kcmy, 8) // kcmy_8_to_color_desaturated DESATURATED_FUNC(kcmy, kcmy, 16) // kcmy_16_to_kcmy_desaturated GENERIC_COLOR_FUNC(kcmy, kcmy_desaturated) #define CMYK_DISPATCH(name) \ CFUNC \ CMYK_to_##name(const stp_vars_t *vars, const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ if (lut->input_color_description->color_id == COLOR_ID_CMYK) \ return cmyk_to_##name(vars, in, out); \ else if (lut->input_color_description->color_id == COLOR_ID_KCMY) \ return kcmy_to_##name(vars, in, out); \ else \ { \ stp_eprintf(vars, "Bad dispatch to CMYK_to_%s: %d\n", #name, \ lut->input_color_description->color_id); \ return 0; \ } \ } CMYK_DISPATCH(color) /* CMYK_to_color */ CMYK_DISPATCH(color_raw) /* CMYK_to_color_raw */ CMYK_DISPATCH(color_fast) /* CMYK_to_color_fast */ CMYK_DISPATCH(color_threshold) /* CMYK_to_color_threshold */ CMYK_DISPATCH(color_desaturated) /* CMYK_to_color_desaturated */ CMYK_DISPATCH(kcmy) /* CMYK_to_kcmy */ CMYK_DISPATCH(kcmy_raw) /* CMYK_to_kcmy_raw */ CMYK_DISPATCH(kcmy_threshold) /* CMYK_to_kcmy_threshold */ CMYK_DISPATCH(kcmy_desaturated) /* CMYK_to_kcmy_desaturated */ CMYK_DISPATCH(gray) /* CMYK_to_gray */ CMYK_DISPATCH(gray_raw) /* CMYK_to_gray_raw */ CMYK_DISPATCH(gray_threshold) /* CMYK_to_gray_threshold */ #define RAW_TO_RAW_THRESHOLD_FUNC(T, name) \ CFUNC \ name##_to_raw_threshold(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int j; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ unsigned nz[STP_CHANNEL_LIMIT]; \ unsigned z = (1 << lut->out_channels) - 1; \ const T *s_in = (const T *) in; \ unsigned desired_high_bit = 0; \ unsigned high_bit = 1 << ((sizeof(T) * 8) - 1); \ int width = lut->image_width; \ memset(out, 0, width * lut->out_channels * sizeof(unsigned short)); \ if (!lut->invert_output) \ desired_high_bit = high_bit; \ for (i = 0; i < lut->out_channels; i++) \ nz[i] = z & ~(1 << i); \ \ for (i = 0; i < width; i++) \ { \ for (j = 0; j < lut->out_channels; j++) \ { \ if ((*s_in++ & high_bit) == desired_high_bit) \ { \ z &= nz[j]; \ *out = 65535; \ } \ out++; \ } \ } \ return z; \ } RAW_TO_RAW_THRESHOLD_FUNC(unsigned char, raw_8) // raw_8_to_raw_threshold RAW_TO_RAW_THRESHOLD_FUNC(unsigned short, raw_16) // raw_16_to_raw_threshold GENERIC_COLOR_FUNC(raw, raw_threshold) #define RAW_TO_RAW_FUNC(T, size) \ CFUNC \ raw_##size##_to_raw(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ unsigned retval = 0; \ int j; \ int nz[STP_CHANNEL_LIMIT]; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ const unsigned short *maps[STP_CHANNEL_LIMIT]; \ const unsigned short *user; \ \ for (i = 0; i < lut->out_channels; i++) \ { \ stp_curve_resample(lut->channel_curves[i].curve, 65536); \ maps[i] = stp_curve_cache_get_ushort_data(&(lut->channel_curves[i])); \ } \ stp_curve_resample(lut->user_color_correction.curve, 1 << size); \ user = stp_curve_cache_get_ushort_data(&(lut->user_color_correction)); \ \ memset(nz, 0, sizeof(nz)); \ \ for (i = 0; i < lut->image_width; i++, out += lut->out_channels) \ { \ for (j = 0; j < lut->out_channels; j++) \ { \ int inval = *s_in++; \ nz[j] |= inval; \ out[j] = maps[j][user[inval]]; \ } \ } \ for (j = 0; j < lut->out_channels; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } RAW_TO_RAW_FUNC(unsigned char, 8) // raw_8_to_raw RAW_TO_RAW_FUNC(unsigned short, 16) // raw_8_to_raw GENERIC_COLOR_FUNC(raw, raw) #define RAW_TO_RAW_RAW_FUNC(T, bits) \ CFUNC \ raw_##bits##_to_raw_raw(const stp_vars_t *vars, \ const unsigned char *in, \ unsigned short *out) \ { \ int i; \ int j; \ int nz[STP_CHANNEL_LIMIT]; \ unsigned retval = 0; \ const T *s_in = (const T *) in; \ lut_t *lut = (lut_t *)(stp_get_component_data(vars, "Color")); \ int colors = lut->in_channels; \ \ memset(nz, 0, sizeof(nz)); \ for (i = 0; i < lut->image_width; i++) \ { \ for (j = 0; j < colors; j++) \ { \ nz[j] |= s_in[j]; \ out[j] = s_in[j] * (65535 / ((1 << bits) - 1)); \ } \ s_in += colors; \ out += colors; \ } \ for (j = 0; j < colors; j++) \ if (nz[j] == 0) \ retval |= (1 << j); \ return retval; \ } RAW_TO_RAW_RAW_FUNC(unsigned char, 8) // raw_8_to_raw_raw RAW_TO_RAW_RAW_FUNC(unsigned short, 16) // raw_16_to_raw_raw GENERIC_COLOR_FUNC(raw, raw_raw) #define CONVERSION_FUNCTION_WITH_FAST(from, to, from2) \ CFUNC \ generic_##from##_to_##to(const stp_vars_t *v, \ const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); \ switch (lut->color_correction->correction) \ { \ case COLOR_CORRECTION_UNCORRECTED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_fast\n", #from2, #to); \ return from2##_to_##to##_fast(v, in, out); \ case COLOR_CORRECTION_ACCURATE: \ case COLOR_CORRECTION_BRIGHT: \ case COLOR_CORRECTION_HUE: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s\n", #from2, #to); \ return from2##_to_##to(v, in, out); \ case COLOR_CORRECTION_DESATURATED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_desaturated\n", #from2, #to); \ return from2##_to_##to##_desaturated(v, in, out); \ case COLOR_CORRECTION_THRESHOLD: \ case COLOR_CORRECTION_PREDITHERED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_threshold\n", #from2, #to); \ return from2##_to_##to##_threshold(v, in, out); \ case COLOR_CORRECTION_DENSITY: \ case COLOR_CORRECTION_RAW: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_raw\n", #from2, #to); \ return from2##_to_##to##_raw(v, in, out); \ default: \ return (unsigned) -1; \ } \ } #define CONVERSION_FUNCTION_WITHOUT_FAST(from, to, from2) \ CFUNC \ generic_##from##_to_##to(const stp_vars_t *v, \ const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); \ switch (lut->color_correction->correction) \ { \ case COLOR_CORRECTION_UNCORRECTED: \ case COLOR_CORRECTION_ACCURATE: \ case COLOR_CORRECTION_BRIGHT: \ case COLOR_CORRECTION_HUE: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s\n", #from2, #to); \ return from2##_to_##to(v, in, out); \ case COLOR_CORRECTION_DESATURATED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_desaturated\n", #from2, #to); \ return from2##_to_##to##_desaturated(v, in, out); \ case COLOR_CORRECTION_THRESHOLD: \ case COLOR_CORRECTION_PREDITHERED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_threshold\n", #from2, #to); \ return from2##_to_##to##_threshold(v, in, out); \ case COLOR_CORRECTION_DENSITY: \ case COLOR_CORRECTION_RAW: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_raw\n", #from2, #to); \ return from2##_to_##to##_raw(v, in, out); \ default: \ return (unsigned) -1; \ } \ } #define CONVERSION_FUNCTION_WITHOUT_DESATURATED(from, to, from2) \ CFUNC \ generic_##from##_to_##to(const stp_vars_t *v, \ const unsigned char *in, \ unsigned short *out) \ { \ lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); \ switch (lut->color_correction->correction) \ { \ case COLOR_CORRECTION_UNCORRECTED: \ case COLOR_CORRECTION_ACCURATE: \ case COLOR_CORRECTION_BRIGHT: \ case COLOR_CORRECTION_HUE: \ case COLOR_CORRECTION_DESATURATED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s\n", #from2, #to); \ return from2##_to_##to(v, in, out); \ case COLOR_CORRECTION_THRESHOLD: \ case COLOR_CORRECTION_PREDITHERED: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_threshold\n", #from2, #to); \ return from2##_to_##to##_threshold(v, in, out); \ case COLOR_CORRECTION_DENSITY: \ case COLOR_CORRECTION_RAW: \ stp_dprintf(STP_DBG_COLORFUNC, v, \ "Colorfunc: %s_to_%s_raw\n", #from2, #to); \ return from2##_to_##to##_raw(v, in, out); \ default: \ return (unsigned) -1; \ } \ } CONVERSION_FUNCTION_WITH_FAST(cmyk, color, CMYK) // generic_cmyk_to_color CONVERSION_FUNCTION_WITH_FAST(color, color, color) // generic_color_to_color CONVERSION_FUNCTION_WITH_FAST(color, kcmy, color) // generic_color_to_kcmy CONVERSION_FUNCTION_WITHOUT_FAST(cmyk, kcmy, CMYK) // generic_cmyk_to_kcmy CONVERSION_FUNCTION_WITHOUT_DESATURATED(cmyk, gray, CMYK) // generic_cmyk_to_gray CONVERSION_FUNCTION_WITHOUT_DESATURATED(color, gray, color) // generic_color_to_gray CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, gray, gray) // generic_gray_to_gray CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, color, gray) // generic_gray_to_color CONVERSION_FUNCTION_WITHOUT_DESATURATED(gray, kcmy, gray) // generic_gray_to_kcmy unsigned stpi_color_convert_to_gray(const stp_vars_t *v, const unsigned char *in, unsigned short *out) { lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); switch (lut->input_color_description->color_id) { case COLOR_ID_GRAY: case COLOR_ID_WHITE: return generic_gray_to_gray(v, in, out); case COLOR_ID_RGB: case COLOR_ID_CMY: return generic_color_to_gray(v, in, out); case COLOR_ID_CMYK: case COLOR_ID_KCMY: return generic_cmyk_to_gray(v, in, out); default: return (unsigned) -1; } } unsigned stpi_color_convert_to_color(const stp_vars_t *v, const unsigned char *in, unsigned short *out) { lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); switch (lut->input_color_description->color_id) { case COLOR_ID_GRAY: case COLOR_ID_WHITE: return generic_gray_to_color(v, in, out); case COLOR_ID_RGB: case COLOR_ID_CMY: return generic_color_to_color(v, in, out); case COLOR_ID_CMYK: case COLOR_ID_KCMY: return generic_cmyk_to_color(v, in, out); default: return (unsigned) -1; } } unsigned stpi_color_convert_to_kcmy(const stp_vars_t *v, const unsigned char *in, unsigned short *out) { lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); switch (lut->input_color_description->color_id) { case COLOR_ID_GRAY: case COLOR_ID_WHITE: return generic_gray_to_kcmy(v, in, out); case COLOR_ID_RGB: case COLOR_ID_CMY: return generic_color_to_kcmy(v, in, out); case COLOR_ID_CMYK: case COLOR_ID_KCMY: return generic_cmyk_to_kcmy(v, in, out); default: return (unsigned) -1; } } unsigned stpi_color_convert_raw(const stp_vars_t *v, const unsigned char *in, unsigned short *out) { lut_t *lut = (lut_t *)(stp_get_component_data(v, "Color")); switch (lut->color_correction->correction) { case COLOR_CORRECTION_THRESHOLD: case COLOR_CORRECTION_PREDITHERED: stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_threshold\n"); return raw_to_raw_threshold(v, in, out); case COLOR_CORRECTION_UNCORRECTED: case COLOR_CORRECTION_BRIGHT: case COLOR_CORRECTION_HUE: case COLOR_CORRECTION_ACCURATE: case COLOR_CORRECTION_DESATURATED: stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_desaturated\n"); return raw_to_raw(v, in, out); case COLOR_CORRECTION_RAW: case COLOR_CORRECTION_DEFAULT: case COLOR_CORRECTION_DENSITY: stp_dprintf(STP_DBG_COLORFUNC, v, "Colorfunc: raw_to_raw_raw\n"); return raw_to_raw_raw(v, in, out); default: return (unsigned) -1; } }