1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gxdcconv.c 8022 2007-06-05 22:23:38Z giles $ */
15
/* Conversion between device color spaces for Ghostscript */
17
#include "gsdcolor.h" /* for gxcmap.h */
18
#include "gxdcconv.h" /* interface */
19
#include "gxdevice.h" /* for gxcmap.h */
25
extern bool CPSI_mode; /* not worth polluting a header file */
28
* The CMYK to RGB algorithms specified by Adobe are, e.g.,
29
* R = 1.0 - min(1.0, C + K)
30
* C = max(0.0, min(1.0, 1 - R - UCR))
31
* We got better results on displays with
32
* R = (1.0 - C) * (1.0 - K)
33
* C = max(0.0, min(1.0, 1 - R / (1 - UCR)))
34
* For PLRM compatibility, we use the Adobe algorithms by default,
35
* but what Adobe says and what they do are two different things.
36
* Testing on CPSI shows that they use the 'better' algorithm.
39
/* ------ Color space conversion ------ */
41
/* Only 4 of the 6 conversions are implemented here; */
42
/* the other 2 (Gray to RGB/CMYK) are trivial. */
44
/* Convert RGB to Gray. */
46
color_rgb_to_gray(frac r, frac g, frac b, const gs_imager_state * pis)
48
return (r * (unsigned long)lum_red_weight +
49
g * (unsigned long)lum_green_weight +
50
b * (unsigned long)lum_blue_weight +
51
(lum_all_weights / 2))
55
/* Convert RGB to CMYK. */
56
/* Note that this involves black generation and undercolor removal. */
58
color_rgb_to_cmyk(frac r, frac g, frac b, const gs_imager_state * pis,
61
frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
62
frac k = (c < m ? min(c, y) : min(m, y));
65
* The default UCR and BG functions are pretty arbitrary,
66
* but they must agree with the ones in gs_init.ps.
69
(pis == NULL ? k : pis->black_generation == NULL ? frac_0 :
70
gx_map_color_frac(pis, k, black_generation));
72
(pis == NULL ? k : pis->undercolor_removal == NULL ? frac_0 :
73
gx_map_color_frac(pis, k, undercolor_removal));
76
cmyk[0] = cmyk[1] = cmyk[2] = 0;
77
else if (ucr == frac_0)
78
cmyk[0] = c, cmyk[1] = m, cmyk[2] = y;
81
/* C = max(0.0, min(1.0, 1 - R - UCR)), etc. */
82
signed_frac not_ucr = (ucr < 0 ? frac_1 + ucr : frac_1);
84
cmyk[0] = (c < ucr ? frac_0 : c > not_ucr ? frac_1 : c - ucr);
85
cmyk[1] = (m < ucr ? frac_0 : m > not_ucr ? frac_1 : m - ucr);
86
cmyk[2] = (y < ucr ? frac_0 : y > not_ucr ? frac_1 : y - ucr);
88
/* Adobe CPSI method */
89
/* C = max(0.0, min(1.0, 1 - R / (1 - UCR))), etc. */
90
float denom = frac2float(frac_1 - ucr); /* unscaled */
93
v = (float)frac_1 - r / denom; /* unscaled */
95
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
96
v = (float)frac_1 - g / denom; /* unscaled */
98
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
99
v = (float)frac_1 - b / denom; /* unscaled */
101
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
105
if_debug7('c', "[c]RGB 0x%x,0x%x,0x%x -> CMYK 0x%x,0x%x,0x%x,0x%x\n",
106
r, g, b, cmyk[0], cmyk[1], cmyk[2], cmyk[3]);
109
/* Convert CMYK to Gray. */
111
color_cmyk_to_gray(frac c, frac m, frac y, frac k, const gs_imager_state * pis)
113
frac not_gray = color_rgb_to_gray(c, m, y, pis);
115
return (not_gray > frac_1 - k ? /* gray + k > 1.0 */
116
frac_0 : frac_1 - (not_gray + k));
119
/* Convert CMYK to RGB. */
121
color_cmyk_to_rgb(frac c, frac m, frac y, frac k, const gs_imager_state * pis,
131
rgb[0] = rgb[1] = rgb[2] = frac_0;
135
/* R = 1.0 - min(1.0, C + K), etc. */
136
frac not_k = frac_1 - k;
138
rgb[0] = (c > not_k ? frac_0 : not_k - c);
139
rgb[1] = (m > not_k ? frac_0 : not_k - m);
140
rgb[2] = (y > not_k ? frac_0 : not_k - y);
142
/* R = (1.0 - C) * (1.0 - K), etc. */
143
ulong not_k = frac_1 - k;
145
/* Compute not_k * (frac_1 - v) / frac_1 efficiently. */
148
#define deduct_black(v)\
149
(prod = (frac_1 - (v)) * not_k, frac_1_quo(prod))
150
rgb[0] = deduct_black(c);
151
rgb[1] = deduct_black(m);
152
rgb[2] = deduct_black(y);
156
if_debug7('c', "[c]CMYK 0x%x,0x%x,0x%x,0x%x -> RGB 0x%x,0x%x,0x%x\n",
157
c, m, y, k, rgb[0], rgb[1], rgb[2]);