/*
*
* 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;
}
}