/src/ghostpdl/base/gxcmap.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Color mapping for Ghostscript */ |
18 | | #include "assert_.h" |
19 | | #include "gx.h" |
20 | | #include "gserrors.h" |
21 | | #include "gsccolor.h" |
22 | | #include "gxalpha.h" |
23 | | #include "gxcspace.h" |
24 | | #include "gxfarith.h" |
25 | | #include "gxfrac.h" |
26 | | #include "gxdcconv.h" |
27 | | #include "gxdevice.h" |
28 | | #include "gxcmap.h" |
29 | | #include "gxlum.h" |
30 | | #include "gzstate.h" |
31 | | #include "gzht.h" |
32 | | #include "gxdither.h" |
33 | | #include "gxcdevn.h" |
34 | | #include "string_.h" |
35 | | #include "gsicc_manage.h" |
36 | | #include "gdevdevn.h" |
37 | | #include "gsicc_cache.h" |
38 | | #include "gscms.h" |
39 | | #include "gsicc.h" |
40 | | #include "gxdevsop.h" |
41 | | |
42 | | /* If enabled, this makes use of the alternate transform |
43 | | ICC profile for mapping separation and |
44 | | DeviceN colorants from CMYK to output |
45 | | ICC color space iff the profiles make |
46 | | sense. We should probably make this yet |
47 | | another color command line option. Disabling |
48 | | it for now for the current release. */ |
49 | 919k | #define USE_ALT_MAP 0 |
50 | | |
51 | | /* Structure descriptor */ |
52 | | public_st_device_color(); |
53 | | static |
54 | 38.0M | ENUM_PTRS_WITH(device_color_enum_ptrs, gx_device_color *cptr) |
55 | 38.0M | { |
56 | 38.0M | return ENUM_USING(*cptr->type->stype, vptr, size, index); |
57 | 0 | } |
58 | 38.0M | ENUM_PTRS_END |
59 | 37.8M | static RELOC_PTRS_WITH(device_color_reloc_ptrs, gx_device_color *cptr) |
60 | 37.8M | { |
61 | 37.8M | RELOC_USING(*cptr->type->stype, vptr, size); |
62 | 37.8M | } |
63 | 37.8M | RELOC_PTRS_END |
64 | | |
65 | | gx_color_index |
66 | | gx_default_encode_color(gx_device * dev, const gx_color_value cv[]) |
67 | 0 | { |
68 | 0 | uchar ncomps = dev->color_info.num_components; |
69 | 0 | uchar i; |
70 | 0 | const byte * comp_shift = dev->color_info.comp_shift; |
71 | 0 | const byte * comp_bits = dev->color_info.comp_bits; |
72 | 0 | gx_color_index color = 0; |
73 | |
|
74 | | #ifdef DEBUG |
75 | | if (!colors_are_separable_and_linear(&dev->color_info)) { |
76 | | dmprintf(dev->memory, "gx_default_encode_color() requires separable and linear\n" ); |
77 | | return gx_no_color_index; |
78 | | } |
79 | | #endif |
80 | 0 | for (i = 0; i < ncomps; i++) { |
81 | 0 | COLROUND_VARS; |
82 | 0 | COLROUND_SETUP(comp_bits[i]); |
83 | 0 | color |= COLROUND_ROUND(cv[i]) << comp_shift[i]; |
84 | |
|
85 | 0 | } |
86 | 0 | return color; |
87 | 0 | } |
88 | | |
89 | | /* |
90 | | * This routine is only used if the device is 'separable'. See |
91 | | * separable_and_linear in gxdevcli.h for more information. |
92 | | */ |
93 | | int |
94 | | gx_default_decode_color(gx_device * dev, gx_color_index color, gx_color_value cv[]) |
95 | 0 | { |
96 | 0 | uchar ncomps = dev->color_info.num_components; |
97 | 0 | uchar i; |
98 | 0 | const byte * comp_shift = dev->color_info.comp_shift; |
99 | 0 | const byte * comp_bits = dev->color_info.comp_bits; |
100 | 0 | const gx_color_index * comp_mask = dev->color_info.comp_mask; |
101 | 0 | uint shift, ivalue, nbits, scale; |
102 | |
|
103 | | #ifdef DEBUG |
104 | | if (!colors_are_separable_and_linear(&dev->color_info)) { |
105 | | dmprintf(dev->memory, "gx_default_decode_color() requires separable and linear\n" ); |
106 | | return_error(gs_error_rangecheck); |
107 | | } |
108 | | #endif |
109 | |
|
110 | 0 | for (i = 0; i < ncomps; i++) { |
111 | | /* |
112 | | * Convert from the gx_color_index bits to a gx_color_value. |
113 | | * Split the conversion into an integer and a fraction calculation |
114 | | * so we can do integer arthmetic. The calculation is equivalent |
115 | | * to floor(0xffff.fffff * ivalue / ((1 << nbits) - 1)) |
116 | | */ |
117 | 0 | nbits = comp_bits[i]; |
118 | 0 | scale = gx_max_color_value / ((1 << nbits) - 1); |
119 | 0 | ivalue = (color & comp_mask[i]) >> comp_shift[i]; |
120 | 0 | cv[i] = ivalue * scale; |
121 | | /* |
122 | | * Since our scaling factor is an integer, we lost the fraction. |
123 | | * Determine what part of the ivalue that the faction would have |
124 | | * added into the result. |
125 | | */ |
126 | 0 | shift = nbits - (gx_color_value_bits % nbits); |
127 | 0 | cv[i] += ivalue >> shift; |
128 | 0 | } |
129 | 0 | return 0; |
130 | 0 | } |
131 | | |
132 | | gx_color_index |
133 | | gx_error_encode_color(gx_device * dev, const gx_color_value colors[]) |
134 | 0 | { |
135 | | #ifdef DEBUG |
136 | | /* The "null" device is expected to be missing encode_color */ |
137 | | if (strcmp(dev->dname, "null") != 0) |
138 | | dmprintf(dev->memory, "No encode_color proc defined for device.\n"); |
139 | | #endif |
140 | 0 | return gx_no_color_index; |
141 | 0 | } |
142 | | |
143 | | int |
144 | | gx_error_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[]) |
145 | 0 | { |
146 | 0 | int i=dev->color_info.num_components; |
147 | |
|
148 | | #ifdef DEBUG |
149 | | dmprintf(dev->memory, "No decode_color proc defined for device.\n"); |
150 | | #endif |
151 | 0 | for(; i>=0; i--) |
152 | 0 | colors[i] = 0; |
153 | 0 | return_error(gs_error_rangecheck); |
154 | 0 | } |
155 | | |
156 | | /* |
157 | | * The "back-stop" default encode_color method. This will be used only |
158 | | * if no applicable color encoding procedure is provided, and the number |
159 | | * of color model components is 1. The encoding is presumed to induce an |
160 | | * additive color model (DeviceGray). |
161 | | * |
162 | | * The particular method employed is a trivial generalization of the |
163 | | * default map_rgb_color method used in the pre-DeviceN code (this was |
164 | | * known as gx_default_w_b_map_rgb_color). Since the DeviceRGB color |
165 | | * model is assumed additive, any of the procedures used as a default |
166 | | * map_rgb_color method are assumed to induce an additive color model. |
167 | | * gx_default_w_b_map_rgb_color mapped white to 1 and black to 0, so |
168 | | * the new procedure is set up with zero-base and positive slope as well. |
169 | | * The generalization is the use of depth; the earlier procedure assumed |
170 | | * a bi-level device. |
171 | | * |
172 | | * Two versions of this procedure are provided, the first of which |
173 | | * applies if max_gray == 2^depth - 1 and is faster, while the second |
174 | | * applies to the general situation. Note that, as with the encoding |
175 | | * procedures used in the pre-DeviceN code, both of these methods induce |
176 | | * a small rounding error if 1 < depth < gx_color_value_bits. |
177 | | */ |
178 | | gx_color_index |
179 | | gx_default_gray_fast_encode(gx_device * dev, const gx_color_value cv[]) |
180 | 2.47M | { |
181 | 2.47M | COLROUND_VARS; |
182 | 2.47M | COLROUND_SETUP(dev->color_info.depth); |
183 | 2.47M | return COLROUND_ROUND(cv[0]); |
184 | 2.47M | } |
185 | | |
186 | | gx_color_index |
187 | | gx_default_gray_encode(gx_device * dev, const gx_color_value cv[]) |
188 | 0 | { |
189 | 0 | return (gx_color_index)(cv[0]) * (dev->color_info.max_gray + 1) / (gx_max_color_value + 1); |
190 | 0 | } |
191 | | |
192 | | /** |
193 | | * This routine is provided for old devices which provide a |
194 | | * map_rgb_color routine but not encode_color. New devices are |
195 | | * encouraged either to use the defaults or to set encode_color rather |
196 | | * than map_rgb_color. |
197 | | **/ |
198 | | gx_color_index |
199 | | gx_backwards_compatible_gray_encode(gx_device *dev, |
200 | | const gx_color_value cv[]) |
201 | 9.25M | { |
202 | 9.25M | gx_color_value gray_val = cv[0]; |
203 | 9.25M | gx_color_value rgb_cv[3]; |
204 | | |
205 | 9.25M | rgb_cv[0] = gray_val; |
206 | 9.25M | rgb_cv[1] = gray_val; |
207 | 9.25M | rgb_cv[2] = gray_val; |
208 | 9.25M | return (*dev_proc(dev, map_rgb_color))(dev, rgb_cv); |
209 | 9.25M | } |
210 | | |
211 | | /* -------- Default color space to color model conversion routines -------- */ |
212 | | |
213 | | void |
214 | | gray_cs_to_gray_cm(const gx_device * dev, frac gray, frac out[]) |
215 | 52.4M | { |
216 | 52.4M | out[0] = gray; |
217 | 52.4M | } |
218 | | |
219 | | static void |
220 | | rgb_cs_to_gray_cm(const gx_device * dev, const gs_gstate *pgs, |
221 | | frac r, frac g, frac b, frac out[]) |
222 | 25.2k | { |
223 | 25.2k | out[0] = color_rgb_to_gray(r, g, b, NULL); |
224 | 25.2k | } |
225 | | |
226 | | static void |
227 | | cmyk_cs_to_gray_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
228 | 5.77k | { |
229 | 5.77k | out[0] = color_cmyk_to_gray(c, m, y, k, NULL); |
230 | 5.77k | } |
231 | | |
232 | | static void |
233 | | gray_cs_to_rgb_cm(const gx_device * dev, frac gray, frac out[]) |
234 | 222k | { |
235 | 222k | out[0] = out[1] = out[2] = gray; |
236 | 222k | } |
237 | | |
238 | | void |
239 | | rgb_cs_to_rgb_cm(const gx_device * dev, const gs_gstate *pgs, |
240 | | frac r, frac g, frac b, frac out[]) |
241 | 1.14G | { |
242 | 1.14G | out[0] = r; |
243 | 1.14G | out[1] = g; |
244 | 1.14G | out[2] = b; |
245 | 1.14G | } |
246 | | |
247 | | static void |
248 | | cmyk_cs_to_rgb_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
249 | 0 | { |
250 | 0 | color_cmyk_to_rgb(c, m, y, k, NULL, out, dev->memory); |
251 | 0 | } |
252 | | |
253 | | static void |
254 | | gray_cs_to_rgbk_cm(const gx_device * dev, frac gray, frac out[]) |
255 | 0 | { |
256 | 0 | out[0] = out[1] = out[2] = frac_0; |
257 | 0 | out[3] = gray; |
258 | 0 | } |
259 | | |
260 | | static void |
261 | | rgb_cs_to_rgbk_cm(const gx_device * dev, const gs_gstate *pgs, |
262 | | frac r, frac g, frac b, frac out[]) |
263 | 0 | { |
264 | 0 | if ((r == g) && (g == b)) { |
265 | 0 | out[0] = out[1] = out[2] = frac_0; |
266 | 0 | out[3] = r; |
267 | 0 | } |
268 | 0 | else { |
269 | 0 | out[0] = r; |
270 | 0 | out[1] = g; |
271 | 0 | out[2] = b; |
272 | 0 | out[3] = frac_0; |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | | static void |
277 | | cmyk_cs_to_rgbk_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
278 | 0 | { |
279 | 0 | frac rgb[3]; |
280 | 0 | if ((c == frac_0) && (m == frac_0) && (y == frac_0)) { |
281 | 0 | out[0] = out[1] = out[2] = frac_0; |
282 | 0 | out[3] = frac_1 - k; |
283 | 0 | } |
284 | 0 | else { |
285 | 0 | color_cmyk_to_rgb(c, m, y, k, NULL, rgb, dev->memory); |
286 | 0 | rgb_cs_to_rgbk_cm(dev, NULL, rgb[0], rgb[1], rgb[2], out); |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | | static void |
291 | | gray_cs_to_cmyk_cm(const gx_device * dev, frac gray, frac out[]) |
292 | 36 | { |
293 | 36 | out[0] = out[1] = out[2] = frac_0; |
294 | 36 | out[3] = frac_1 - gray; |
295 | 36 | } |
296 | | |
297 | | /* |
298 | | * Default map from DeviceRGB color space to DeviceCMYK color |
299 | | * model. Since this mapping is defined by the PostScript language |
300 | | * it is unlikely that any device with a DeviceCMYK color model |
301 | | * would define this mapping on its own. |
302 | | * |
303 | | * If the gs_gstate is not available, map as though the black |
304 | | * generation and undercolor removal functions are identity |
305 | | * transformations. This mode is used primarily to support the |
306 | | * raster operation (rop) feature of PCL, which requires that |
307 | | * the raster operation be performed in an RGB color space. |
308 | | * Note that default black generation and undercolor removal |
309 | | * functions in PostScript need NOT be identity transformations: |
310 | | * often they are { pop 0 }. |
311 | | */ |
312 | | static void |
313 | | rgb_cs_to_cmyk_cm(const gx_device * dev, const gs_gstate *pgs, |
314 | | frac r, frac g, frac b, frac out[]) |
315 | 0 | { |
316 | 0 | if (pgs != 0) |
317 | 0 | color_rgb_to_cmyk(r, g, b, pgs, out, dev->memory); |
318 | 0 | else { |
319 | 0 | frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b; |
320 | 0 | frac k = min(c, min(m, y)); |
321 | |
|
322 | 0 | out[0] = c - k; |
323 | 0 | out[1] = m - k; |
324 | 0 | out[2] = y - k; |
325 | 0 | out[3] = k; |
326 | 0 | } |
327 | 0 | } |
328 | | |
329 | | void |
330 | | cmyk_cs_to_cmyk_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
331 | 22.9M | { |
332 | 22.9M | out[0] = c; |
333 | 22.9M | out[1] = m; |
334 | 22.9M | out[2] = y; |
335 | 22.9M | out[3] = k; |
336 | 22.9M | } |
337 | | |
338 | | /* The list of default color space to color model conversion routines. */ |
339 | | |
340 | | static const gx_cm_color_map_procs DeviceGray_procs = { |
341 | | gray_cs_to_gray_cm, rgb_cs_to_gray_cm, cmyk_cs_to_gray_cm |
342 | | }; |
343 | | |
344 | | static const gx_cm_color_map_procs DeviceRGB_procs = { |
345 | | gray_cs_to_rgb_cm, rgb_cs_to_rgb_cm, cmyk_cs_to_rgb_cm |
346 | | }; |
347 | | |
348 | | static const gx_cm_color_map_procs DeviceCMYK_procs = { |
349 | | gray_cs_to_cmyk_cm, rgb_cs_to_cmyk_cm, cmyk_cs_to_cmyk_cm |
350 | | }; |
351 | | |
352 | | static const gx_cm_color_map_procs DeviceRGBK_procs = { |
353 | | gray_cs_to_rgbk_cm, rgb_cs_to_rgbk_cm, cmyk_cs_to_rgbk_cm |
354 | | }; |
355 | | |
356 | | /* |
357 | | * These are the default handlers for returning the list of color space |
358 | | * to color model conversion routines. |
359 | | */ |
360 | | const gx_cm_color_map_procs * |
361 | | gx_default_DevGray_get_color_mapping_procs(const gx_device * dev, |
362 | | const gx_device ** tdev) |
363 | 52.6M | { |
364 | 52.6M | *tdev = dev; |
365 | 52.6M | return &DeviceGray_procs; |
366 | 52.6M | } |
367 | | |
368 | | const gx_cm_color_map_procs * |
369 | | gx_default_DevRGB_get_color_mapping_procs(const gx_device * dev, |
370 | | const gx_device ** tdev) |
371 | 1.14G | { |
372 | 1.14G | *tdev = dev; |
373 | 1.14G | return &DeviceRGB_procs; |
374 | 1.14G | } |
375 | | |
376 | | const gx_cm_color_map_procs * |
377 | | gx_default_DevCMYK_get_color_mapping_procs(const gx_device * dev, |
378 | | const gx_device ** tdev) |
379 | 22.9M | { |
380 | 22.9M | *tdev = dev; |
381 | 22.9M | return &DeviceCMYK_procs; |
382 | 22.9M | } |
383 | | |
384 | | const gx_cm_color_map_procs * |
385 | | gx_default_DevRGBK_get_color_mapping_procs(const gx_device * dev, |
386 | | const gx_device ** tdev) |
387 | 0 | { |
388 | 0 | *tdev = dev; |
389 | 0 | return &DeviceRGBK_procs; |
390 | 0 | } |
391 | | |
392 | | const gx_cm_color_map_procs * |
393 | | gx_error_get_color_mapping_procs(const gx_device * dev, |
394 | | const gx_device ** tdev) |
395 | 0 | { |
396 | | /* |
397 | | * We should never get here. If we do then we do not have a "get_color_mapping_procs" |
398 | | * routine for the device. This will be noisy, but better than returning NULL which |
399 | | * would lead to SEGV (Segmentation Fault) errors when this is used. |
400 | | */ |
401 | 0 | emprintf1(dev->memory, |
402 | 0 | "No get_color_mapping_procs proc defined for device '%s'\n", |
403 | 0 | dev->dname); |
404 | 0 | switch (dev->color_info.num_components) { |
405 | 0 | case 1: /* DeviceGray or DeviceInvertGray */ |
406 | 0 | return gx_default_DevGray_get_color_mapping_procs(dev, tdev); |
407 | | |
408 | 0 | case 3: |
409 | 0 | return gx_default_DevRGB_get_color_mapping_procs(dev, tdev); |
410 | | |
411 | 0 | case 4: |
412 | 0 | default: /* Unknown color model - punt with CMYK */ |
413 | 0 | return gx_default_DevCMYK_get_color_mapping_procs(dev, tdev); |
414 | 0 | } |
415 | 0 | } |
416 | | |
417 | | /* ----- Default color component name to colorant index conversion routines ------ */ |
418 | | |
419 | | #define compare_color_names(pname, name_size, name_str) \ |
420 | 2.72M | (name_size == (int)strlen(name_str) && strncmp(pname, name_str, name_size) == 0) |
421 | | |
422 | | /* Default color component to index for a DeviceGray color model */ |
423 | | int |
424 | | gx_default_DevGray_get_color_comp_index(gx_device * dev, const char * pname, |
425 | | int name_size, int component_type) |
426 | 882k | { |
427 | 882k | if (compare_color_names(pname, name_size, "Gray") || |
428 | 759k | compare_color_names(pname, name_size, "Grey")) |
429 | 123k | return 0; |
430 | 759k | else |
431 | 759k | return -1; /* Indicate that the component name is "unknown" */ |
432 | 882k | } |
433 | | |
434 | | /* Default color component to index for a DeviceRGB color model */ |
435 | | int |
436 | | gx_default_DevRGB_get_color_comp_index(gx_device * dev, const char * pname, |
437 | | int name_size, int component_type) |
438 | 30.9k | { |
439 | 30.9k | if (compare_color_names(pname, name_size, "Red")) |
440 | 52 | return 0; |
441 | 30.9k | if (compare_color_names(pname, name_size, "Green")) |
442 | 52 | return 1; |
443 | 30.8k | if (compare_color_names(pname, name_size, "Blue")) |
444 | 52 | return 2; |
445 | 30.8k | else |
446 | 30.8k | return -1; /* Indicate that the component name is "unknown" */ |
447 | 30.8k | } |
448 | | |
449 | | /* Default color component to index for a DeviceCMYK color model */ |
450 | | int |
451 | | gx_default_DevCMYK_get_color_comp_index(gx_device * dev, const char * pname, |
452 | | int name_size, int component_type) |
453 | 29.3k | { |
454 | 29.3k | if (compare_color_names(pname, name_size, "Cyan")) |
455 | 377 | return 0; |
456 | 28.9k | if (compare_color_names(pname, name_size, "Magenta")) |
457 | 2.23k | return 1; |
458 | 26.7k | if (compare_color_names(pname, name_size, "Yellow")) |
459 | 1.91k | return 2; |
460 | 24.7k | if (compare_color_names(pname, name_size, "Black")) |
461 | 24.7k | return 3; |
462 | 0 | else |
463 | 0 | return -1; /* Indicate that the component name is "unknown" */ |
464 | 24.7k | } |
465 | | |
466 | | /* Default color component to index for a DeviceRGBK color model */ |
467 | | int |
468 | | gx_default_DevRGBK_get_color_comp_index(gx_device * dev, const char * pname, |
469 | | int name_size, int component_type) |
470 | 0 | { |
471 | 0 | if (compare_color_names(pname, name_size, "Red")) |
472 | 0 | return 0; |
473 | 0 | if (compare_color_names(pname, name_size, "Green")) |
474 | 0 | return 1; |
475 | 0 | if (compare_color_names(pname, name_size, "Blue")) |
476 | 0 | return 2; |
477 | 0 | if (compare_color_names(pname, name_size, "Black")) |
478 | 0 | return 3; |
479 | 0 | else |
480 | 0 | return -1; /* Indicate that the component name is "unknown" */ |
481 | 0 | } |
482 | | |
483 | | /* Default color component to index for an unknown color model */ |
484 | | int |
485 | | gx_error_get_color_comp_index(gx_device * dev, const char * pname, |
486 | | int name_size, int component_type) |
487 | 0 | { |
488 | | /* |
489 | | * We should never get here. If we do then we do not have a "get_color_comp_index" |
490 | | * routine for the device. |
491 | | */ |
492 | | #ifdef DEBUG |
493 | | dmprintf(dev->memory, "No get_color_comp_index proc defined for device.\n"); |
494 | | #endif |
495 | 0 | return -1; /* Always return "unknown" component name */ |
496 | 0 | } |
497 | | |
498 | | #undef compare_color_names |
499 | | |
500 | | /* ---------------- Device color rendering ---------------- */ |
501 | | |
502 | | static cmap_proc_gray(cmap_gray_halftoned); |
503 | | static cmap_proc_gray(cmap_gray_direct); |
504 | | |
505 | | static cmap_proc_rgb(cmap_rgb_halftoned); |
506 | | static cmap_proc_rgb(cmap_rgb_direct); |
507 | | |
508 | | #define cmap_cmyk_halftoned cmap_cmyk_direct |
509 | | static cmap_proc_cmyk(cmap_cmyk_direct); |
510 | | |
511 | | /* Procedure names are only guaranteed unique to 23 characters.... */ |
512 | | static cmap_proc_separation(cmap_separation_halftoned); |
513 | | static cmap_proc_separation(cmap_separation_direct); |
514 | | |
515 | | static cmap_proc_devicen(cmap_devicen_halftoned); |
516 | | static cmap_proc_devicen(cmap_devicen_direct); |
517 | | |
518 | | static cmap_proc_is_halftoned(cmap_halftoned_is_halftoned); |
519 | | static cmap_proc_is_halftoned(cmap_direct_is_halftoned); |
520 | | |
521 | | static const gx_color_map_procs cmap_few = { |
522 | | cmap_gray_halftoned, |
523 | | cmap_rgb_halftoned, |
524 | | cmap_cmyk_halftoned, |
525 | | cmap_separation_halftoned, |
526 | | cmap_devicen_halftoned, |
527 | | cmap_halftoned_is_halftoned |
528 | | }; |
529 | | static const gx_color_map_procs cmap_many = { |
530 | | cmap_gray_direct, |
531 | | cmap_rgb_direct, |
532 | | cmap_cmyk_direct, |
533 | | cmap_separation_direct, |
534 | | cmap_devicen_direct, |
535 | | cmap_direct_is_halftoned |
536 | | }; |
537 | | |
538 | | const gx_color_map_procs *const cmap_procs_default = &cmap_many; |
539 | | |
540 | | /* Determine the color mapping procedures for a device. */ |
541 | | /* Note that the default procedure doesn't consult the gs_gstate. */ |
542 | | const gx_color_map_procs * |
543 | | gx_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev) |
544 | 16.8M | { |
545 | 16.8M | return (pgs->get_cmap_procs)(pgs, dev); |
546 | 16.8M | } |
547 | | |
548 | | const gx_color_map_procs * |
549 | | gx_default_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev) |
550 | 13.1M | { |
551 | 13.1M | return (gx_device_must_halftone(dev) ? &cmap_few : &cmap_many); |
552 | 13.1M | } |
553 | | |
554 | | /* Set the color mapping procedures in the graphics state. */ |
555 | | void |
556 | | gx_set_cmap_procs(gs_gstate * pgs, const gx_device * dev) |
557 | 10.7M | { |
558 | 10.7M | pgs->cmap_procs = gx_get_cmap_procs(pgs, dev); |
559 | 10.7M | } |
560 | | |
561 | | /* Remap the color in the graphics state. */ |
562 | | int |
563 | | gx_remap_color(gs_gstate * pgs) |
564 | 19.7M | { |
565 | 19.7M | const gs_color_space *pcs = gs_currentcolorspace_inline(pgs); |
566 | 19.7M | int code = 0; |
567 | | |
568 | | /* The current color in the graphics state is always used for */ |
569 | | /* the texture, never for the source. */ |
570 | | /* skip remap if the dev_color is already set and is type "pure" (a common case) */ |
571 | 19.7M | if (!gx_dc_is_pure(gs_currentdevicecolor_inline(pgs))) |
572 | 19.7M | code = (*pcs->type->remap_color) (gs_currentcolor_inline(pgs), |
573 | 19.7M | pcs, gs_currentdevicecolor_inline(pgs), |
574 | 19.7M | (gs_gstate *) pgs, pgs->device, |
575 | 19.7M | gs_color_select_texture); |
576 | 19.7M | return code; |
577 | 19.7M | } |
578 | | |
579 | | /* Indicate that a color space has no underlying concrete space. */ |
580 | | const gs_color_space * |
581 | | gx_no_concrete_space(const gs_color_space * pcs, const gs_gstate * pgs) |
582 | 0 | { |
583 | 0 | return NULL; |
584 | 0 | } |
585 | | |
586 | | /* Indicate that a color space is concrete. */ |
587 | | const gs_color_space * |
588 | | gx_same_concrete_space(const gs_color_space * pcs, const gs_gstate * pgs) |
589 | 52.3M | { |
590 | 52.3M | return pcs; |
591 | 52.3M | } |
592 | | |
593 | | /* Indicate that a color cannot be concretized. */ |
594 | | int |
595 | | gx_no_concretize_color(const gs_client_color * pcc, const gs_color_space * pcs, |
596 | | frac * pconc, const gs_gstate * pgs, gx_device *dev) |
597 | 0 | { |
598 | 0 | return_error(gs_error_rangecheck); |
599 | 0 | } |
600 | | |
601 | | /* If someone has specified a table for handling named spot colors then we will |
602 | | be attempting to do the special handling to go directly to the device colors |
603 | | here */ |
604 | | int |
605 | | gx_remap_named_color(const gs_client_color * pcc, const gs_color_space * pcs, |
606 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
607 | | gs_color_select_t select) |
608 | 0 | { |
609 | 0 | gx_color_value device_values[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
610 | 0 | byte *pname; |
611 | 0 | uint name_size; |
612 | 0 | gsicc_rendering_param_t rendering_params; |
613 | 0 | int code; |
614 | 0 | gsicc_namedcolor_t named_color_sep; |
615 | 0 | gsicc_namedcolor_t *named_color_devn = NULL; |
616 | 0 | gsicc_namedcolor_t *named_color_ptr = NULL; |
617 | 0 | uchar num_des_comps = dev->color_info.num_components; |
618 | 0 | uchar k; |
619 | 0 | frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
620 | 0 | int i = pcs->type->num_components(pcs); |
621 | 0 | cmm_dev_profile_t *dev_profile = NULL; |
622 | 0 | gs_color_space_index type = gs_color_space_get_index(pcs); |
623 | 0 | uchar num_src_comps = 1; |
624 | | |
625 | | /* Define the rendering intents. */ |
626 | 0 | rendering_params.black_point_comp = pgs->blackptcomp; |
627 | 0 | rendering_params.graphics_type_tag = dev->graphics_type_tag; |
628 | 0 | rendering_params.override_icc = false; |
629 | 0 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
630 | 0 | rendering_params.rendering_intent = pgs->renderingintent; |
631 | 0 | rendering_params.cmm = gsCMM_DEFAULT; |
632 | |
|
633 | 0 | if (type == gs_color_space_index_Separation) { |
634 | 0 | named_color_sep.colorant_name = pcs->params.separation.sep_name; |
635 | 0 | named_color_sep.name_size = strlen(pcs->params.separation.sep_name); |
636 | 0 | named_color_ptr = &named_color_sep; |
637 | 0 | } else if (type == gs_color_space_index_DeviceN) { |
638 | 0 | char **names = pcs->params.device_n.names; |
639 | 0 | num_src_comps = pcs->params.device_n.num_components; |
640 | | /* Allocate and initialize name structure */ |
641 | 0 | named_color_devn = |
642 | 0 | (gsicc_namedcolor_t*)gs_alloc_bytes(dev->memory->non_gc_memory, |
643 | 0 | num_src_comps * sizeof(gsicc_namedcolor_t), |
644 | 0 | "gx_remap_named_color"); |
645 | 0 | if (named_color_devn == NULL) |
646 | 0 | return false; /* Clearly a bigger issue. But lets not end here */ |
647 | 0 | for (k = 0; k < num_src_comps; k++) { |
648 | 0 | pname = (byte *)names[k]; |
649 | 0 | name_size = strlen(names[k]); |
650 | 0 | named_color_devn[k].colorant_name = (char*)pname; |
651 | 0 | named_color_devn[k].name_size = name_size; |
652 | 0 | } |
653 | 0 | named_color_ptr = named_color_devn; |
654 | 0 | } else |
655 | 0 | return false; /* Only sep and deviceN for named color replacement */ |
656 | | |
657 | 0 | code = gsicc_transform_named_color(pcc->paint.values, named_color_ptr, |
658 | 0 | num_src_comps, device_values, pgs, dev, NULL, &rendering_params); |
659 | 0 | if (named_color_devn != NULL) |
660 | 0 | gs_free_object(dev->memory->non_gc_memory, named_color_devn, |
661 | 0 | "gx_remap_named_color"); |
662 | |
|
663 | 0 | if (code == 0) { |
664 | | /* Named color was found and set. Note that gsicc_transform_named_color |
665 | | MUST set ALL the colorant values AND they must be in the proper |
666 | | order already. If we have specified the colorants with |
667 | | -sICCOutputColors (i.e. if you are using an NCLR output profile) then |
668 | | we should be good. If not or if instead one used SeparationColorNames and |
669 | | SeparationOrder to set up the device, then we need to make a copy |
670 | | of the gs_gstate and make sure that we set color_component_map is |
671 | | properly set up for the gx_remap_concrete_devicen proc. */ |
672 | 0 | for (k = 0; k < num_des_comps; k++) |
673 | 0 | conc[k] = float2frac(((float)device_values[k]) / 65535.0); |
674 | | |
675 | | /* If we are looking to create the equivalent CMYK value then no need |
676 | | to worry about NCLR profiles or about altering the colorant map */ |
677 | 0 | if (!named_color_equivalent_cmyk_colors(pgs)) { |
678 | | /* We need to apply transfer functions, possibily halftone and |
679 | | encode the color for the device. To get proper mapping of the |
680 | | colors to the device positions, you MUST specify -sICCOutputColors |
681 | | which will enumerate the positions of the colorants and enable |
682 | | proper color management for the CMYK portions IF you are using |
683 | | an NCLR output profile. */ |
684 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
685 | 0 | if (code < 0) |
686 | 0 | return false; |
687 | | |
688 | | /* Check if the profile is DeviceN (NCLR) */ |
689 | 0 | if (dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->data_cs == gsNCHANNEL) { |
690 | 0 | if (dev_profile->spotnames == NULL) |
691 | 0 | return false; |
692 | 0 | if (!dev_profile->spotnames->equiv_cmyk_set) { |
693 | | /* Note that if the improper NCLR profile is used, then the |
694 | | composite preview will be wrong. */ |
695 | 0 | code = gsicc_set_devicen_equiv_colors(dev, pgs, |
696 | 0 | dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]); |
697 | 0 | if (code < 0) |
698 | 0 | return false; |
699 | 0 | dev_profile->spotnames->equiv_cmyk_set = true; |
700 | 0 | } |
701 | 0 | gx_remap_concrete_devicen(conc, pdc, pgs, dev, select, pcs); |
702 | 0 | } else { |
703 | 0 | gs_gstate temp_state = *((const gs_gstate *)pgs); |
704 | | |
705 | | /* No NCLR profile with spot names. So set up the |
706 | | color_component_map in the gs_gstate. Again, note that |
707 | | gsicc_transform_named_color must have set ALL the device |
708 | | colors */ |
709 | 0 | for (k = 0; k < dev->color_info.num_components; k++) |
710 | 0 | temp_state.color_component_map.color_map[k] = k; |
711 | 0 | temp_state.color_component_map.num_components = dev->color_info.num_components; |
712 | 0 | gx_remap_concrete_devicen(conc, pdc, &temp_state, dev, select, pcs); |
713 | 0 | } |
714 | 0 | } else { |
715 | 0 | gx_remap_concrete_devicen(conc, pdc, pgs, dev, select, pcs); |
716 | 0 | } |
717 | | /* Save original color space and color info into dev color */ |
718 | 0 | i = any_abs(i); |
719 | 0 | for (i--; i >= 0; i--) |
720 | 0 | pdc->ccolor.paint.values[i] = pcc->paint.values[i]; |
721 | 0 | pdc->ccolor_valid = true; |
722 | 0 | return true; |
723 | 0 | } |
724 | 0 | return false; |
725 | 0 | } |
726 | | |
727 | | /* By default, remap a color by concretizing it and then remapping the concrete |
728 | | color. */ |
729 | | int |
730 | | gx_default_remap_color(const gs_client_color * pcc, const gs_color_space * pcs, |
731 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
732 | | gs_color_select_t select) |
733 | 47.5M | { |
734 | 47.5M | frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
735 | 47.5M | const gs_color_space *pconcs; |
736 | 47.5M | int i = pcs->type->num_components(pcs); |
737 | 47.5M | int code = (*pcs->type->concretize_color)(pcc, pcs, conc, pgs, dev); |
738 | 47.5M | cmm_dev_profile_t *dev_profile; |
739 | | |
740 | 47.5M | if (code < 0) |
741 | 8.23k | return code; |
742 | 47.5M | pconcs = cs_concrete_space(pcs, pgs); |
743 | 47.5M | if (!pconcs) |
744 | 0 | return gs_note_error(gs_error_undefined); |
745 | 47.5M | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
746 | 47.5M | if (code < 0) |
747 | 0 | return code; |
748 | 47.5M | code = (*pconcs->type->remap_concrete_color)(pconcs, conc, pdc, pgs, dev, select, dev_profile); |
749 | | |
750 | | /* Save original color space and color info into dev color */ |
751 | 47.5M | i = any_abs(i); |
752 | 95.1M | for (i--; i >= 0; i--) |
753 | 47.5M | pdc->ccolor.paint.values[i] = pcc->paint.values[i]; |
754 | 47.5M | pdc->ccolor_valid = true; |
755 | 47.5M | return code; |
756 | 47.5M | } |
757 | | |
758 | | /* Color remappers for the standard color spaces. */ |
759 | | /* Note that we use D... instead of Device... in some places because */ |
760 | | /* gcc under VMS only retains 23 characters of procedure names. */ |
761 | | |
762 | | /* DeviceGray */ |
763 | | int |
764 | | gx_concretize_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs, |
765 | | frac * pconc, const gs_gstate * pgs, gx_device *dev) |
766 | 0 | { |
767 | 0 | pconc[0] = gx_unit_frac(pc->paint.values[0]); |
768 | 0 | return 0; |
769 | 0 | } |
770 | | int |
771 | | gx_remap_concrete_DGray(const gs_color_space * pcs, const frac * pconc, |
772 | | gx_device_color * pdc, const gs_gstate * pgs, |
773 | | gx_device * dev, gs_color_select_t select, |
774 | | const cmm_dev_profile_t *dev_profile) |
775 | 52.1M | { |
776 | 52.1M | (*pgs->cmap_procs->map_gray)(pconc[0], pdc, pgs, dev, select); |
777 | 52.1M | return 0; |
778 | 52.1M | } |
779 | | int |
780 | | gx_remap_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs, |
781 | | gx_device_color * pdc, const gs_gstate * pgs, |
782 | | gx_device * dev, gs_color_select_t select) |
783 | 578k | { |
784 | 578k | frac fgray = gx_unit_frac(pc->paint.values[0]); |
785 | 578k | int code; |
786 | | |
787 | | /* We are in here due to the fact that we are using a color space that |
788 | | was set in the graphic state before the ICC manager was intitialized |
789 | | and the color space was never actually "installed" and hence set |
790 | | over to a proper ICC color space. We will "install" this color space |
791 | | at this time */ |
792 | 578k | if (pgs->icc_manager->default_gray != NULL) { |
793 | 192k | gs_color_space *pcs_notconst = (gs_color_space*) pcs; |
794 | 192k | pcs_notconst->cmm_icc_profile_data = pgs->icc_manager->default_gray; |
795 | 192k | gsicc_adjust_profile_rc(pgs->icc_manager->default_gray, 1, "gx_remap_DeviceGray"); |
796 | 192k | pcs_notconst->type = &gs_color_space_type_ICC; |
797 | 192k | code = |
798 | 192k | (*pcs_notconst->type->remap_color)(gs_currentcolor_inline(pgs), |
799 | 192k | pcs_notconst, |
800 | 192k | gs_currentdevicecolor_inline(pgs), |
801 | 192k | pgs, pgs->device, |
802 | 192k | gs_color_select_texture); |
803 | 192k | return code; |
804 | 192k | } |
805 | | |
806 | | /* Save original color space and color info into dev color */ |
807 | 385k | pdc->ccolor.paint.values[0] = pc->paint.values[0]; |
808 | 385k | pdc->ccolor_valid = true; |
809 | | |
810 | 385k | (*pgs->cmap_procs->map_gray)(fgray, pdc, pgs, dev, select); |
811 | 385k | return 0; |
812 | 578k | } |
813 | | |
814 | | /* DeviceRGB */ |
815 | | int |
816 | | gx_concretize_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs, |
817 | | frac * pconc, const gs_gstate * pgs, gx_device *dev) |
818 | 0 | { |
819 | 0 | pconc[0] = gx_unit_frac(pc->paint.values[0]); |
820 | 0 | pconc[1] = gx_unit_frac(pc->paint.values[1]); |
821 | 0 | pconc[2] = gx_unit_frac(pc->paint.values[2]); |
822 | 0 | return 0; |
823 | 0 | } |
824 | | int |
825 | | gx_remap_concrete_DRGB(const gs_color_space * pcs, const frac * pconc, |
826 | | gx_device_color * pdc, const gs_gstate * pgs, |
827 | | gx_device * dev, gs_color_select_t select, |
828 | | const cmm_dev_profile_t *dev_profile) |
829 | 1.43G | { |
830 | | |
831 | 1.43G | gx_remap_concrete_rgb(pconc[0], pconc[1], pconc[2], pdc, pgs, dev, select); |
832 | 1.43G | return 0; |
833 | 1.43G | } |
834 | | int |
835 | | gx_remap_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs, |
836 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
837 | | gs_color_select_t select) |
838 | 0 | { |
839 | 0 | frac fred = gx_unit_frac(pc->paint.values[0]), fgreen = gx_unit_frac(pc->paint.values[1]), |
840 | 0 | fblue = gx_unit_frac(pc->paint.values[2]); |
841 | | |
842 | | /* Save original color space and color info into dev color */ |
843 | 0 | pdc->ccolor.paint.values[0] = pc->paint.values[0]; |
844 | 0 | pdc->ccolor.paint.values[1] = pc->paint.values[1]; |
845 | 0 | pdc->ccolor.paint.values[2] = pc->paint.values[2]; |
846 | 0 | pdc->ccolor_valid = true; |
847 | |
|
848 | 0 | gx_remap_concrete_rgb(fred, fgreen, fblue, pdc, pgs, dev, select); |
849 | 0 | return 0; |
850 | 0 | } |
851 | | |
852 | | /* DeviceCMYK */ |
853 | | int |
854 | | gx_concretize_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs, |
855 | | frac * pconc, const gs_gstate * pgs, gx_device *dev) |
856 | 0 | { |
857 | 0 | pconc[0] = gx_unit_frac(pc->paint.values[0]); |
858 | 0 | pconc[1] = gx_unit_frac(pc->paint.values[1]); |
859 | 0 | pconc[2] = gx_unit_frac(pc->paint.values[2]); |
860 | 0 | pconc[3] = gx_unit_frac(pc->paint.values[3]); |
861 | 0 | return 0; |
862 | 0 | } |
863 | | int |
864 | | gx_remap_concrete_DCMYK(const gs_color_space * pcs, const frac * pconc, |
865 | | gx_device_color * pdc, const gs_gstate * pgs, |
866 | | gx_device * dev, gs_color_select_t select, |
867 | | const cmm_dev_profile_t *dev_profile) |
868 | 124M | { |
869 | | /****** IGNORE alpha ******/ |
870 | 124M | gx_remap_concrete_cmyk(pconc[0], pconc[1], pconc[2], pconc[3], pdc, |
871 | 124M | pgs, dev, select, pcs); |
872 | 124M | return 0; |
873 | 124M | } |
874 | | int |
875 | | gx_remap_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs, |
876 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
877 | | gs_color_select_t select) |
878 | 0 | { |
879 | | /****** IGNORE alpha ******/ |
880 | | /* Save original color space and color info into dev color */ |
881 | 0 | pdc->ccolor.paint.values[0] = pc->paint.values[0]; |
882 | 0 | pdc->ccolor.paint.values[1] = pc->paint.values[1]; |
883 | 0 | pdc->ccolor.paint.values[2] = pc->paint.values[2]; |
884 | 0 | pdc->ccolor.paint.values[3] = pc->paint.values[3]; |
885 | 0 | pdc->ccolor_valid = true; |
886 | 0 | gx_remap_concrete_cmyk(gx_unit_frac(pc->paint.values[0]), |
887 | 0 | gx_unit_frac(pc->paint.values[1]), |
888 | 0 | gx_unit_frac(pc->paint.values[2]), |
889 | 0 | gx_unit_frac(pc->paint.values[3]), |
890 | 0 | pdc, pgs, dev, select, pcs); |
891 | 0 | return 0; |
892 | 0 | } |
893 | | |
894 | | /* ------ Utility for selecting the dev_ht from the pgs using the dev->graphics_type_tag ----- */ |
895 | | |
896 | | static gs_HT_objtype_t |
897 | | tag_to_HT_objtype[8] = { HT_OBJTYPE_DEFAULT, |
898 | | HT_OBJTYPE_TEXT, /* GS_TEXT_TAG = 0x1 */ |
899 | | HT_OBJTYPE_IMAGE, /* GS_IMAGE_TAG = 0x2 */ |
900 | | HT_OBJTYPE_DEFAULT, |
901 | | HT_OBJTYPE_VECTOR, /* GS_VECTOR_TAG = 0x4 */ |
902 | | HT_OBJTYPE_DEFAULT, HT_OBJTYPE_DEFAULT, HT_OBJTYPE_DEFAULT |
903 | | }; |
904 | | |
905 | | /* Return the selected dev_ht[] or the pgs->dev_ht[HT_OBJTYPE_DEFAULT] */ |
906 | | gx_device_halftone * |
907 | | gx_select_dev_ht(const gs_gstate *pgs) |
908 | 373M | { |
909 | 373M | gs_HT_objtype_t objtype; |
910 | | |
911 | | /* This function only works with 3 bits currently. Flag here in case we add object types */ |
912 | 373M | assert(HT_OBJTYPE_COUNT == 4); |
913 | | |
914 | 373M | objtype = tag_to_HT_objtype[pgs->device->graphics_type_tag & 7]; |
915 | 373M | if (pgs->dev_ht[objtype] == NULL) |
916 | 372M | objtype = HT_OBJTYPE_DEFAULT; |
917 | 373M | return pgs->dev_ht[objtype]; |
918 | 373M | } |
919 | | |
920 | | /* ------ Render Gray color. ------ */ |
921 | | |
922 | | static void |
923 | | cmap_gray_halftoned(frac gray, gx_device_color * pdc, |
924 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select) |
925 | 24.0M | { |
926 | 24.0M | uchar i, ncomps = dev->color_info.num_components; |
927 | 24.0M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
928 | 24.0M | const gx_device *cmdev; |
929 | 24.0M | const gx_cm_color_map_procs *cmprocs; |
930 | | |
931 | | /* map to the color model */ |
932 | 24.0M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
933 | 24.0M | cmprocs->map_gray(cmdev, gray, cm_comps); |
934 | | |
935 | | /* apply the transfer function(s); convert to color values */ |
936 | 24.0M | if (pgs->effective_transfer_non_identity_count == 0) { |
937 | | /* No transfer function to apply */ |
938 | 23.3M | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
939 | 46.7M | for (i = 0; i < ncomps; i++) |
940 | 23.3M | cm_comps[i] = gx_map_color_frac(pgs, |
941 | 23.3M | cm_comps[i], effective_transfer[i]); |
942 | 35.7k | else { |
943 | 35.7k | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
944 | 0 | i = dev->color_info.black_component; |
945 | 0 | if (i < ncomps) |
946 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
947 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
948 | 35.7k | } else { |
949 | 71.4k | for (i = 0; i < ncomps; i++) |
950 | 35.7k | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
951 | 35.7k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
952 | 35.7k | } |
953 | 35.7k | } |
954 | 24.0M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
955 | 24.0M | &pgs->screen_phase[select]) == 1) |
956 | 20.0M | gx_color_load_select(pdc, pgs, dev, select); |
957 | 24.0M | } |
958 | | |
959 | | static void |
960 | | cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_gstate * pgs, |
961 | | gx_device * dev, gs_color_select_t select) |
962 | 10.1M | { |
963 | 10.1M | uchar i, nc, ncomps = dev->color_info.num_components; |
964 | 10.1M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
965 | 10.1M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
966 | 10.1M | gx_color_index color; |
967 | 10.1M | const gx_device *cmdev; |
968 | 10.1M | const gx_cm_color_map_procs *cmprocs; |
969 | | |
970 | | /* map to the color model */ |
971 | 10.1M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
972 | 10.1M | cmprocs->map_gray(cmdev, gray, cm_comps); |
973 | | |
974 | 10.1M | nc = ncomps; |
975 | 10.1M | if (device_encodes_tags(dev)) |
976 | 0 | nc--; |
977 | | /* apply the transfer function(s); convert to color values */ |
978 | 10.1M | if (pgs->effective_transfer_non_identity_count == 0) { |
979 | 20.2M | for (i = 0; i < nc; i++) |
980 | 10.1M | cv[i] = frac2cv(cm_comps[i]); |
981 | 10.1M | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
982 | 13.8k | for (i = 0; i < nc; i++) { |
983 | 6.94k | cm_comps[i] = gx_map_color_frac(pgs, |
984 | 6.94k | cm_comps[i], effective_transfer[i]); |
985 | 6.94k | cv[i] = frac2cv(cm_comps[i]); |
986 | 6.94k | } |
987 | 0 | else { |
988 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
989 | 0 | i = dev->color_info.black_component; |
990 | 0 | if (i < ncomps) |
991 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
992 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
993 | 0 | for (i = 0; i < nc; i++) |
994 | 0 | cv[i] = frac2cv(cm_comps[i]); |
995 | 0 | } else { |
996 | 0 | for (i = 0; i < nc; i++) { |
997 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
998 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
999 | 0 | cv[i] = frac2cv(cm_comps[i]); |
1000 | 0 | } |
1001 | 0 | } |
1002 | 0 | } |
1003 | | /* Copy tags untransformed. */ |
1004 | 10.1M | if (nc < ncomps) |
1005 | 0 | cv[nc] = cm_comps[nc]; |
1006 | | |
1007 | | /* encode as a color index */ |
1008 | 10.1M | color = dev_proc(dev, encode_color)(dev, cv); |
1009 | | |
1010 | | /* check if the encoding was successful; we presume failure is rare */ |
1011 | 10.1M | if (color != gx_no_color_index) { |
1012 | 10.1M | color_set_pure(pdc, color); |
1013 | 10.1M | return; |
1014 | 10.1M | } |
1015 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1016 | 0 | &pgs->screen_phase[select]) == 1) |
1017 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1018 | 0 | } |
1019 | | |
1020 | | /* ------ Render RGB color. ------ */ |
1021 | | |
1022 | | static void |
1023 | | cmap_rgb_halftoned(frac r, frac g, frac b, gx_device_color * pdc, |
1024 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select) |
1025 | 265M | { |
1026 | 265M | uchar i, nc, ncomps = dev->color_info.num_components; |
1027 | 265M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1028 | 265M | const gx_device *cmdev; |
1029 | 265M | const gx_cm_color_map_procs *cmprocs; |
1030 | | |
1031 | | /* map to the color model */ |
1032 | 265M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1033 | 265M | cmprocs->map_rgb(cmdev, pgs, r, g, b, cm_comps); |
1034 | | |
1035 | 265M | nc = ncomps; |
1036 | 265M | if (device_encodes_tags(dev)) |
1037 | 0 | nc--; |
1038 | | /* apply the transfer function(s); convert to color values */ |
1039 | 265M | if (pgs->effective_transfer_non_identity_count != 0) { |
1040 | 265M | int n = 0; |
1041 | 265M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1042 | 265M | n = nc < 3 ? nc : 3; |
1043 | | |
1044 | 1.06G | for (i = 0; i < n; i++) |
1045 | 796M | cm_comps[i] = gx_map_color_frac(pgs, |
1046 | 265M | cm_comps[i], effective_transfer[i]); |
1047 | 265M | for (; i < nc; i++) |
1048 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1049 | 265M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1050 | 265M | } |
1051 | | |
1052 | 265M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1053 | 265M | &pgs->screen_phase[select]) == 1) |
1054 | 155M | gx_color_load_select(pdc, pgs, dev, select); |
1055 | 265M | } |
1056 | | |
1057 | | static void |
1058 | | cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc, |
1059 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select) |
1060 | 733M | { |
1061 | 733M | uchar i, nc, ncomps = dev->color_info.num_components; |
1062 | 733M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1063 | 733M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1064 | 733M | gx_color_index color; |
1065 | 733M | const gx_device *cmdev; |
1066 | 733M | const gx_cm_color_map_procs *cmprocs; |
1067 | | |
1068 | | /* map to the color model */ |
1069 | 733M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1070 | 733M | cmprocs->map_rgb(cmdev, pgs, r, g, b, cm_comps); |
1071 | | |
1072 | 733M | nc = ncomps; |
1073 | 733M | if (device_encodes_tags(dev)) |
1074 | 0 | nc--; |
1075 | | /* apply the transfer function(s); convert to color values */ |
1076 | 733M | if (pgs->effective_transfer_non_identity_count != 0) { |
1077 | 733k | int n = 0; |
1078 | 733k | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1079 | 733k | n = nc < 3 ? nc : 3; |
1080 | 2.93M | for (i = 0; i < n; i++) |
1081 | 2.19M | cm_comps[i] = gx_map_color_frac(pgs, cm_comps[i], |
1082 | 733k | effective_transfer[i]); |
1083 | 733k | for (; i < nc; i++) |
1084 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1085 | 733k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1086 | 733k | } |
1087 | | |
1088 | 733M | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1089 | 0 | for (i = 0; i < nc; i++) |
1090 | 0 | pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); |
1091 | 0 | if (i < ncomps) |
1092 | 0 | pdc->colors.devn.values[i] = cm_comps[i], i++; |
1093 | 0 | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
1094 | 0 | pdc->colors.devn.values[i] = 0; |
1095 | 0 | pdc->type = gx_dc_type_devn; |
1096 | 733M | } else { |
1097 | 2.93G | for (i = 0; i < nc; i++) |
1098 | 2.20G | cv[i] = frac2cv(cm_comps[i]); |
1099 | 733M | if (i < ncomps) |
1100 | 0 | cv[i] = cm_comps[i]; |
1101 | | /* encode as a color index */ |
1102 | 733M | color = dev_proc(dev, encode_color)(dev, cv); |
1103 | | |
1104 | | /* check if the encoding was successful; we presume failure is rare */ |
1105 | 733M | if (color != gx_no_color_index) { |
1106 | 733M | color_set_pure(pdc, color); |
1107 | 733M | return; |
1108 | 733M | } |
1109 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1110 | 0 | &pgs->screen_phase[select]) == 1) |
1111 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1112 | 0 | } |
1113 | 733M | } |
1114 | | |
1115 | | /* ------ Render CMYK color. ------ */ |
1116 | | |
1117 | | static void |
1118 | | cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc, |
1119 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select, |
1120 | | const gs_color_space *source_pcs) |
1121 | 92.2M | { |
1122 | 92.2M | uchar i, nc, ncomps = dev->color_info.num_components; |
1123 | 92.2M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1124 | 92.2M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1125 | 92.2M | gx_color_index color; |
1126 | 92.2M | uint black_index; |
1127 | 92.2M | cmm_dev_profile_t *dev_profile; |
1128 | 92.2M | gsicc_colorbuffer_t src_space = gsUNDEFINED; |
1129 | 92.2M | bool gray_to_k; |
1130 | 92.2M | const gx_device *cmdev; |
1131 | 92.2M | const gx_cm_color_map_procs *cmprocs; |
1132 | | |
1133 | | /* map to the color model */ |
1134 | 92.2M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1135 | 92.2M | cmprocs->map_cmyk(cmdev, c, m, y, k, cm_comps); |
1136 | | |
1137 | | /* apply the transfer function(s); convert to color values */ |
1138 | 92.2M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
1139 | 10 | if (pgs->effective_transfer_non_identity_count != 0) |
1140 | 20 | for (i = 0; i < ncomps; i++) |
1141 | 10 | cm_comps[i] = gx_map_color_frac(pgs, |
1142 | 10 | cm_comps[i], effective_transfer[i]); |
1143 | 92.2M | } else { |
1144 | | /* Check if source space is gray. In this case we are to use only the |
1145 | | transfer function on the K channel. Do this only if gray to K is |
1146 | | also set */ |
1147 | 92.2M | dev_proc(dev, get_profile)(dev, &dev_profile); |
1148 | 92.2M | gray_to_k = dev_profile->devicegraytok; |
1149 | 92.2M | if (source_pcs != NULL && source_pcs->cmm_icc_profile_data != NULL) { |
1150 | 92.2M | src_space = source_pcs->cmm_icc_profile_data->data_cs; |
1151 | 92.2M | } else if (source_pcs != NULL && source_pcs->icc_equivalent != NULL) { |
1152 | 0 | src_space = source_pcs->icc_equivalent->cmm_icc_profile_data->data_cs; |
1153 | 0 | } |
1154 | 92.2M | if (src_space == gsGRAY && gray_to_k) { |
1155 | | /* Find the black channel location */ |
1156 | 1.40M | black_index = dev_proc(dev, get_color_comp_index)(dev, "Black", |
1157 | 1.40M | strlen("Black"), SEPARATION_NAME); |
1158 | 1.40M | if (black_index < GX_DEVICE_COLOR_MAX_COMPONENTS) |
1159 | 1.40M | cm_comps[black_index] = frac_1 - gx_map_color_frac(pgs, |
1160 | 1.40M | (frac)(frac_1 - cm_comps[black_index]), |
1161 | 1.40M | effective_transfer[black_index]); |
1162 | 90.8M | } else if (pgs->effective_transfer_non_identity_count != 0) |
1163 | 389M | for (i = 0; i < ncomps; i++) |
1164 | 311M | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1165 | 92.2M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1166 | 92.2M | } |
1167 | | /* We make a test for direct vs. halftoned, rather than */ |
1168 | | /* duplicating most of the code of this procedure. */ |
1169 | 92.2M | if (gx_device_must_halftone(dev)) { |
1170 | 78.5M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, |
1171 | 78.5M | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
1172 | 49.5M | gx_color_load_select(pdc, pgs, dev, select); |
1173 | 78.5M | return; |
1174 | 78.5M | } |
1175 | | /* if output device supports devn, we need to make sure we send it the |
1176 | | proper color type */ |
1177 | 13.7M | nc = ncomps; |
1178 | 13.7M | if (device_encodes_tags(dev)) |
1179 | 0 | nc--; |
1180 | 13.7M | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1181 | 74.9M | for (i = 0; i < nc; i++) |
1182 | 61.1M | pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); |
1183 | 13.7M | if (i < ncomps) |
1184 | 0 | pdc->colors.devn.values[i] = cm_comps[i], i++; |
1185 | 834M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
1186 | 820M | pdc->colors.devn.values[i] = 0; |
1187 | 13.7M | pdc->type = gx_dc_type_devn; |
1188 | 13.7M | } else { |
1189 | 0 | for (i = 0; i < nc; i++) |
1190 | 0 | cv[i] = frac2cv(cm_comps[i]); |
1191 | 0 | if (i < ncomps) |
1192 | 0 | cv[i] = cm_comps[i]; |
1193 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1194 | 0 | if (color != gx_no_color_index) |
1195 | 0 | color_set_pure(pdc, color); |
1196 | 0 | else { |
1197 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, |
1198 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
1199 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1200 | 0 | } |
1201 | 0 | } |
1202 | 13.7M | return; |
1203 | 92.2M | } |
1204 | | |
1205 | | /* ------ Render Separation All color. ------ */ |
1206 | | |
1207 | | /* |
1208 | | * This routine maps DeviceN components into the order of the device's |
1209 | | * colorants. |
1210 | | * |
1211 | | * Parameters: |
1212 | | * pcc - Pointer to DeviceN components. |
1213 | | * pcolor_component_map - Map from DeviceN to the Devices colorants. |
1214 | | * A negative value indicates component is not to be mapped. |
1215 | | * plist - Pointer to list for mapped components |
1216 | | * num_comps - num_comps that we need to zero (may be more than |
1217 | | * is set if we are mapping values for an NCLR ICC profile |
1218 | | * via an alternate tint transform for a sep value) -- |
1219 | | * i.e. cmyk+og values and we may have some spots that |
1220 | | * are supported but may have reached the limit and |
1221 | | * using the alt tint values. Need to make sure to zero all. |
1222 | | * |
1223 | | * Returns: |
1224 | | * Mapped components in plist. |
1225 | | */ |
1226 | | static inline void |
1227 | | map_components_to_colorants(const frac * pcc, |
1228 | | const gs_devicen_color_map * pcolor_component_map, frac * plist, |
1229 | | int num_colorants) |
1230 | 1.46M | { |
1231 | 1.46M | int i; |
1232 | 1.46M | int pos; |
1233 | | |
1234 | | /* Clear all output colorants first */ |
1235 | 9.89M | for (i = num_colorants - 1; i >= 0; i--) { |
1236 | 8.43M | plist[i] = frac_0; |
1237 | 8.43M | } |
1238 | | |
1239 | | /* Map color components into output list */ |
1240 | 7.67M | for (i = pcolor_component_map->num_components - 1; i >= 0; i--) { |
1241 | 6.21M | pos = pcolor_component_map->color_map[i]; |
1242 | 6.21M | if (pos >= 0) |
1243 | 6.20M | plist[pos] = pcc[i]; |
1244 | 6.21M | } |
1245 | 1.46M | } |
1246 | | |
1247 | | static bool |
1248 | | named_color_supported(const gs_gstate * pgs) |
1249 | 1.46M | { |
1250 | 1.46M | gs_color_space *pcs = gs_currentcolorspace_inline(pgs); |
1251 | 1.46M | gs_color_space_index type = gs_color_space_get_index(pcs); |
1252 | | |
1253 | 1.46M | if (pgs->icc_manager->device_named == NULL) |
1254 | 1.46M | return false; |
1255 | | |
1256 | 0 | if (type == gs_color_space_index_Separation && pcs->params.separation.named_color_supported) |
1257 | 0 | return true; |
1258 | | |
1259 | 0 | if (type == gs_color_space_index_DeviceN && pcs->params.device_n.named_color_supported) |
1260 | 0 | return true; |
1261 | | |
1262 | 0 | return false; |
1263 | 0 | } |
1264 | | |
1265 | | /* Routines for handling CM of CMYK components of a DeviceN color space */ |
1266 | | static bool |
1267 | | devicen_has_cmyk(gx_device * dev, cmm_profile_t *des_profile) |
1268 | 1.46M | { |
1269 | 1.46M | gs_devn_params *devn_params; |
1270 | | |
1271 | 1.46M | devn_params = dev_proc(dev, ret_devn_params)(dev); |
1272 | 1.46M | if (devn_params == NULL) { |
1273 | 0 | if (des_profile != NULL && des_profile->data_cs == gsCMYK) |
1274 | 0 | return true; |
1275 | 0 | else |
1276 | 0 | return false; |
1277 | 0 | } |
1278 | 1.46M | return(devn_params->num_std_colorant_names == 4); |
1279 | 1.46M | } |
1280 | | |
1281 | | static void |
1282 | | devicen_sep_icc_cmyk(frac cm_comps[], const gs_gstate * pgs, |
1283 | | const gs_color_space * pcs, gx_device *dev) |
1284 | 1.46M | { |
1285 | 1.46M | gsicc_link_t *icc_link; |
1286 | 1.46M | gsicc_rendering_param_t rendering_params; |
1287 | 1.46M | unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1288 | 1.46M | unsigned short psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1289 | 1.46M | int k, code; |
1290 | 1.46M | unsigned short *psrc_temp; |
1291 | 1.46M | gsicc_rendering_param_t render_cond; |
1292 | 1.46M | cmm_dev_profile_t *dev_profile = NULL; |
1293 | 1.46M | cmm_profile_t *des_profile = NULL; |
1294 | 1.46M | cmm_profile_t *src_profile = pgs->icc_manager->default_cmyk; |
1295 | | |
1296 | 1.46M | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
1297 | | |
1298 | | /* If we can't transform them, we will just leave them as is. */ |
1299 | 1.46M | if (code < 0) |
1300 | 0 | return; |
1301 | | |
1302 | 1.46M | gsicc_extract_profile(dev->graphics_type_tag, |
1303 | 1.46M | dev_profile, &des_profile, &render_cond); |
1304 | | /* Define the rendering intents. */ |
1305 | 1.46M | rendering_params.black_point_comp = pgs->blackptcomp; |
1306 | 1.46M | rendering_params.graphics_type_tag = dev->graphics_type_tag; |
1307 | 1.46M | rendering_params.override_icc = false; |
1308 | 1.46M | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
1309 | 1.46M | rendering_params.rendering_intent = pgs->renderingintent; |
1310 | 1.46M | rendering_params.cmm = gsCMM_DEFAULT; |
1311 | | /* Sigh, frac to full 16 bit. Need to clean this up */ |
1312 | 7.34M | for (k = 0; k < 4; k++) { |
1313 | 5.87M | psrc[k] = frac2cv(cm_comps[k]); |
1314 | 5.87M | } |
1315 | | |
1316 | | /* Determine what src profile to use. First choice is the attributes |
1317 | | process color space if it is the correct type. Second choice is |
1318 | | the alternate tint transform color space if it is the correct type. |
1319 | | Third type is default_cmyk. If we have an issue with bad profiles then |
1320 | | the color values will just remain as they were from the source */ |
1321 | 1.46M | if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) { |
1322 | 1.45M | if (pcs->params.device_n.devn_process_space != NULL && |
1323 | 1.79k | pcs->params.device_n.devn_process_space->cmm_icc_profile_data != NULL && |
1324 | 1.79k | pcs->params.device_n.devn_process_space->cmm_icc_profile_data->data_cs == gsCMYK) { |
1325 | 1.79k | src_profile = pcs->params.device_n.devn_process_space->cmm_icc_profile_data; |
1326 | 1.45M | } else if (pcs->base_space != NULL && |
1327 | 1.45M | pcs->base_space->cmm_icc_profile_data != NULL && |
1328 | 1.45M | pcs->base_space->cmm_icc_profile_data->data_cs == gsCMYK && |
1329 | 914k | USE_ALT_MAP) { |
1330 | 0 | src_profile = pcs->base_space->cmm_icc_profile_data; |
1331 | 0 | } |
1332 | 1.45M | } else if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) { |
1333 | 10.5k | if (pcs->base_space != NULL && |
1334 | 10.5k | pcs->base_space->cmm_icc_profile_data != NULL && |
1335 | 10.5k | pcs->base_space->cmm_icc_profile_data->data_cs == gsCMYK && |
1336 | 5.23k | USE_ALT_MAP) { |
1337 | 0 | src_profile = pcs->base_space->cmm_icc_profile_data; |
1338 | 0 | } |
1339 | 10.5k | } |
1340 | | |
1341 | 1.46M | icc_link = gsicc_get_link_profile(pgs, dev, src_profile, des_profile, |
1342 | 1.46M | &rendering_params, pgs->memory, dev_profile->devicegraytok); |
1343 | | |
1344 | 1.46M | if (icc_link == NULL && src_profile != pgs->icc_manager->default_cmyk) { |
1345 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, |
1346 | 0 | pgs->icc_manager->default_cmyk, des_profile, |
1347 | 0 | &rendering_params, pgs->memory, dev_profile->devicegraytok); |
1348 | 0 | } |
1349 | | |
1350 | | /* If we can't transform them, we will just leave them as is. */ |
1351 | 1.46M | if (icc_link == NULL) |
1352 | 0 | return; |
1353 | | |
1354 | | /* Transform the color */ |
1355 | 1.46M | if (icc_link->is_identity) { |
1356 | 1.46M | psrc_temp = &(psrc[0]); |
1357 | 1.46M | } else { |
1358 | | /* Transform the color */ |
1359 | 0 | psrc_temp = &(psrc_cm[0]); |
1360 | 0 | (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2); |
1361 | 0 | } |
1362 | | /* This needs to be optimized */ |
1363 | 7.34M | for (k = 0; k < 4; k++) { |
1364 | 5.87M | cm_comps[k] = float2frac(((float)psrc_temp[k]) / 65535.0); |
1365 | 5.87M | } |
1366 | | /* Release the link */ |
1367 | 1.46M | gsicc_release_link(icc_link); |
1368 | 1.46M | } |
1369 | | |
1370 | | static void |
1371 | | cmap_separation_halftoned(frac all, gx_device_color * pdc, |
1372 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select, |
1373 | | const gs_color_space *pcs) |
1374 | 5.23k | { |
1375 | 5.23k | uint i, ncomps = dev->color_info.num_components; |
1376 | 5.23k | bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1377 | 5.23k | frac comp_value = all; |
1378 | 5.23k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1379 | 5.23k | gsicc_rendering_param_t render_cond; |
1380 | 5.23k | cmm_dev_profile_t *dev_profile = NULL; |
1381 | 5.23k | cmm_profile_t *des_profile = NULL; |
1382 | | |
1383 | 5.23k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1384 | 5.23k | gsicc_extract_profile(dev->graphics_type_tag, |
1385 | 5.23k | dev_profile, &des_profile, &render_cond); |
1386 | | |
1387 | 5.23k | if (pgs->color_component_map.sep_type == SEP_ALL) { |
1388 | | /* |
1389 | | * Invert the photometric interpretation for additive |
1390 | | * color spaces because separations are always subtractive. |
1391 | | */ |
1392 | 0 | if (additive) |
1393 | 0 | comp_value = frac_1 - comp_value; |
1394 | | |
1395 | | /* Use the "all" value for all components */ |
1396 | 0 | for (i = 0; i < pgs->color_component_map.num_colorants; i++) |
1397 | 0 | cm_comps[i] = comp_value; |
1398 | 5.23k | } else { |
1399 | 5.23k | if (pgs->color_component_map.sep_type == SEP_NONE) { |
1400 | 0 | color_set_null(pdc); |
1401 | 0 | return; |
1402 | 0 | } |
1403 | | |
1404 | | /* map to the color model */ |
1405 | 5.23k | map_components_to_colorants(&all, &(pgs->color_component_map), cm_comps, |
1406 | 5.23k | pgs->color_component_map.num_colorants); |
1407 | 5.23k | } |
1408 | | |
1409 | 5.23k | if (devicen_has_cmyk(dev, des_profile) && |
1410 | 5.23k | des_profile->data_cs == gsCMYK && |
1411 | 5.23k | !named_color_supported(pgs)) { |
1412 | 5.23k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1413 | 5.23k | } |
1414 | | |
1415 | | /* apply the transfer function(s); convert to color values */ |
1416 | 5.23k | if (pgs->effective_transfer_non_identity_count != 0) { |
1417 | 3.96k | int n = 0; |
1418 | 3.96k | if (additive) |
1419 | 0 | n = ncomps < 3 ? ncomps : 3; |
1420 | 3.96k | for (i = 0; i < n; i++) |
1421 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1422 | 3.96k | cm_comps[i], effective_transfer[i]); |
1423 | 27.8k | for (; i < ncomps; i++) |
1424 | 23.8k | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1425 | 3.96k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1426 | 3.96k | } |
1427 | | |
1428 | 5.23k | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1429 | 5.23k | &pgs->screen_phase[select]) == 1) |
1430 | 2.29k | gx_color_load_select(pdc, pgs, dev, select); |
1431 | 5.23k | } |
1432 | | |
1433 | | static void |
1434 | | cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs, |
1435 | | gx_device * dev, gs_color_select_t select, const gs_color_space *pcs) |
1436 | 5.30k | { |
1437 | 5.30k | uint i, nc, ncomps = dev->color_info.num_components; |
1438 | 5.30k | bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1439 | 5.30k | frac comp_value = all; |
1440 | 5.30k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1441 | 5.30k | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1442 | 5.30k | gx_color_index color; |
1443 | 5.30k | bool use_rgb2dev_icc = false; |
1444 | 5.30k | gsicc_rendering_param_t render_cond; |
1445 | 5.30k | cmm_dev_profile_t *dev_profile = NULL; |
1446 | 5.30k | cmm_profile_t *des_profile = NULL; |
1447 | 5.30k | int num_additives = additive ? dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0) : 0; |
1448 | | |
1449 | 5.30k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1450 | 5.30k | gsicc_extract_profile(dev->graphics_type_tag, |
1451 | 5.30k | dev_profile, &des_profile, &render_cond); |
1452 | 5.30k | if (pgs->color_component_map.sep_type == SEP_ALL) { |
1453 | | /* |
1454 | | * Invert the photometric interpretation for additive |
1455 | | * color spaces because separations are always subtractive. |
1456 | | */ |
1457 | 0 | if (additive && num_additives <= 0) { |
1458 | 0 | comp_value = frac_1 - comp_value; |
1459 | 0 | } |
1460 | | |
1461 | | /* Use the "all" value for all components */ |
1462 | 0 | for (i = 0; i < pgs->color_component_map.num_colorants; i++) |
1463 | 0 | cm_comps[i] = comp_value; |
1464 | | /* If our device space is CIELAB then we really want to treat this |
1465 | | as RGB during the fill up here of the separation value and then |
1466 | | go ahead and convert from RGB to CIELAB. The PDF spec is not clear |
1467 | | on how addivite devices should behave with the ALL option but it |
1468 | | is clear from testing the AR 10 does simply do the RGB = 1 - INK |
1469 | | type of mapping */ |
1470 | 0 | if (des_profile->data_cs == gsCIELAB || des_profile->islab) { |
1471 | 0 | use_rgb2dev_icc = true; |
1472 | 0 | } |
1473 | 5.30k | } else { |
1474 | 5.30k | if (pgs->color_component_map.sep_type == SEP_NONE) { |
1475 | 0 | color_set_null(pdc); |
1476 | 0 | return; |
1477 | 0 | } |
1478 | | |
1479 | | /* map to the color model */ |
1480 | 5.30k | map_components_to_colorants(&comp_value, &(pgs->color_component_map), cm_comps, |
1481 | 5.30k | pgs->color_component_map.num_colorants); |
1482 | 5.30k | } |
1483 | | |
1484 | | /* Check if we have the standard colorants. If yes, then we will apply |
1485 | | ICC color management to those colorants. */ |
1486 | 5.30k | if (devicen_has_cmyk(dev, des_profile) && des_profile->data_cs == gsCMYK && |
1487 | 5.30k | !named_color_supported(pgs) && pgs->color_component_map.sep_type != SEP_ALL) { |
1488 | | /* We need to do a CMYK to CMYK conversion here. This will always |
1489 | | use the default CMYK profile and the device's output profile. |
1490 | | We probably need to add some checking here |
1491 | | and possibly permute the colorants, much as is done on the input |
1492 | | side for the case when we add DeviceN icc source profiles for use |
1493 | | in PDF and PS data. Also, don't do this if we are doing mapping |
1494 | | through the named color mapping. */ |
1495 | 5.30k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1496 | 5.30k | } |
1497 | | |
1498 | | /* apply the transfer function(s); convert to color values */ |
1499 | 5.30k | nc = ncomps; |
1500 | 5.30k | if (device_encodes_tags(dev)) |
1501 | 0 | nc--; |
1502 | 5.30k | if (pgs->effective_transfer_non_identity_count != 0) { |
1503 | 0 | int n = 0; |
1504 | 0 | if (additive) |
1505 | 0 | n = nc < 3 ? nc : 3; |
1506 | 0 | for (i = 0; i < n; i++) |
1507 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1508 | 0 | cm_comps[i], effective_transfer[i]); |
1509 | 0 | for (; i < nc; i++) |
1510 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1511 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1512 | 0 | } |
1513 | 37.5k | for (i = 0; i < nc; i++) |
1514 | 32.2k | cv[i] = frac2cv(cm_comps[i]); |
1515 | | /* For additive devices, we should invert the process colors |
1516 | | * here! But how do we know how many process colors we have? For |
1517 | | * now we'll have to ask the device using a dso. */ |
1518 | 5.30k | if (additive) { |
1519 | 0 | int j; |
1520 | 0 | for (j = 0; j < num_additives; j++) |
1521 | 0 | cv[j] = 65535 - cv[j]; |
1522 | 0 | } |
1523 | | /* Copy tags untransformed. */ |
1524 | 5.30k | if (nc < ncomps) |
1525 | 0 | cv[nc] = cm_comps[nc]; |
1526 | | |
1527 | 5.30k | if (use_rgb2dev_icc && pgs->icc_manager->default_rgb != NULL) { |
1528 | | /* After the transfer function go ahead and do the mapping from RGB to |
1529 | | the device profile. */ |
1530 | 0 | gsicc_link_t *icc_link; |
1531 | 0 | gsicc_rendering_param_t rendering_params; |
1532 | 0 | unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1533 | |
|
1534 | 0 | rendering_params.black_point_comp = pgs->blackptcomp; |
1535 | 0 | rendering_params.graphics_type_tag = dev->graphics_type_tag; |
1536 | 0 | rendering_params.override_icc = false; |
1537 | 0 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
1538 | 0 | rendering_params.rendering_intent = pgs->renderingintent; |
1539 | 0 | rendering_params.cmm = gsCMM_DEFAULT; |
1540 | |
|
1541 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, pgs->icc_manager->default_rgb, |
1542 | 0 | des_profile, &rendering_params, |
1543 | 0 | pgs->memory, dev_profile->devicegraytok); |
1544 | | /* Transform the color */ |
1545 | 0 | for (i = 0; i < ncomps; i++) { |
1546 | 0 | psrc[i] = cv[i]; |
1547 | 0 | } |
1548 | 0 | (icc_link->procs.map_color)(dev, icc_link, &(psrc[0]), &(psrc_cm[0]), 2); |
1549 | 0 | gsicc_release_link(icc_link); |
1550 | 0 | for (i = 0; i < ncomps; i++) { |
1551 | 0 | cv[i] = psrc_cm[i]; |
1552 | 0 | } |
1553 | 0 | } |
1554 | | /* if output device supports devn, we need to make sure we send it the |
1555 | | proper color type */ |
1556 | 5.30k | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1557 | 37.5k | for (i = 0; i < ncomps; i++) |
1558 | 32.2k | pdc->colors.devn.values[i] = cv[i]; |
1559 | 312k | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
1560 | 307k | pdc->colors.devn.values[i] = 0; |
1561 | 5.30k | pdc->type = gx_dc_type_devn; |
1562 | | |
1563 | | /* Let device set the tags if present */ |
1564 | 5.30k | if (device_encodes_tags(dev)) { |
1565 | 0 | const gx_device *cmdev; |
1566 | 0 | const gx_cm_color_map_procs *cmprocs; |
1567 | |
|
1568 | 0 | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1569 | 0 | cmprocs->map_cmyk(cmdev, 0, 0, 0, 0, cm_comps); |
1570 | 0 | pdc->colors.devn.values[ncomps - 1] = cm_comps[ncomps - 1]; |
1571 | 0 | } |
1572 | 5.30k | return; |
1573 | 5.30k | } |
1574 | | |
1575 | | /* encode as a color index */ |
1576 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1577 | | |
1578 | | /* check if the encoding was successful; we presume failure is rare */ |
1579 | 0 | if (color != gx_no_color_index) { |
1580 | 0 | color_set_pure(pdc, color); |
1581 | 0 | return; |
1582 | 0 | } |
1583 | | |
1584 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1585 | 0 | &pgs->screen_phase[select]) == 1) |
1586 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1587 | 0 | } |
1588 | | |
1589 | | /* ------ DeviceN color mapping */ |
1590 | | |
1591 | | /* |
1592 | | * This routine is called to map a DeviceN colorspace to a DeviceN |
1593 | | * output device which requires halftoning. T |
1594 | | */ |
1595 | | static void |
1596 | | cmap_devicen_halftoned(const frac * pcc, |
1597 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
1598 | | gs_color_select_t select, const gs_color_space *pcs) |
1599 | 1.34M | { |
1600 | 1.34M | uchar i, ncomps = dev->color_info.num_components; |
1601 | 1.34M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1602 | 1.34M | gsicc_rendering_param_t render_cond; |
1603 | 1.34M | cmm_dev_profile_t *dev_profile = NULL; |
1604 | 1.34M | cmm_profile_t *des_profile = NULL; |
1605 | | |
1606 | 1.34M | if (pcs->params.device_n.all_none == true) { |
1607 | 0 | color_set_null(pdc); |
1608 | 0 | return; |
1609 | 0 | } |
1610 | | |
1611 | 1.34M | dev_proc(dev, get_profile)(dev, &dev_profile); |
1612 | 1.34M | gsicc_extract_profile(dev->graphics_type_tag, |
1613 | 1.34M | dev_profile, &des_profile, &render_cond); |
1614 | | /* map to the color model */ |
1615 | 1.34M | map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps, |
1616 | 1.34M | pgs->color_component_map.num_colorants); |
1617 | | /* See comments in cmap_devicen_direct for details on below operations */ |
1618 | 1.34M | if (devicen_has_cmyk(dev, des_profile) && |
1619 | 1.34M | des_profile->data_cs == gsCMYK && |
1620 | 1.34M | !named_color_supported(pgs)) { |
1621 | 1.34M | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1622 | 1.34M | } |
1623 | | /* apply the transfer function(s); convert to color values */ |
1624 | 1.34M | if (pgs->effective_transfer_non_identity_count != 0) { |
1625 | 1.34M | int n = 0; |
1626 | 1.34M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1627 | 0 | n = ncomps < 3 ? ncomps : 3; |
1628 | 1.34M | for (i = 0; i < n; i++) |
1629 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1630 | 1.34M | cm_comps[i], effective_transfer[i]); |
1631 | 8.88M | for (; i < ncomps; i++) |
1632 | 7.54M | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1633 | 1.34M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1634 | 1.34M | } |
1635 | | |
1636 | | /* We need to finish halftoning */ |
1637 | 1.34M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1638 | 1.34M | &pgs->screen_phase[select]) == 1) |
1639 | 880k | gx_color_load_select(pdc, pgs, dev, select); |
1640 | 1.34M | } |
1641 | | |
1642 | | static void |
1643 | | encode_tags(const gx_device *dev, gx_device_color *pdc) |
1644 | 0 | { |
1645 | 0 | const gx_device *cmdev; |
1646 | 0 | const gx_cm_color_map_procs *cmprocs; |
1647 | 0 | uchar ncomps = dev->color_info.num_components; |
1648 | 0 | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1649 | |
|
1650 | 0 | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1651 | 0 | cmprocs->map_cmyk(cmdev, 0, 0, 0, 0, cm_comps); |
1652 | 0 | pdc->colors.devn.values[ncomps - 1] = cm_comps[ncomps - 1]; |
1653 | 0 | } |
1654 | | |
1655 | | /* |
1656 | | * This routine is called to map a DeviceN colorspace to a DeviceN |
1657 | | * output device which does not require halftoning. |
1658 | | */ |
1659 | | static void |
1660 | | cmap_devicen_direct(const frac * pcc, |
1661 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
1662 | | gs_color_select_t select, const gs_color_space *pcs) |
1663 | 117k | { |
1664 | 117k | uchar i, nc, ncomps = dev->color_info.num_components; |
1665 | 117k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1666 | 117k | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1667 | 117k | gx_color_index color; |
1668 | 117k | gsicc_rendering_param_t render_cond; |
1669 | 117k | cmm_dev_profile_t *dev_profile = NULL; |
1670 | 117k | cmm_profile_t *des_profile = NULL; |
1671 | 117k | int additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1672 | | |
1673 | 117k | if (pcs->params.device_n.all_none == true) { |
1674 | 0 | color_set_null(pdc); |
1675 | 0 | return; |
1676 | 0 | } |
1677 | | |
1678 | 117k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1679 | 117k | gsicc_extract_profile(dev->graphics_type_tag, |
1680 | 117k | dev_profile, &des_profile, &render_cond); |
1681 | | /* See the comment below */ |
1682 | | /* map to the color model */ |
1683 | 117k | if (dev_profile->spotnames != NULL && dev_profile->spotnames->equiv_cmyk_set) { |
1684 | 0 | map_components_to_colorants(pcc, dev_profile->spotnames->color_map, |
1685 | 0 | cm_comps, ncomps); |
1686 | 117k | } else { |
1687 | 117k | map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps, |
1688 | 117k | pgs->color_component_map.num_colorants); |
1689 | 117k | } |
1690 | | /* Check if we have the standard colorants. If yes, then we will apply |
1691 | | ICC color management to those colorants. To understand why, consider |
1692 | | the example where I have a Device with CMYK + O and I have a |
1693 | | DeviceN color in the document that is specified for any set of |
1694 | | these colorants, and suppose that I let them pass through |
1695 | | witout any color management. This is probably not the |
1696 | | desired effect since I could have a DeviceN color fill that had 10% C, |
1697 | | 20% M 0% Y 0% K and 0% O. I would like this to look the same |
1698 | | as a CMYK color that will be color managed and specified with 10% C, |
1699 | | 20% M 0% Y 0% K. Hence the CMYK values should go through the same |
1700 | | color management as a stand alone CMYK value. */ |
1701 | 117k | if (devicen_has_cmyk(dev, des_profile) && des_profile->data_cs == gsCMYK && |
1702 | 117k | !named_color_supported(pgs)) { |
1703 | | /* We need to do a CMYK to CMYK conversion here. This will always |
1704 | | use the default CMYK profile and the device's output profile. |
1705 | | We probably need to add some checking here |
1706 | | and possibly permute the colorants, much as is done on the input |
1707 | | side for the case when we add DeviceN icc source profiles for use |
1708 | | in PDF and PS data. Also, don't do this if we are doing mapping |
1709 | | through the named color mapping. */ |
1710 | 117k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1711 | 117k | } |
1712 | 117k | nc = ncomps; |
1713 | 117k | if (device_encodes_tags(dev)) |
1714 | 0 | nc--; |
1715 | | /* apply the transfer function(s); convert to color values. |
1716 | | assign directly if output device supports devn */ |
1717 | 117k | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1718 | 117k | if (pgs->effective_transfer_non_identity_count == 0) |
1719 | 938k | for (i = 0; i < nc; i++) |
1720 | 821k | pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); |
1721 | 0 | else { |
1722 | 0 | int n = 0; |
1723 | 0 | if (additive) |
1724 | 0 | n = nc < 3 ? nc : 3; |
1725 | 0 | for (i = 0; i < n; i++) |
1726 | 0 | pdc->colors.devn.values[i] = frac2cv(gx_map_color_frac(pgs, |
1727 | 0 | cm_comps[i], effective_transfer[i])); |
1728 | 0 | for (; i < nc; i++) |
1729 | 0 | pdc->colors.devn.values[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
1730 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); |
1731 | 0 | } |
1732 | 117k | if (i < ncomps) |
1733 | 0 | pdc->colors.devn.values[i] = cm_comps[i], i++; |
1734 | 6.81M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
1735 | 6.69M | pdc->colors.devn.values[i] = 0; |
1736 | 117k | pdc->type = gx_dc_type_devn; |
1737 | | /* For additive devices, we should invert the process colors |
1738 | | * here! But how do we know how many process colors we have? |
1739 | | * Ask the device using a dso. */ |
1740 | 117k | if (additive) { |
1741 | 0 | int j, n = dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0); |
1742 | 0 | for (j = 0; j < n; j++) |
1743 | 0 | pdc->colors.devn.values[j] = 65535 - pdc->colors.devn.values[j]; |
1744 | 0 | } |
1745 | | |
1746 | | /* Let device set the tags if present */ |
1747 | 117k | if (device_encodes_tags(dev)) |
1748 | 0 | encode_tags(dev, pdc); |
1749 | | |
1750 | 117k | return; |
1751 | 117k | } |
1752 | | |
1753 | 0 | if (pgs->effective_transfer_non_identity_count != 0) { |
1754 | 0 | int n = 0; |
1755 | 0 | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1756 | 0 | n = nc < 3 ? nc : 3; |
1757 | 0 | for (i = 0; i < n; i++) |
1758 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1759 | 0 | cm_comps[i], effective_transfer[i]); |
1760 | 0 | for (; i < nc; i++) |
1761 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1762 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1763 | 0 | } |
1764 | 0 | if (nc < ncomps) |
1765 | 0 | encode_tags(dev, pdc); |
1766 | | /* For additive devices, we should invert the process colors |
1767 | | * here! But how do we know how many process colors we have? |
1768 | | * Ask the device using a dso. */ |
1769 | 0 | if (additive) { |
1770 | 0 | int j, n = dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0); |
1771 | 0 | for (j = 0; j < n; j++) |
1772 | 0 | cm_comps[j] = frac_1 - cm_comps[j]; |
1773 | 0 | } |
1774 | 0 | for (i = 0; i < nc; i++) |
1775 | 0 | cv[i] = frac2cv(cm_comps[i]); |
1776 | 0 | if(i < ncomps) |
1777 | 0 | cv[i] = cm_comps[i]; |
1778 | | /* encode as a color index */ |
1779 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1780 | | /* check if the encoding was successful; we presume failure is rare */ |
1781 | 0 | if (color != gx_no_color_index) { |
1782 | 0 | color_set_pure(pdc, color); |
1783 | 0 | return; |
1784 | 0 | } |
1785 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1786 | 0 | &pgs->screen_phase[select]) == 1) |
1787 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1788 | 0 | } |
1789 | | |
1790 | | /* ------ Halftoning check ----- */ |
1791 | | |
1792 | | static bool |
1793 | | cmap_halftoned_is_halftoned(const gs_gstate * pgs, gx_device * dev) |
1794 | 1.38M | { |
1795 | 1.38M | return true; |
1796 | 1.38M | } |
1797 | | |
1798 | | static bool |
1799 | | cmap_direct_is_halftoned(const gs_gstate * pgs, gx_device * dev) |
1800 | 4.20M | { |
1801 | 4.20M | return false; |
1802 | 4.20M | } |
1803 | | |
1804 | | /* ------ Transfer function mapping ------ */ |
1805 | | |
1806 | | /* Define an identity transfer function. */ |
1807 | | float |
1808 | | gs_identity_transfer(double value, const gx_transfer_map * pmap) |
1809 | 78.8M | { |
1810 | 78.8M | return (float) value; |
1811 | 78.8M | } |
1812 | | |
1813 | | /* Define the generic transfer function for the library layer. */ |
1814 | | /* This just returns what's already in the map. */ |
1815 | | float |
1816 | | gs_mapped_transfer(double value, const gx_transfer_map * pmap) |
1817 | 6 | { |
1818 | 6 | int index = (int)((value) * (transfer_map_size) + 0.5); |
1819 | 6 | if (index > transfer_map_size - 1) |
1820 | 0 | index = transfer_map_size - 1; |
1821 | 6 | return frac2float(pmap->values[index]); |
1822 | 6 | } |
1823 | | |
1824 | | /* Set a transfer map to the identity map. */ |
1825 | | void |
1826 | | gx_set_identity_transfer(gx_transfer_map *pmap) |
1827 | 1.91M | { |
1828 | 1.91M | int i; |
1829 | | |
1830 | 1.91M | pmap->proc = gs_identity_transfer; |
1831 | | /* We still have to fill in the cached values. */ |
1832 | 491M | for (i = 0; i < transfer_map_size; ++i) |
1833 | 489M | pmap->values[i] = bits2frac(i, log2_transfer_map_size); |
1834 | 1.91M | } |
1835 | | |
1836 | | #if FRAC_MAP_INTERPOLATE /* NOTA BENE */ |
1837 | | |
1838 | | /* Map a color fraction through a transfer map. */ |
1839 | | /* We only use this if we are interpolating. */ |
1840 | | frac |
1841 | | gx_color_frac_map(frac cv, const frac * values) |
1842 | 1.86G | { |
1843 | 1.86G | #define cp_frac_bits (frac_bits - log2_transfer_map_size) |
1844 | 1.86G | int cmi = frac2bits_floor(cv, log2_transfer_map_size); |
1845 | 1.86G | frac mv = values[cmi]; |
1846 | 1.86G | int rem, mdv; |
1847 | | |
1848 | | /* Interpolate between two adjacent values if needed. */ |
1849 | 1.86G | rem = cv - bits2frac(cmi, log2_transfer_map_size); |
1850 | 1.86G | if (rem == 0) |
1851 | 1.54G | return mv; |
1852 | 318M | mdv = values[cmi + 1] - mv; |
1853 | | #if ARCH_INTS_ARE_SHORT |
1854 | | /* Only use long multiplication if necessary. */ |
1855 | | if (mdv < -(1 << (16 - cp_frac_bits)) || |
1856 | | mdv > 1 << (16 - cp_frac_bits) |
1857 | | ) |
1858 | | return mv + (uint) (((ulong) rem * mdv) >> cp_frac_bits); |
1859 | | #endif |
1860 | 318M | return mv + ((rem * mdv) >> cp_frac_bits); |
1861 | 1.86G | #undef cp_frac_bits |
1862 | 1.86G | } |
1863 | | |
1864 | | #endif /* FRAC_MAP_INTERPOLATE */ |
1865 | | |
1866 | | /* ------ Default device color mapping ------ */ |
1867 | | /* White-on-black */ |
1868 | | gx_color_index |
1869 | | gx_default_w_b_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1870 | 486 | { /* Map values >= 1/2 to 1, < 1/2 to 0. */ |
1871 | 486 | int i, ncomps = dev->color_info.num_components; |
1872 | 486 | gx_color_value cv_all = 0; |
1873 | | |
1874 | 972 | for (i = 0; i < ncomps; i++) |
1875 | 486 | cv_all |= cv[i]; |
1876 | 486 | return cv_all > gx_max_color_value / 2 ? (gx_color_index)1 |
1877 | 486 | : (gx_color_index)0; |
1878 | | |
1879 | 486 | } |
1880 | | |
1881 | | int |
1882 | | gx_default_w_b_map_color_rgb(gx_device * dev, gx_color_index color, |
1883 | | gx_color_value prgb[3]) |
1884 | 1.02M | { /* Map 1 to max_value, 0 to 0. */ |
1885 | 1.02M | prgb[0] = prgb[1] = prgb[2] = -(gx_color_value) color; |
1886 | 1.02M | return 0; |
1887 | 1.02M | } |
1888 | | |
1889 | | gx_color_index |
1890 | | gx_default_w_b_mono_encode_color(gx_device *dev, const gx_color_value cv[]) |
1891 | 0 | { |
1892 | 0 | return cv[0] > gx_max_color_value / 2 ? (gx_color_index)1 |
1893 | 0 | : (gx_color_index)0; |
1894 | 0 | } |
1895 | | |
1896 | | int |
1897 | | gx_default_w_b_mono_decode_color(gx_device * dev, gx_color_index color, |
1898 | | gx_color_value pgray[]) |
1899 | 0 | { /* Map 0 to max_value, 1 to 0. */ |
1900 | 0 | pgray[0] = -(gx_color_value) color; |
1901 | 0 | return 0; |
1902 | 0 | } |
1903 | | |
1904 | | /* Black-on-white */ |
1905 | | gx_color_index |
1906 | | gx_default_b_w_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1907 | 179M | { |
1908 | 179M | uchar i, ncomps = dev->color_info.num_components; |
1909 | 179M | gx_color_value cv_all = 0; |
1910 | | |
1911 | 359M | for (i = 0; i < ncomps; i++) |
1912 | 179M | cv_all |= cv[i]; |
1913 | 179M | return cv_all > gx_max_color_value / 2 ? (gx_color_index)0 |
1914 | 179M | : (gx_color_index)1; |
1915 | 179M | } |
1916 | | |
1917 | | int |
1918 | | gx_default_b_w_map_color_rgb(gx_device * dev, gx_color_index color, |
1919 | | gx_color_value prgb[3]) |
1920 | 154k | { /* Map 0 to max_value, 1 to 0. */ |
1921 | 154k | prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1); |
1922 | 154k | return 0; |
1923 | 154k | } |
1924 | | |
1925 | | gx_color_index |
1926 | | gx_default_b_w_mono_encode_color(gx_device *dev, const gx_color_value cv[]) |
1927 | 0 | { |
1928 | 0 | return cv[0] > gx_max_color_value / 2 ? (gx_color_index)0 |
1929 | 0 | : (gx_color_index)1; |
1930 | 0 | } |
1931 | | |
1932 | | int |
1933 | | gx_default_b_w_mono_decode_color(gx_device * dev, gx_color_index color, |
1934 | | gx_color_value pgray[]) |
1935 | 0 | { /* Map 0 to max_value, 1 to 0. */ |
1936 | 0 | pgray[0] = -((gx_color_value) color ^ 1); |
1937 | 0 | return 0; |
1938 | 0 | } |
1939 | | |
1940 | | /* RGB mapping for gray-scale devices */ |
1941 | | |
1942 | | gx_color_index |
1943 | | gx_default_gray_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1944 | 9.25M | { /* We round the value rather than truncating it. */ |
1945 | 9.25M | gx_color_value gray = |
1946 | 9.25M | (((cv[0] * (ulong) lum_red_weight) + |
1947 | 9.25M | (cv[1] * (ulong) lum_green_weight) + |
1948 | 9.25M | (cv[2] * (ulong) lum_blue_weight) + |
1949 | 9.25M | (lum_all_weights / 2)) / lum_all_weights |
1950 | 9.25M | * dev->color_info.max_gray + |
1951 | 9.25M | (gx_max_color_value / 2)) / gx_max_color_value; |
1952 | | |
1953 | 9.25M | return gray; |
1954 | 9.25M | } |
1955 | | |
1956 | | int |
1957 | | gx_default_gray_map_color_rgb(gx_device * dev, gx_color_index color, |
1958 | | gx_color_value prgb[3]) |
1959 | 9.25M | { |
1960 | 9.25M | gx_color_value gray = (gx_color_value) |
1961 | 9.25M | (color * gx_max_color_value / dev->color_info.max_gray); |
1962 | | |
1963 | 9.25M | prgb[0] = gray; |
1964 | 9.25M | prgb[1] = gray; |
1965 | 9.25M | prgb[2] = gray; |
1966 | 9.25M | return 0; |
1967 | 9.25M | } |
1968 | | |
1969 | | gx_color_index |
1970 | | gx_default_gray_encode_color(gx_device * dev, const gx_color_value cv[]) |
1971 | 0 | { |
1972 | 0 | gx_color_value gray = (cv[0] * dev->color_info.max_gray + |
1973 | 0 | (gx_max_color_value / 2)) / gx_max_color_value; |
1974 | |
|
1975 | 0 | return gray; |
1976 | 0 | } |
1977 | | |
1978 | | int |
1979 | | gx_default_gray_decode_color(gx_device * dev, gx_color_index color, |
1980 | | gx_color_value *cv) |
1981 | 0 | { |
1982 | 0 | gx_color_value gray = (gx_color_value) |
1983 | 0 | (color * gx_max_color_value / dev->color_info.max_gray); |
1984 | |
|
1985 | 0 | cv[0] = gray; |
1986 | 0 | return 0; |
1987 | 0 | } |
1988 | | |
1989 | | gx_color_index |
1990 | | gx_default_8bit_map_gray_color(gx_device * dev, const gx_color_value cv[]) |
1991 | 57.3M | { |
1992 | 57.3M | gx_color_index color = gx_color_value_to_byte(cv[0]); |
1993 | | |
1994 | 57.3M | return color; |
1995 | 57.3M | } |
1996 | | |
1997 | | int |
1998 | | gx_default_8bit_map_color_gray(gx_device * dev, gx_color_index color, |
1999 | | gx_color_value pgray[]) |
2000 | 0 | { |
2001 | 0 | pgray[0] = (gx_color_value)(color * gx_max_color_value / 255); |
2002 | 0 | return 0; |
2003 | 0 | } |
2004 | | |
2005 | | /* RGB mapping for 24-bit true (RGB) color devices */ |
2006 | | |
2007 | | gx_color_index |
2008 | | gx_default_rgb_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
2009 | 731M | { |
2010 | 731M | if (dev->color_info.depth == 24) |
2011 | 731M | return gx_color_value_to_byte(cv[2]) + |
2012 | 731M | ((uint) gx_color_value_to_byte(cv[1]) << 8) + |
2013 | 731M | ((ulong) gx_color_value_to_byte(cv[0]) << 16); |
2014 | 0 | else { |
2015 | 0 | COLROUND_VARS; |
2016 | 0 | int bpc = dev->color_info.depth / 3; |
2017 | 0 | COLROUND_SETUP(bpc); |
2018 | |
|
2019 | 0 | return (((COLROUND_ROUND(cv[0]) << bpc) + |
2020 | 0 | COLROUND_ROUND(cv[1])) << bpc) + |
2021 | 0 | COLROUND_ROUND(cv[2]); |
2022 | 0 | } |
2023 | 731M | } |
2024 | | |
2025 | | /* Map a color index to a r-g-b color. */ |
2026 | | int |
2027 | | gx_default_rgb_map_color_rgb(gx_device * dev, gx_color_index color, |
2028 | | gx_color_value prgb[3]) |
2029 | 12.4M | { |
2030 | 12.4M | if (dev->color_info.depth == 24) { |
2031 | 12.4M | prgb[0] = gx_color_value_from_byte(color >> 16); |
2032 | 12.4M | prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff); |
2033 | 12.4M | prgb[2] = gx_color_value_from_byte(color & 0xff); |
2034 | 12.4M | } else { |
2035 | 0 | uint bits_per_color = dev->color_info.depth / 3; |
2036 | 0 | uint color_mask = (1 << bits_per_color) - 1; |
2037 | |
|
2038 | 0 | prgb[0] = ((color >> (bits_per_color * 2)) & color_mask) * |
2039 | 0 | (ulong) gx_max_color_value / color_mask; |
2040 | 0 | prgb[1] = ((color >> (bits_per_color)) & color_mask) * |
2041 | 0 | (ulong) gx_max_color_value / color_mask; |
2042 | 0 | prgb[2] = (color & color_mask) * |
2043 | 0 | (ulong) gx_max_color_value / color_mask; |
2044 | 0 | } |
2045 | 12.4M | return 0; |
2046 | 12.4M | } |
2047 | | |
2048 | | /* CMYK mapping for RGB devices (should never be called!) */ |
2049 | | |
2050 | | gx_color_index |
2051 | | gx_default_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2052 | 0 | { /* Convert to RGB */ |
2053 | 0 | frac rgb[3]; |
2054 | 0 | gx_color_value rgb_cv[3]; |
2055 | 0 | color_cmyk_to_rgb(cv2frac(cv[0]), cv2frac(cv[1]), cv2frac(cv[2]), cv2frac(cv[3]), |
2056 | 0 | NULL, rgb, dev->memory); |
2057 | 0 | rgb_cv[0] = frac2cv(rgb[0]); |
2058 | 0 | rgb_cv[1] = frac2cv(rgb[1]); |
2059 | 0 | rgb_cv[2] = frac2cv(rgb[2]); |
2060 | 0 | return (*dev_proc(dev, map_rgb_color)) (dev, rgb_cv); |
2061 | 0 | } |
2062 | | |
2063 | | /* Mapping for CMYK devices */ |
2064 | | |
2065 | | gx_color_index |
2066 | | cmyk_1bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2067 | 0 | { |
2068 | 0 | #define CV_BIT(v) ((v) >> (gx_color_value_bits - 1)) |
2069 | 0 | return (gx_color_index) |
2070 | 0 | (CV_BIT(cv[3]) + (CV_BIT(cv[2]) << 1) + (CV_BIT(cv[1]) << 2) + (CV_BIT(cv[0]) << 3)); |
2071 | 0 | #undef CV_BIT |
2072 | 0 | } |
2073 | | |
2074 | | /* Shouldn't be called: decode_color should be cmyk_1bit_map_color_cmyk */ |
2075 | | int |
2076 | | cmyk_1bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2077 | | gx_color_value prgb[3]) |
2078 | 0 | { |
2079 | 0 | if (color & 1) |
2080 | 0 | prgb[0] = prgb[1] = prgb[2] = 0; |
2081 | 0 | else { |
2082 | 0 | prgb[0] = (color & 8 ? 0 : gx_max_color_value); |
2083 | 0 | prgb[1] = (color & 4 ? 0 : gx_max_color_value); |
2084 | 0 | prgb[2] = (color & 2 ? 0 : gx_max_color_value); |
2085 | 0 | } |
2086 | 0 | return 0; |
2087 | 0 | } |
2088 | | |
2089 | | int |
2090 | | cmyk_1bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2091 | | gx_color_value pcv[]) |
2092 | 0 | { |
2093 | 0 | pcv[0] = (color & 8 ? 0 : gx_max_color_value); |
2094 | 0 | pcv[1] = (color & 4 ? 0 : gx_max_color_value); |
2095 | 0 | pcv[2] = (color & 2 ? 0 : gx_max_color_value); |
2096 | 0 | pcv[3] = (color & 1 ? 0 : gx_max_color_value); |
2097 | 0 | return 0; |
2098 | 0 | } |
2099 | | |
2100 | | gx_color_index |
2101 | | cmyk_8bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2102 | 0 | { |
2103 | 0 | gx_color_index color = |
2104 | 0 | gx_color_value_to_byte(cv[3]) + |
2105 | 0 | ((uint)gx_color_value_to_byte(cv[2]) << 8) + |
2106 | 0 | ((uint)gx_color_value_to_byte(cv[1]) << 16) + |
2107 | 0 | ((uint)gx_color_value_to_byte(cv[0]) << 24); |
2108 | |
|
2109 | 0 | #if ARCH_SIZEOF_GX_COLOR_INDEX > 4 |
2110 | 0 | return color; |
2111 | | #else |
2112 | | return (color == gx_no_color_index ? color ^ 1 : color); |
2113 | | #endif |
2114 | 0 | } |
2115 | | |
2116 | | gx_color_index |
2117 | | cmyk_16bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2118 | 0 | { |
2119 | 0 | gx_color_index color = |
2120 | 0 | (uint64_t)cv[3] + |
2121 | 0 | ((uint64_t)cv[2] << 16) + |
2122 | 0 | ((uint64_t)cv[1] << 32) + |
2123 | 0 | ((uint64_t)cv[0] << 48); |
2124 | |
|
2125 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
2126 | 0 | } |
2127 | | |
2128 | | /* Shouldn't be called: decode_color should be cmyk_8bit_map_color_cmyk */ |
2129 | | int |
2130 | | cmyk_8bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2131 | | gx_color_value prgb[3]) |
2132 | 0 | { |
2133 | 0 | int |
2134 | 0 | not_k = (int) (~color & 0xff), |
2135 | 0 | r = not_k - (int) (color >> 24), |
2136 | 0 | g = not_k - (int) ((color >> 16) & 0xff), |
2137 | 0 | b = not_k - (int) ((color >> 8) & 0xff); |
2138 | |
|
2139 | 0 | prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r)); |
2140 | 0 | prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g)); |
2141 | 0 | prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b)); |
2142 | 0 | return 0; |
2143 | 0 | } |
2144 | | |
2145 | | int |
2146 | | cmyk_8bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2147 | | gx_color_value pcv[]) |
2148 | 0 | { |
2149 | 0 | pcv[0] = gx_color_value_from_byte((color >> 24) & 0xff); |
2150 | 0 | pcv[1] = gx_color_value_from_byte((color >> 16) & 0xff); |
2151 | 0 | pcv[2] = gx_color_value_from_byte((color >> 8) & 0xff); |
2152 | 0 | pcv[3] = gx_color_value_from_byte(color & 0xff); |
2153 | 0 | return 0; |
2154 | 0 | } |
2155 | | |
2156 | | int |
2157 | | cmyk_16bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2158 | | gx_color_value pcv[]) |
2159 | 0 | { |
2160 | 0 | pcv[0] = ((color >> 24) >> 24) & 0xffff; |
2161 | 0 | pcv[1] = ((color >> 16) >> 16) & 0xffff; |
2162 | 0 | pcv[2] = ( color >> 16) & 0xffff; |
2163 | 0 | pcv[3] = ( color ) & 0xffff; |
2164 | 0 | return 0; |
2165 | 0 | } |
2166 | | |
2167 | | int |
2168 | | cmyk_16bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2169 | | gx_color_value prgb[3]) |
2170 | 0 | { |
2171 | 0 | gx_color_value c = ((color >> 24) >> 24) & 0xffff; |
2172 | 0 | gx_color_value m = ((color >> 16) >> 16) & 0xffff; |
2173 | 0 | gx_color_value y = ( color >> 16) & 0xffff; |
2174 | 0 | gx_color_value not_k = (~color ) & 0xffff; |
2175 | 0 | int r = not_k - c; |
2176 | 0 | int g = not_k - m; |
2177 | 0 | int b = not_k - y; |
2178 | |
|
2179 | 0 | prgb[0] = (r < 0 ? 0 : r); |
2180 | 0 | prgb[1] = (g < 0 ? 0 : g); |
2181 | 0 | prgb[2] = (b < 0 ? 0 : b); |
2182 | 0 | return 0; |
2183 | 0 | } |
2184 | | |
2185 | | frac |
2186 | | gx_unit_frac(float fvalue) |
2187 | 12.1M | { |
2188 | 12.1M | frac f = frac_0; |
2189 | 12.1M | if (is_fneg(fvalue)) |
2190 | 0 | f = frac_0; |
2191 | 12.1M | else if (is_fge1(fvalue)) |
2192 | 316k | f = frac_1; |
2193 | 11.8M | else |
2194 | 11.8M | f = float2frac(fvalue); |
2195 | 12.1M | return f; |
2196 | 12.1M | } |
2197 | | |
2198 | | static void |
2199 | | cmapper_transfer_halftone_add(gx_cmapper_t *data) |
2200 | 1.02M | { |
2201 | 1.02M | gx_color_value *pconc = &data->conc[0]; |
2202 | 1.02M | const gs_gstate * pgs = data->pgs; |
2203 | 1.02M | gx_device * dev = data->dev; |
2204 | 1.02M | gs_color_select_t select = data->select; |
2205 | 1.02M | uchar ncomps = dev->color_info.num_components; |
2206 | 1.02M | frac frac_value; |
2207 | 1.02M | uchar i; |
2208 | 1.02M | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2209 | | |
2210 | | /* apply the transfer function(s) */ |
2211 | 2.05M | for (i = 0; i < ncomps; i++) { |
2212 | 1.02M | frac_value = cv2frac(pconc[i]); |
2213 | 1.02M | cv_frac[i] = gx_map_color_frac(pgs, frac_value, effective_transfer[i]); |
2214 | 1.02M | } |
2215 | | /* Halftoning */ |
2216 | 1.02M | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2217 | 1.02M | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2218 | 677k | gx_color_load_select(&data->devc, pgs, dev, select); |
2219 | 1.02M | } |
2220 | | |
2221 | | static void |
2222 | | cmapper_transfer_halftone_op(gx_cmapper_t *data) |
2223 | 0 | { |
2224 | 0 | gx_color_value *pconc = &data->conc[0]; |
2225 | 0 | const gs_gstate * pgs = data->pgs; |
2226 | 0 | gx_device * dev = data->dev; |
2227 | 0 | gs_color_select_t select = data->select; |
2228 | 0 | uchar ncomps = dev->color_info.num_components; |
2229 | 0 | frac frac_value; |
2230 | 0 | uchar i; |
2231 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2232 | | |
2233 | | /* apply the transfer function(s) */ |
2234 | 0 | uint k = dev->color_info.black_component; |
2235 | 0 | for (i = 0; i < ncomps; i++) { |
2236 | 0 | frac_value = cv2frac(pconc[i]); |
2237 | 0 | if (i == k) { |
2238 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2239 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2240 | 0 | } else { |
2241 | 0 | cv_frac[i] = frac_value; /* Ignore transfer, see PLRM3 p. 494 */ |
2242 | 0 | } |
2243 | 0 | } |
2244 | | /* Halftoning */ |
2245 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2246 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2247 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2248 | 0 | } |
2249 | | |
2250 | | static void |
2251 | | cmapper_transfer_halftone_sub(gx_cmapper_t *data) |
2252 | 0 | { |
2253 | 0 | gx_color_value *pconc = &data->conc[0]; |
2254 | 0 | const gs_gstate * pgs = data->pgs; |
2255 | 0 | gx_device * dev = data->dev; |
2256 | 0 | gs_color_select_t select = data->select; |
2257 | 0 | uchar ncomps = dev->color_info.num_components; |
2258 | 0 | frac frac_value; |
2259 | 0 | uchar i; |
2260 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2261 | | |
2262 | | /* apply the transfer function(s) */ |
2263 | 0 | for (i = 0; i < ncomps; i++) { |
2264 | 0 | frac_value = cv2frac(pconc[i]); |
2265 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2266 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2267 | 0 | } |
2268 | | /* Halftoning */ |
2269 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2270 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2271 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2272 | 0 | } |
2273 | | |
2274 | | static void |
2275 | | cmapper_transfer_add(gx_cmapper_t *data) |
2276 | 5.95M | { |
2277 | 5.95M | gx_color_value *pconc = &data->conc[0]; |
2278 | 5.95M | const gs_gstate * pgs = data->pgs; |
2279 | 5.95M | gx_device * dev = data->dev; |
2280 | 5.95M | uchar ncomps = dev->color_info.num_components; |
2281 | 5.95M | frac frac_value; |
2282 | 5.95M | uchar i; |
2283 | 5.95M | gx_color_index color; |
2284 | | |
2285 | | /* apply the transfer function(s) */ |
2286 | 5.95M | if (device_encodes_tags(dev)) |
2287 | 0 | ncomps--; |
2288 | 11.9M | for (i = 0; i < ncomps; i++) { |
2289 | 5.95M | frac_value = cv2frac(pconc[i]); |
2290 | 5.95M | frac_value = gx_map_color_frac(pgs, |
2291 | 5.95M | frac_value, effective_transfer[i]); |
2292 | 5.95M | pconc[i] = frac2cv(frac_value); |
2293 | 5.95M | } |
2294 | | /* Halftoning */ |
2295 | 5.95M | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2296 | | /* check if the encoding was successful; we presume failure is rare */ |
2297 | 5.95M | if (color != gx_no_color_index) |
2298 | 5.95M | color_set_pure(&data->devc, color); |
2299 | 5.95M | } |
2300 | | |
2301 | | static void |
2302 | | cmapper_transfer_op(gx_cmapper_t *data) |
2303 | 0 | { |
2304 | 0 | gx_color_value *pconc = &data->conc[0]; |
2305 | 0 | const gs_gstate * pgs = data->pgs; |
2306 | 0 | gx_device * dev = data->dev; |
2307 | 0 | frac frac_value; |
2308 | 0 | gx_color_index color; |
2309 | |
|
2310 | 0 | uint k = dev->color_info.black_component; |
2311 | | /* Ignore transfer for non blacks, see PLRM3 p. 494 */ |
2312 | 0 | frac_value = cv2frac(pconc[k]); |
2313 | 0 | frac_value = frac_1 - gx_map_color_frac(pgs, |
2314 | 0 | (frac)(frac_1 - frac_value), effective_transfer[k]); |
2315 | 0 | pconc[k] = frac2cv(frac_value); |
2316 | | /* Halftoning */ |
2317 | 0 | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2318 | | /* check if the encoding was successful; we presume failure is rare */ |
2319 | 0 | if (color != gx_no_color_index) |
2320 | 0 | color_set_pure(&data->devc, color); |
2321 | 0 | } |
2322 | | |
2323 | | static void |
2324 | | cmapper_transfer_sub(gx_cmapper_t *data) |
2325 | 0 | { |
2326 | 0 | gx_color_value *pconc = &data->conc[0]; |
2327 | 0 | const gs_gstate * pgs = data->pgs; |
2328 | 0 | gx_device * dev = data->dev; |
2329 | 0 | uchar ncomps = dev->color_info.num_components; |
2330 | 0 | frac frac_value; |
2331 | 0 | uchar i; |
2332 | 0 | gx_color_index color; |
2333 | | |
2334 | | /* apply the transfer function(s) */ |
2335 | 0 | if (device_encodes_tags(dev)) |
2336 | 0 | ncomps--; |
2337 | 0 | for (i = 0; i < ncomps; i++) { |
2338 | 0 | frac_value = cv2frac(pconc[i]); |
2339 | 0 | frac_value = frac_1 - gx_map_color_frac(pgs, |
2340 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2341 | 0 | pconc[i] = frac2cv(frac_value); |
2342 | 0 | } |
2343 | | /* Halftoning */ |
2344 | 0 | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2345 | | /* check if the encoding was successful; we presume failure is rare */ |
2346 | 0 | if (color != gx_no_color_index) |
2347 | 0 | color_set_pure(&data->devc, color); |
2348 | 0 | } |
2349 | | |
2350 | | /* This is used by image color render to handle the cases where we need to |
2351 | | perform either a transfer function or halftoning on the color values |
2352 | | during an ICC color flow. In this case, the color is already in the |
2353 | | device color space but in 16bpp color values. */ |
2354 | | static void |
2355 | | cmapper_halftone(gx_cmapper_t *data) |
2356 | 0 | { |
2357 | 0 | gx_color_value *pconc = &data->conc[0]; |
2358 | 0 | const gs_gstate * pgs = data->pgs; |
2359 | 0 | gx_device * dev = data->dev; |
2360 | 0 | gs_color_select_t select = data->select; |
2361 | 0 | uchar ncomps = dev->color_info.num_components; |
2362 | 0 | uchar i; |
2363 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2364 | | |
2365 | | /* We need this to be in frac form */ |
2366 | 0 | for (i = 0; i < ncomps; i++) { |
2367 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2368 | 0 | } |
2369 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2370 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2371 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2372 | 0 | } |
2373 | | |
2374 | | /* This is used by image color render to handle the cases where we need to |
2375 | | perform either a transfer function or halftoning on the color values |
2376 | | during an ICC color flow. In this case, the color is already in the |
2377 | | device color space but in 16bpp color values. */ |
2378 | | static void |
2379 | | cmapper_vanilla(gx_cmapper_t *data) |
2380 | 108M | { |
2381 | 108M | gx_color_value *pconc = &data->conc[0]; |
2382 | 108M | gx_device * dev = data->dev; |
2383 | 108M | gx_color_index color; |
2384 | | |
2385 | 108M | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2386 | | /* check if the encoding was successful; we presume failure is rare */ |
2387 | 108M | if (color != gx_no_color_index) |
2388 | 108M | color_set_pure(&data->devc, color); |
2389 | 108M | } |
2390 | | |
2391 | | void |
2392 | | gx_get_cmapper(gx_cmapper_t *data, const gs_gstate *pgs, |
2393 | | gx_device *dev, bool has_transfer, bool has_halftone, |
2394 | | gs_color_select_t select) |
2395 | 2.01M | { |
2396 | 2.01M | memset(&(data->conc[0]), 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS])); |
2397 | 2.01M | data->pgs = pgs; |
2398 | 2.01M | data->dev = dev; |
2399 | 2.01M | data->select = select; |
2400 | 2.01M | data->devc.type = gx_dc_type_none; |
2401 | 2.01M | data->direct = 0; |
2402 | | /* Per spec. Images with soft mask, and the mask, do not use transfer function */ |
2403 | 2.01M | if (pgs->effective_transfer_non_identity_count == 0 || |
2404 | 546k | (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0) |
2405 | 1.89M | has_transfer = 0; |
2406 | 2.01M | if (has_transfer) { |
2407 | 120k | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2408 | 120k | if (has_halftone) |
2409 | 13.4k | data->set_color = cmapper_transfer_halftone_add; |
2410 | 107k | else |
2411 | 107k | data->set_color = cmapper_transfer_add; |
2412 | 120k | } else if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { |
2413 | 0 | if (has_halftone) |
2414 | 0 | data->set_color = cmapper_transfer_halftone_op; |
2415 | 0 | else |
2416 | 0 | data->set_color = cmapper_transfer_op; |
2417 | 0 | } else { |
2418 | 0 | if (has_halftone) |
2419 | 0 | data->set_color = cmapper_transfer_halftone_sub; |
2420 | 0 | else |
2421 | 0 | data->set_color = cmapper_transfer_sub; |
2422 | 0 | } |
2423 | 1.89M | } else { |
2424 | 1.89M | if (has_halftone) |
2425 | 0 | data->set_color = cmapper_halftone; |
2426 | 1.89M | else { |
2427 | 1.89M | int code = dev_proc(dev, dev_spec_op)(dev, gxdso_is_encoding_direct, NULL, 0); |
2428 | 1.89M | data->set_color = cmapper_vanilla; |
2429 | 1.89M | data->direct = (code == 1); |
2430 | 1.89M | } |
2431 | 1.89M | } |
2432 | 2.01M | } |
2433 | | |
2434 | | /* This is used by image color render to handle the cases where we need to |
2435 | | perform either a transfer function or halftoning on the color values |
2436 | | during an ICC color flow. In this case, the color is already in the |
2437 | | device color space but in 16bpp color values. */ |
2438 | | void |
2439 | | cmap_transfer_halftone(gx_color_value *pconc, gx_device_color * pdc, |
2440 | | const gs_gstate * pgs, gx_device * dev, bool has_transfer, |
2441 | | bool has_halftone, gs_color_select_t select) |
2442 | 0 | { |
2443 | 0 | uchar nc, ncomps = dev->color_info.num_components; |
2444 | 0 | frac frac_value; |
2445 | 0 | uchar i; |
2446 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2447 | 0 | gx_color_index color; |
2448 | 0 | gx_color_value color_val[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2449 | | |
2450 | | /* apply the transfer function(s) */ |
2451 | 0 | nc = ncomps; |
2452 | 0 | if (device_encodes_tags(dev)) |
2453 | 0 | nc--; |
2454 | 0 | if (has_transfer) { |
2455 | 0 | if (pgs->effective_transfer_non_identity_count == 0) { |
2456 | 0 | for (i = 0; i < nc; i++) |
2457 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2458 | 0 | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2459 | 0 | for (i = 0; i < nc; i++) { |
2460 | 0 | frac_value = cv2frac(pconc[i]); |
2461 | 0 | cv_frac[i] = gx_map_color_frac(pgs, |
2462 | 0 | frac_value, effective_transfer[i]); |
2463 | 0 | } |
2464 | 0 | } else { |
2465 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2466 | 0 | uint k = dev->color_info.black_component; |
2467 | 0 | for (i = 0; i < nc; i++) { |
2468 | 0 | frac_value = cv2frac(pconc[i]); |
2469 | 0 | if (i == k) { |
2470 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2471 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2472 | 0 | } else { |
2473 | 0 | cv_frac[i] = cv2frac(pconc[i]); /* Ignore transfer, see PLRM3 p. 494 */ |
2474 | 0 | } |
2475 | 0 | } |
2476 | 0 | } else { |
2477 | 0 | for (i = 0; i < nc; i++) { |
2478 | 0 | frac_value = cv2frac(pconc[i]); |
2479 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2480 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2481 | 0 | } |
2482 | 0 | } |
2483 | 0 | } |
2484 | 0 | if (nc < ncomps) |
2485 | 0 | cv_frac[nc] = pconc[nc]; |
2486 | 0 | } else { |
2487 | 0 | if (has_halftone) { |
2488 | | /* We need this to be in frac form */ |
2489 | 0 | for (i = 0; i < nc; i++) { |
2490 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2491 | 0 | } |
2492 | 0 | if (nc < ncomps) |
2493 | 0 | cv_frac[nc] = pconc[nc]; |
2494 | 0 | } |
2495 | 0 | } |
2496 | | /* Halftoning */ |
2497 | 0 | if (has_halftone) { |
2498 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), pdc, dev, |
2499 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2500 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
2501 | 0 | } else { |
2502 | | /* We have a frac value from the transfer function. Do the encode. |
2503 | | which does not take a frac value... */ |
2504 | 0 | for (i = 0; i < nc; i++) { |
2505 | 0 | color_val[i] = frac2cv(cv_frac[i]); |
2506 | 0 | } |
2507 | 0 | if (i < ncomps) |
2508 | 0 | color_val[i] = cv_frac[i]; |
2509 | 0 | color = dev_proc(dev, encode_color)(dev, &(color_val[0])); |
2510 | | /* check if the encoding was successful; we presume failure is rare */ |
2511 | 0 | if (color != gx_no_color_index) |
2512 | 0 | color_set_pure(pdc, color); |
2513 | 0 | } |
2514 | 0 | } |
2515 | | |
2516 | | /* This is used by image color render to apply only the transfer function. |
2517 | | We follow this up with threshold rendering. */ |
2518 | | void |
2519 | | cmap_transfer(gx_color_value *pconc, const gs_gstate * pgs, gx_device * dev) |
2520 | 0 | { |
2521 | 0 | uchar ncomps = dev->color_info.num_components; |
2522 | 0 | uchar i; |
2523 | | |
2524 | | /* apply the transfer function(s) */ |
2525 | 0 | if (device_encodes_tags(dev)) |
2526 | 0 | ncomps--; |
2527 | 0 | if (pgs->effective_transfer_non_identity_count == 0) { |
2528 | | /* No transfer function to apply */ |
2529 | 0 | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
2530 | 0 | for (i = 0; i < ncomps; i++) |
2531 | 0 | pconc[i] = frac2cv(gx_map_color_frac(pgs, |
2532 | 0 | cv2frac(pconc[i]), effective_transfer[i])); |
2533 | 0 | else { |
2534 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2535 | 0 | i = dev->color_info.black_component; |
2536 | 0 | if (i < ncomps) |
2537 | 0 | pconc[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
2538 | 0 | (frac)(frac_1 - cv2frac(pconc[i])), effective_transfer[i])); |
2539 | 0 | } else { |
2540 | 0 | for (i = 0; i < ncomps; i++) |
2541 | 0 | pconc[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
2542 | 0 | (frac)(frac_1 - cv2frac(pconc[i])), effective_transfer[i])); |
2543 | 0 | } |
2544 | 0 | } |
2545 | 0 | } |
2546 | | |
2547 | | /* A planar version which applies only one transfer function */ |
2548 | | void |
2549 | | cmap_transfer_plane(gx_color_value *pconc, const gs_gstate *pgs, |
2550 | | gx_device *dev, int plane) |
2551 | 0 | { |
2552 | 0 | frac frac_value; |
2553 | 0 | frac cv_frac; |
2554 | | |
2555 | | /* apply the transfer function(s) */ |
2556 | 0 | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2557 | 0 | frac_value = cv2frac(pconc[0]); |
2558 | 0 | cv_frac = gx_map_color_frac(pgs, frac_value, effective_transfer[plane]); |
2559 | 0 | pconc[0] = frac2cv(cv_frac); |
2560 | 0 | } else { |
2561 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2562 | 0 | uint k = dev->color_info.black_component; |
2563 | 0 | if (plane == k) { |
2564 | 0 | frac_value = cv2frac(pconc[0]); |
2565 | 0 | cv_frac = frac_1 - gx_map_color_frac(pgs, |
2566 | 0 | (frac)(frac_1 - frac_value), effective_transfer[plane]); |
2567 | 0 | pconc[0] = frac2cv(cv_frac); |
2568 | 0 | } |
2569 | 0 | } else { |
2570 | 0 | frac_value = cv2frac(pconc[0]); |
2571 | 0 | cv_frac = frac_1 - gx_map_color_frac(pgs, |
2572 | 0 | (frac)(frac_1 - frac_value), effective_transfer[plane]); |
2573 | 0 | pconc[0] = frac2cv(cv_frac); |
2574 | 0 | } |
2575 | 0 | } |
2576 | 0 | } |
2577 | | |
2578 | | |
2579 | | bool |
2580 | | gx_device_uses_std_cmap_procs(gx_device * dev, const gs_gstate * pgs) |
2581 | 1.52M | { |
2582 | 1.52M | const gx_cm_color_map_procs *pprocs; |
2583 | 1.52M | gsicc_rendering_param_t render_cond; |
2584 | 1.52M | cmm_dev_profile_t *dev_profile = NULL; |
2585 | 1.52M | cmm_profile_t *des_profile = NULL; |
2586 | | |
2587 | 1.52M | dev_proc(dev, get_profile)(dev, &dev_profile); |
2588 | 1.52M | gsicc_extract_profile(dev->graphics_type_tag, |
2589 | 1.52M | dev_profile, &des_profile, &render_cond); |
2590 | | |
2591 | 1.52M | if (des_profile != NULL) { |
2592 | 1.52M | const gx_device *cmdev; |
2593 | | |
2594 | 1.52M | pprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
2595 | | /* Check if they are forwarding procs */ |
2596 | 1.52M | switch(des_profile->num_comps) { |
2597 | 204k | case 1: |
2598 | 204k | if (pprocs == &DeviceGray_procs) { |
2599 | 202k | return true; |
2600 | 202k | } |
2601 | 1.49k | break; |
2602 | 1.24M | case 3: |
2603 | 1.24M | if (pprocs == &DeviceRGB_procs) { |
2604 | 972k | return true; |
2605 | 972k | } |
2606 | 268k | break; |
2607 | 268k | case 4: |
2608 | 82.5k | if (pprocs == &DeviceCMYK_procs) { |
2609 | 0 | return true; |
2610 | 0 | } |
2611 | 82.5k | break; |
2612 | 82.5k | default: |
2613 | 0 | break; |
2614 | 1.52M | } |
2615 | 1.52M | } |
2616 | 352k | return false; |
2617 | 1.52M | } |