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
color_rgb_to_gray(frac r,frac g,frac b,const gs_imager_state * pis)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
color_rgb_to_cmyk(frac r,frac g,frac b,const gs_imager_state * pis,frac cmyk[4])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
color_cmyk_to_gray(frac c,frac m,frac y,frac k,const gs_imager_state * pis)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
color_cmyk_to_rgb(frac c,frac m,frac y,frac k,const gs_imager_state * pis,frac rgb[3])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 }
160