1 /* Copyright (C) 1989, 1995, 1996, 1998, 1999 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: gxdevndi.c,v 1.6 2005/05/05 05:35:22 dan Exp $ */
18 #include "gx.h"
19 #include "gsstruct.h"
20 #include "gsdcolor.h"
21 #include "gxdevice.h"
22 #include "gxlum.h"
23 #include "gxcmap.h"
24 #include "gxdither.h"
25 #include "gzht.h"
26 #include "gxfrac.h"
27 #include "gxwts.h"
28
29 /*
30 * Binary halftoning algorithms.
31 *
32 * The procedures in this file use halftoning (if necessary)
33 * to implement a given device color that has already gone through
34 * the transfer function. There are two major cases: gray and color.
35 * Gray halftoning always uses a binary screen. Color halftoning
36 * uses either a fast algorithm with a binary screen that produces
37 * relatively poor approximations, or a very slow algorithm with a
38 * general colored screen (or screens) that faithfully implements
39 * the Adobe specifications.
40 */
41
42 /* Tables for fast computation of fractional color levels. */
43 /* We have to put the table before any uses of it because of a bug */
44 /* in the VAX C compiler. */
45 /* We have to split up the definition of the table itself because of a bug */
46 /* in the IBM AIX 3.2 C compiler. */
47 private const gx_color_value q0[] = {
48 0
49 };
50 private const gx_color_value q1[] = {
51 0, frac_color_(1, 1)
52 };
53 private const gx_color_value q2[] = {
54 0, frac_color_(1, 2), frac_color_(2, 2)
55 };
56 private const gx_color_value q3[] = {
57 0, frac_color_(1, 3), frac_color_(2, 3), frac_color_(3, 3)
58 };
59 private const gx_color_value q4[] = {
60 0, frac_color_(1, 4), frac_color_(2, 4), frac_color_(3, 4),
61 frac_color_(4, 4)
62 };
63 private const gx_color_value q5[] = {
64 0, frac_color_(1, 5), frac_color_(2, 5), frac_color_(3, 5),
65 frac_color_(4, 5), frac_color_(5, 5)
66 };
67 private const gx_color_value q6[] = {
68 0, frac_color_(1, 6), frac_color_(2, 6), frac_color_(3, 6),
69 frac_color_(4, 6), frac_color_(5, 6), frac_color_(6, 6)
70 };
71 private const gx_color_value q7[] = {
72 0, frac_color_(1, 7), frac_color_(2, 7), frac_color_(3, 7),
73 frac_color_(4, 7), frac_color_(5, 7), frac_color_(6, 7), frac_color_(7, 7)
74 };
75
76 /* We export fc_color_quo for the fractional_color macro in gzht.h. */
77 const gx_color_value *const fc_color_quo[8] = {
78 q0, q1, q2, q3, q4, q5, q6, q7
79 };
80
81 /* Begin code for setting up WTS device color. This should probably
82 move into its own module. */
83
84 /**
85 * gx_render_device_DevN_wts: Render DeviceN color by halftoning with WTS.
86 *
87 * This routine is the primary constructor for WTS device colors.
88 * Note that, in the WTS code path, we sample the plane_vector array
89 * during device color construction, while in the legacy code path,
90 * it is sampled in the set_ht_colors procedure, invoked from
91 * fill_rectangle. Does it affect correctness? I don't think so, but
92 * it needs to be tested.
93 **/
94 private int
gx_render_device_DeviceN_wts(frac * pcolor,gx_device_color * pdevc,gx_device * dev,gx_device_halftone * pdht,const gs_int_point * ht_phase)95 gx_render_device_DeviceN_wts(frac * pcolor,
96 gx_device_color * pdevc, gx_device * dev,
97 gx_device_halftone * pdht,
98 const gs_int_point * ht_phase)
99 {
100 int i;
101 gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
102 int num_comp = pdht->num_comp;
103
104 for (i = 0; i < num_comp; i++) {
105 cv[i] = 0;
106 }
107
108 pdevc->type = gx_dc_type_wts;
109 pdevc->colors.wts.w_ht = pdht;
110
111 if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN) {
112 /* Monochrome case may be inverted. */
113 pdevc->colors.wts.plane_vector[1] =
114 dev_proc(dev, encode_color)(dev, cv);
115 }
116 for (i = 0; i < num_comp; i++) {
117 pdevc->colors.wts.levels[i] = pcolor[i];
118 cv[i] = gx_max_color_value;
119 pdevc->colors.wts.plane_vector[i] =
120 dev_proc(dev, encode_color)(dev, cv);
121 cv[i] = 0;
122 }
123 pdevc->colors.wts.num_components = num_comp;
124 return 0;
125 }
126
127 /*
128 * Render DeviceN possibly by halftoning.
129 * pcolors = pointer to an array color values (as fracs)
130 * pdevc - pointer to device color structure
131 * dev = pointer to device data structure
132 * pht = pointer to halftone data structure
133 * ht_phase = halftone phase
134 * gray_colorspace = true -> current color space is DeviceGray.
135 * This is part of a kludge to minimize differences in the
136 * regression testing.
137 */
138 int
gx_render_device_DeviceN(frac * pcolor,gx_device_color * pdevc,gx_device * dev,gx_device_halftone * pdht,const gs_int_point * ht_phase)139 gx_render_device_DeviceN(frac * pcolor,
140 gx_device_color * pdevc, gx_device * dev,
141 gx_device_halftone * pdht, const gs_int_point * ht_phase)
142 {
143 uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
144 frac dither_check = 0;
145 uint int_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
146 gx_color_value vcolor[GS_CLIENT_COLOR_MAX_COMPONENTS];
147 int i;
148 int num_colors = dev->color_info.num_components;
149 uint l_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
150
151 if (pdht && pdht->components && pdht->components[0].corder.wts)
152 return gx_render_device_DeviceN_wts(pcolor, pdevc, dev, pdht,
153 ht_phase);
154
155 for (i=0; i<num_colors; i++) {
156 max_value[i] = (dev->color_info.gray_index == i) ?
157 dev->color_info.dither_grays - 1 :
158 dev->color_info.dither_colors - 1;
159 }
160
161 for (i = 0; i < num_colors; i++) {
162 unsigned long hsize = pdht ?
163 (unsigned) pdht->components[i].corder.num_levels
164 : 1;
165 unsigned long nshades = hsize * max_value[i] + 1;
166 long shade = pcolor[i] * nshades / (frac_1_long + 1);
167 int_color[i] = shade / hsize;
168 l_color[i] = shade % hsize;
169 if (max_value[i] < MIN_CONTONE_LEVELS)
170 dither_check |= l_color[i];
171 }
172
173 #ifdef DEBUG
174 if (gs_debug_c('c')) {
175 dlprintf1("[c]ncomp=%d ", num_colors);
176 for (i = 0; i < num_colors; i++)
177 dlprintf1("0x%x, ", pcolor[i]);
178 dlprintf("--> ");
179 for (i = 0; i < num_colors; i++)
180 dlprintf2("%x+0x%x, ", int_color[i], l_color[i]);
181 dlprintf("\n");
182 }
183 #endif
184
185 /* Check for no dithering required */
186 if (!dither_check) {
187 for (i = 0; i < num_colors; i++)
188 vcolor[i] = fractional_color(int_color[i], max_value[i]);
189 color_set_pure(pdevc, dev_proc(dev, encode_color)(dev, vcolor));
190 return 0;
191 }
192
193 /* Use the slow, general colored halftone algorithm. */
194
195 for (i = 0; i < num_colors; i++)
196 _color_set_c(pdevc, i, int_color[i], l_color[i]);
197 gx_complete_halftone(pdevc, num_colors, pdht);
198
199 color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
200 pdht->lcm_width, pdht->lcm_height);
201
202 /* Determine if we are using only one component */
203 if (!(pdevc->colors.colored.plane_mask &
204 (pdevc->colors.colored.plane_mask - 1))) {
205 /* We can reduce this color to a binary halftone or pure color. */
206 return gx_devn_reduce_colored_halftone(pdevc, dev);
207 }
208
209 return 1;
210 }
211
212 /* Reduce a colored halftone to a binary halftone or pure color. */
213 /* This routine is called when only one component is being halftoned. */
214 int
gx_devn_reduce_colored_halftone(gx_device_color * pdevc,gx_device * dev)215 gx_devn_reduce_colored_halftone(gx_device_color *pdevc, gx_device *dev)
216 {
217 int planes = pdevc->colors.colored.plane_mask;
218 int num_colors = dev->color_info.num_components;
219 uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
220 uint b[GX_DEVICE_COLOR_MAX_COMPONENTS];
221 gx_color_value v[GX_DEVICE_COLOR_MAX_COMPONENTS];
222 gx_color_index c0, c1;
223 int i;
224
225 for (i = 0; i < num_colors; i++) {
226 max_value[i] = (dev->color_info.gray_index == i) ?
227 dev->color_info.dither_grays - 1 :
228 dev->color_info.dither_colors - 1;
229 b[i] = pdevc->colors.colored.c_base[i];
230 v[i] = fractional_color(b[i], max_value[i]);
231 }
232 c0 = dev_proc(dev, encode_color)(dev, v);
233
234 if (planes == 0) {
235 /*
236 * Use a pure color. This case is unlikely, but it can occur if
237 * (and only if) the difference of each component from the nearest
238 * device color is less than one halftone level.
239 */
240 color_set_pure(pdevc, c0);
241 return 0;
242 } else {
243 /* Use a binary color. */
244 int i = 0;
245 uint bi;
246 const gx_device_halftone *pdht = pdevc->colors.colored.c_ht;
247 /*
248 * NB: the halftone orders are all set up for an additive color
249 * space. To use these work with a subtractive color space, it is
250 * necessary to invert both the color level and the color
251 * pair. Note that if the original color was provided an
252 * additive space, this will reverse (in an approximate sense)
253 * the color conversion performed to express the color in
254 * subtractive space.
255 */
256 bool invert = dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE;
257 uint level;
258
259 /* Convert plane mask bit position to component number */
260 /* Determine i = log2(planes); This works for powers of two */
261 while (planes > 7) {
262 i += 3;
263 planes >>= 3;
264 }
265 i += planes >> 1; /* log2 for 1,2,4 */
266
267 bi = b[i] + 1;
268 v[i] = fractional_color(bi, max_value[i]);
269 level = pdevc->colors.colored.c_level[i];
270 c1 = dev_proc(dev, encode_color)(dev, v);
271 if (invert) {
272 level = pdht->components[i].corder.num_levels - level;
273 color_set_binary_halftone_component(pdevc, pdht, i, c1, c0, level);
274 } else
275 color_set_binary_halftone_component(pdevc, pdht, i, c0, c1, level);
276
277 return 1;
278 }
279 }
280