2 |
- |
1 |
/* Copyright (C) 1992, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gxdcconv.c,v 1.6 2002/08/22 07:12:29 henrys Exp $ */
|
|
|
18 |
/* Conversion between device color spaces for Ghostscript */
|
|
|
19 |
#include "gx.h"
|
|
|
20 |
#include "gsdcolor.h" /* for gxcmap.h */
|
|
|
21 |
#include "gxdcconv.h" /* interface */
|
|
|
22 |
#include "gxdevice.h" /* for gxcmap.h */
|
|
|
23 |
#include "gxcmap.h"
|
|
|
24 |
#include "gxfarith.h"
|
|
|
25 |
#include "gxlum.h"
|
|
|
26 |
#include "gxistate.h"
|
|
|
27 |
|
|
|
28 |
/*
|
|
|
29 |
* The CMYK to RGB algorithms specified by Adobe are, e.g.,
|
|
|
30 |
* R = 1.0 - min(1.0, C + K)
|
|
|
31 |
* C = max(0.0, min(1.0, 1 - R - UCR))
|
|
|
32 |
* We got better results on displays with
|
|
|
33 |
* R = (1.0 - C) * (1.0 - K)
|
|
|
34 |
* C = max(0.0, min(1.0, 1 - R / (1 - UCR)))
|
|
|
35 |
* For utmost compatibility, we offer the Adobe algorithms as an option:
|
|
|
36 |
*/
|
|
|
37 |
#define USE_ADOBE_CMYK_RGB
|
|
|
38 |
|
|
|
39 |
/* ------ Color space conversion ------ */
|
|
|
40 |
|
|
|
41 |
/* Only 4 of the 6 conversions are implemented here; */
|
|
|
42 |
/* the other 2 (Gray to RGB/CMYK) are trivial. */
|
|
|
43 |
|
|
|
44 |
/* Convert RGB to Gray. */
|
|
|
45 |
frac
|
|
|
46 |
color_rgb_to_gray(frac r, frac g, frac b, const gs_imager_state * pis)
|
|
|
47 |
{
|
|
|
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))
|
|
|
52 |
/ lum_all_weights;
|
|
|
53 |
}
|
|
|
54 |
|
|
|
55 |
/* Convert RGB to CMYK. */
|
|
|
56 |
/* Note that this involves black generation and undercolor removal. */
|
|
|
57 |
void
|
|
|
58 |
color_rgb_to_cmyk(frac r, frac g, frac b, const gs_imager_state * pis,
|
|
|
59 |
frac cmyk[4])
|
|
|
60 |
{
|
|
|
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));
|
|
|
63 |
|
|
|
64 |
/*
|
|
|
65 |
* The default UCR and BG functions are pretty arbitrary,
|
|
|
66 |
* but they must agree with the ones in gs_init.ps.
|
|
|
67 |
*/
|
|
|
68 |
frac bg =
|
|
|
69 |
(pis == NULL ? k : pis->black_generation == NULL ? frac_0 :
|
|
|
70 |
gx_map_color_frac(pis, k, black_generation));
|
|
|
71 |
signed_frac ucr =
|
|
|
72 |
(pis == NULL ? k : pis->undercolor_removal == NULL ? frac_0 :
|
|
|
73 |
gx_map_color_frac(pis, k, undercolor_removal));
|
|
|
74 |
|
|
|
75 |
if (ucr == frac_1)
|
|
|
76 |
cmyk[0] = cmyk[1] = cmyk[2] = 0;
|
|
|
77 |
else if (ucr == frac_0)
|
|
|
78 |
cmyk[0] = c, cmyk[1] = m, cmyk[2] = y;
|
|
|
79 |
else {
|
|
|
80 |
#ifdef USE_ADOBE_CMYK_RGB
|
|
|
81 |
/* C = max(0.0, min(1.0, 1 - R - UCR)), etc. */
|
|
|
82 |
signed_frac not_ucr = (ucr < 0 ? frac_1 + ucr : frac_1);
|
|
|
83 |
|
|
|
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);
|
|
|
87 |
#else
|
|
|
88 |
/* C = max(0.0, min(1.0, 1 - R / (1 - UCR))), etc. */
|
|
|
89 |
float denom = frac2float(frac_1 - ucr); /* unscaled */
|
|
|
90 |
float v;
|
|
|
91 |
|
|
|
92 |
v = (float)frac_1 - r / denom; /* unscaled */
|
|
|
93 |
cmyk[0] =
|
|
|
94 |
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
|
|
|
95 |
v = (float)frac_1 - g / denom; /* unscaled */
|
|
|
96 |
cmyk[1] =
|
|
|
97 |
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
|
|
|
98 |
v = (float)frac_1 - b / denom; /* unscaled */
|
|
|
99 |
cmyk[2] =
|
|
|
100 |
(is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
|
|
|
101 |
#endif
|
|
|
102 |
}
|
|
|
103 |
cmyk[3] = bg;
|
|
|
104 |
if_debug7('c', "[c]RGB 0x%x,0x%x,0x%x -> CMYK 0x%x,0x%x,0x%x,0x%x\n",
|
|
|
105 |
r, g, b, cmyk[0], cmyk[1], cmyk[2], cmyk[3]);
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
/* Convert CMYK to Gray. */
|
|
|
109 |
frac
|
|
|
110 |
color_cmyk_to_gray(frac c, frac m, frac y, frac k, const gs_imager_state * pis)
|
|
|
111 |
{
|
|
|
112 |
frac not_gray = color_rgb_to_gray(c, m, y, pis);
|
|
|
113 |
|
|
|
114 |
return (not_gray > frac_1 - k ? /* gray + k > 1.0 */
|
|
|
115 |
frac_0 : frac_1 - (not_gray + k));
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
/* Convert CMYK to RGB. */
|
|
|
119 |
void
|
|
|
120 |
color_cmyk_to_rgb(frac c, frac m, frac y, frac k, const gs_imager_state * pis,
|
|
|
121 |
frac rgb[3])
|
|
|
122 |
{
|
|
|
123 |
switch (k) {
|
|
|
124 |
case frac_0:
|
|
|
125 |
rgb[0] = frac_1 - c;
|
|
|
126 |
rgb[1] = frac_1 - m;
|
|
|
127 |
rgb[2] = frac_1 - y;
|
|
|
128 |
break;
|
|
|
129 |
case frac_1:
|
|
|
130 |
rgb[0] = rgb[1] = rgb[2] = frac_0;
|
|
|
131 |
break;
|
|
|
132 |
default:
|
|
|
133 |
{
|
|
|
134 |
#ifdef USE_ADOBE_CMYK_RGB
|
|
|
135 |
/* R = 1.0 - min(1.0, C + K), etc. */
|
|
|
136 |
frac not_k = frac_1 - k;
|
|
|
137 |
|
|
|
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);
|
|
|
141 |
#else
|
|
|
142 |
/* R = (1.0 - C) * (1.0 - K), etc. */
|
|
|
143 |
ulong not_k = frac_1 - k;
|
|
|
144 |
|
|
|
145 |
/* Compute not_k * (frac_1 - v) / frac_1 efficiently. */
|
|
|
146 |
ulong prod;
|
|
|
147 |
|
|
|
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);
|
|
|
153 |
#undef deduct_black
|
|
|
154 |
#endif
|
|
|
155 |
}
|
|
|
156 |
}
|
|
|
157 |
if_debug7('c', "[c]CMYK 0x%x,0x%x,0x%x,0x%x -> RGB 0x%x,0x%x,0x%x\n",
|
|
|
158 |
c, m, y, k, rgb[0], rgb[1], rgb[2]);
|
|
|
159 |
}
|