/src/ghostpdl/base/gxcmap.c
Line | Count | Source (jump to first uncovered line) |
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 | 12.9k | #define USE_ALT_MAP 0 |
50 | | |
51 | | /* Structure descriptor */ |
52 | | public_st_device_color(); |
53 | | static |
54 | 25.9M | ENUM_PTRS_WITH(device_color_enum_ptrs, gx_device_color *cptr) |
55 | 25.9M | { |
56 | 25.9M | return ENUM_USING(*cptr->type->stype, vptr, size, index); |
57 | 0 | } |
58 | 25.9M | ENUM_PTRS_END |
59 | 25.8M | static RELOC_PTRS_WITH(device_color_reloc_ptrs, gx_device_color *cptr) |
60 | 25.8M | { |
61 | 25.8M | RELOC_USING(*cptr->type->stype, vptr, size); |
62 | 25.8M | } |
63 | 25.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.05M | { |
181 | 2.05M | COLROUND_VARS; |
182 | 2.05M | COLROUND_SETUP(dev->color_info.depth); |
183 | 2.05M | return COLROUND_ROUND(cv[0]); |
184 | 2.05M | } |
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.24M | { |
202 | 9.24M | gx_color_value gray_val = cv[0]; |
203 | 9.24M | gx_color_value rgb_cv[3]; |
204 | | |
205 | 9.24M | rgb_cv[0] = gray_val; |
206 | 9.24M | rgb_cv[1] = gray_val; |
207 | 9.24M | rgb_cv[2] = gray_val; |
208 | 9.24M | return (*dev_proc(dev, map_rgb_color))(dev, rgb_cv); |
209 | 9.24M | } |
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 | 48.7M | { |
216 | 48.7M | out[0] = gray; |
217 | 48.7M | } |
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 | 22.4k | { |
223 | 22.4k | out[0] = color_rgb_to_gray(r, g, b, NULL); |
224 | 22.4k | } |
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 | 3.40k | { |
229 | 3.40k | out[0] = color_cmyk_to_gray(c, m, y, k, NULL); |
230 | 3.40k | } |
231 | | |
232 | | static void |
233 | | gray_cs_to_rgb_cm(const gx_device * dev, frac gray, frac out[]) |
234 | 187k | { |
235 | 187k | out[0] = out[1] = out[2] = gray; |
236 | 187k | } |
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 | 112M | { |
242 | 112M | out[0] = r; |
243 | 112M | out[1] = g; |
244 | 112M | out[2] = b; |
245 | 112M | } |
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 | 19 | { |
293 | 19 | out[0] = out[1] = out[2] = frac_0; |
294 | 19 | out[3] = frac_1 - gray; |
295 | 19 | } |
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 | 24.8M | { |
332 | 24.8M | out[0] = c; |
333 | 24.8M | out[1] = m; |
334 | 24.8M | out[2] = y; |
335 | 24.8M | out[3] = k; |
336 | 24.8M | } |
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 | 48.9M | { |
364 | 48.9M | *tdev = dev; |
365 | 48.9M | return &DeviceGray_procs; |
366 | 48.9M | } |
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 | 113M | { |
372 | 113M | *tdev = dev; |
373 | 113M | return &DeviceRGB_procs; |
374 | 113M | } |
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 | 24.8M | { |
380 | 24.8M | *tdev = dev; |
381 | 24.8M | return &DeviceCMYK_procs; |
382 | 24.8M | } |
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.36M | (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 | 774k | { |
427 | 774k | if (compare_color_names(pname, name_size, "Gray") || |
428 | 774k | compare_color_names(pname, name_size, "Grey")) |
429 | 108k | return 0; |
430 | 665k | else |
431 | 665k | return -1; /* Indicate that the component name is "unknown" */ |
432 | 774k | } |
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 | 19.4k | { |
439 | 19.4k | if (compare_color_names(pname, name_size, "Red")) |
440 | 48 | return 0; |
441 | 19.3k | if (compare_color_names(pname, name_size, "Green")) |
442 | 48 | return 1; |
443 | 19.3k | if (compare_color_names(pname, name_size, "Blue")) |
444 | 48 | return 2; |
445 | 19.2k | else |
446 | 19.2k | return -1; /* Indicate that the component name is "unknown" */ |
447 | 19.3k | } |
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 | 23.5k | { |
454 | 23.5k | if (compare_color_names(pname, name_size, "Cyan")) |
455 | 310 | return 0; |
456 | 23.2k | if (compare_color_names(pname, name_size, "Magenta")) |
457 | 1.77k | return 1; |
458 | 21.4k | if (compare_color_names(pname, name_size, "Yellow")) |
459 | 1.51k | return 2; |
460 | 19.9k | if (compare_color_names(pname, name_size, "Black")) |
461 | 19.9k | return 3; |
462 | 0 | else |
463 | 0 | return -1; /* Indicate that the component name is "unknown" */ |
464 | 19.9k | } |
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 | 13.9M | { |
545 | 13.9M | return (pgs->get_cmap_procs)(pgs, dev); |
546 | 13.9M | } |
547 | | |
548 | | const gx_color_map_procs * |
549 | | gx_default_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev) |
550 | 11.0M | { |
551 | 11.0M | return (gx_device_must_halftone(dev) ? &cmap_few : &cmap_many); |
552 | 11.0M | } |
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 | 9.13M | { |
558 | 9.13M | pgs->cmap_procs = gx_get_cmap_procs(pgs, dev); |
559 | 9.13M | } |
560 | | |
561 | | /* Remap the color in the graphics state. */ |
562 | | int |
563 | | gx_remap_color(gs_gstate * pgs) |
564 | 15.7M | { |
565 | 15.7M | const gs_color_space *pcs = gs_currentcolorspace_inline(pgs); |
566 | 15.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 | 15.7M | if (!gx_dc_is_pure(gs_currentdevicecolor_inline(pgs))) |
572 | 15.7M | code = (*pcs->type->remap_color) (gs_currentcolor_inline(pgs), |
573 | 15.7M | pcs, gs_currentdevicecolor_inline(pgs), |
574 | 15.7M | (gs_gstate *) pgs, pgs->device, |
575 | 15.7M | gs_color_select_texture); |
576 | 15.7M | return code; |
577 | 15.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 | 46.7M | { |
590 | 46.7M | return pcs; |
591 | 46.7M | } |
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 | 42.8M | { |
734 | 42.8M | frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
735 | 42.8M | const gs_color_space *pconcs; |
736 | 42.8M | int i = pcs->type->num_components(pcs); |
737 | 42.8M | int code = (*pcs->type->concretize_color)(pcc, pcs, conc, pgs, dev); |
738 | 42.8M | cmm_dev_profile_t *dev_profile; |
739 | | |
740 | 42.8M | if (code < 0) |
741 | 5.72k | return code; |
742 | 42.8M | pconcs = cs_concrete_space(pcs, pgs); |
743 | 42.8M | if (!pconcs) |
744 | 0 | return gs_note_error(gs_error_undefined); |
745 | 42.8M | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
746 | 42.8M | if (code < 0) |
747 | 0 | return code; |
748 | 42.8M | 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 | 42.8M | i = any_abs(i); |
752 | 85.7M | for (i--; i >= 0; i--) |
753 | 42.8M | pdc->ccolor.paint.values[i] = pcc->paint.values[i]; |
754 | 42.8M | pdc->ccolor_valid = true; |
755 | 42.8M | return code; |
756 | 42.8M | } |
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 | 48.5M | { |
776 | 48.5M | (*pgs->cmap_procs->map_gray)(pconc[0], pdc, pgs, dev, select); |
777 | 48.5M | return 0; |
778 | 48.5M | } |
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 | 487k | { |
784 | 487k | frac fgray = gx_unit_frac(pc->paint.values[0]); |
785 | 487k | 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 | 487k | if (pgs->icc_manager->default_gray != NULL) { |
793 | 162k | gs_color_space *pcs_notconst = (gs_color_space*) pcs; |
794 | 162k | pcs_notconst->cmm_icc_profile_data = pgs->icc_manager->default_gray; |
795 | 162k | gsicc_adjust_profile_rc(pgs->icc_manager->default_gray, 1, "gx_remap_DeviceGray"); |
796 | 162k | pcs_notconst->type = &gs_color_space_type_ICC; |
797 | 162k | code = |
798 | 162k | (*pcs_notconst->type->remap_color)(gs_currentcolor_inline(pgs), |
799 | 162k | pcs_notconst, |
800 | 162k | gs_currentdevicecolor_inline(pgs), |
801 | 162k | pgs, pgs->device, |
802 | 162k | gs_color_select_texture); |
803 | 162k | return code; |
804 | 162k | } |
805 | | |
806 | | /* Save original color space and color info into dev color */ |
807 | 324k | pdc->ccolor.paint.values[0] = pc->paint.values[0]; |
808 | 324k | pdc->ccolor_valid = true; |
809 | | |
810 | 324k | (*pgs->cmap_procs->map_gray)(fgray, pdc, pgs, dev, select); |
811 | 324k | return 0; |
812 | 487k | } |
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 | 376M | { |
830 | | |
831 | 376M | gx_remap_concrete_rgb(pconc[0], pconc[1], pconc[2], pdc, pgs, dev, select); |
832 | 376M | return 0; |
833 | 376M | } |
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 | 82.8M | { |
869 | | /****** IGNORE alpha ******/ |
870 | 82.8M | gx_remap_concrete_cmyk(pconc[0], pconc[1], pconc[2], pconc[3], pdc, |
871 | 82.8M | pgs, dev, select, pcs); |
872 | 82.8M | return 0; |
873 | 82.8M | } |
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 | 321M | { |
909 | 321M | gs_HT_objtype_t objtype; |
910 | | |
911 | | /* This function only works with 3 bits currently. Flag here in case we add object types */ |
912 | 321M | assert(HT_OBJTYPE_COUNT == 4); |
913 | | |
914 | 321M | objtype = tag_to_HT_objtype[pgs->device->graphics_type_tag & 7]; |
915 | 321M | if (pgs->dev_ht[objtype] == NULL) |
916 | 320M | objtype = HT_OBJTYPE_DEFAULT; |
917 | 321M | return pgs->dev_ht[objtype]; |
918 | 321M | } |
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 | 22.5M | { |
926 | 22.5M | uchar i, ncomps = dev->color_info.num_components; |
927 | 22.5M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
928 | 22.5M | const gx_device *cmdev; |
929 | 22.5M | const gx_cm_color_map_procs *cmprocs; |
930 | | |
931 | | /* map to the color model */ |
932 | 22.5M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
933 | 22.5M | cmprocs->map_gray(cmdev, gray, cm_comps); |
934 | | |
935 | | /* apply the transfer function(s); convert to color values */ |
936 | 22.5M | if (pgs->effective_transfer_non_identity_count == 0) { |
937 | | /* No transfer function to apply */ |
938 | 22.0M | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
939 | 43.9M | for (i = 0; i < ncomps; i++) |
940 | 21.9M | cm_comps[i] = gx_map_color_frac(pgs, |
941 | 22.0M | cm_comps[i], effective_transfer[i]); |
942 | 36.3k | else { |
943 | 36.3k | 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 | 36.3k | } else { |
949 | 72.7k | for (i = 0; i < ncomps; i++) |
950 | 36.3k | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
951 | 36.3k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
952 | 36.3k | } |
953 | 36.3k | } |
954 | 22.5M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
955 | 22.5M | &pgs->screen_phase[select]) == 1) |
956 | 19.3M | gx_color_load_select(pdc, pgs, dev, select); |
957 | 22.5M | } |
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.9M | { |
963 | 10.9M | uchar i, nc, ncomps = dev->color_info.num_components; |
964 | 10.9M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
965 | 10.9M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
966 | 10.9M | gx_color_index color; |
967 | 10.9M | const gx_device *cmdev; |
968 | 10.9M | const gx_cm_color_map_procs *cmprocs; |
969 | | |
970 | | /* map to the color model */ |
971 | 10.9M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
972 | 10.9M | cmprocs->map_gray(cmdev, gray, cm_comps); |
973 | | |
974 | 10.9M | nc = ncomps; |
975 | 10.9M | if (device_encodes_tags(dev)) |
976 | 0 | nc--; |
977 | | /* apply the transfer function(s); convert to color values */ |
978 | 10.9M | if (pgs->effective_transfer_non_identity_count == 0) { |
979 | 21.8M | for (i = 0; i < nc; i++) |
980 | 10.9M | cv[i] = frac2cv(cm_comps[i]); |
981 | 10.9M | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
982 | 9.59k | for (i = 0; i < nc; i++) { |
983 | 4.79k | cm_comps[i] = gx_map_color_frac(pgs, |
984 | 4.79k | cm_comps[i], effective_transfer[i]); |
985 | 4.79k | cv[i] = frac2cv(cm_comps[i]); |
986 | 4.79k | } |
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.9M | if (nc < ncomps) |
1005 | 0 | cv[nc] = cm_comps[nc]; |
1006 | | |
1007 | | /* encode as a color index */ |
1008 | 10.9M | color = dev_proc(dev, encode_color)(dev, cv); |
1009 | | |
1010 | | /* check if the encoding was successful; we presume failure is rare */ |
1011 | 10.9M | if (color != gx_no_color_index) { |
1012 | 10.9M | color_set_pure(pdc, color); |
1013 | 10.9M | return; |
1014 | 10.9M | } |
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 | 252M | { |
1026 | 252M | uchar i, nc, ncomps = dev->color_info.num_components; |
1027 | 252M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1028 | 252M | const gx_device *cmdev; |
1029 | 252M | const gx_cm_color_map_procs *cmprocs; |
1030 | | |
1031 | | /* map to the color model */ |
1032 | 252M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1033 | 252M | cmprocs->map_rgb(cmdev, pgs, r, g, b, cm_comps); |
1034 | | |
1035 | 252M | nc = ncomps; |
1036 | 252M | if (device_encodes_tags(dev)) |
1037 | 0 | nc--; |
1038 | | /* apply the transfer function(s); convert to color values */ |
1039 | 252M | if (pgs->effective_transfer_non_identity_count != 0) { |
1040 | 252M | int n = 0; |
1041 | 252M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1042 | 252M | n = nc < 3 ? nc : 3; |
1043 | | |
1044 | 1.00G | for (i = 0; i < n; i++) |
1045 | 757M | cm_comps[i] = gx_map_color_frac(pgs, |
1046 | 252M | cm_comps[i], effective_transfer[i]); |
1047 | 252M | for (; i < n; i++) |
1048 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1049 | 252M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1050 | 252M | } |
1051 | | |
1052 | 252M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1053 | 252M | &pgs->screen_phase[select]) == 1) |
1054 | 142M | gx_color_load_select(pdc, pgs, dev, select); |
1055 | 252M | } |
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 | 114M | { |
1061 | 114M | uchar i, nc, ncomps = dev->color_info.num_components; |
1062 | 114M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1063 | 114M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1064 | 114M | gx_color_index color; |
1065 | 114M | const gx_device *cmdev; |
1066 | 114M | const gx_cm_color_map_procs *cmprocs; |
1067 | | |
1068 | | /* map to the color model */ |
1069 | 114M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1070 | 114M | cmprocs->map_rgb(cmdev, pgs, r, g, b, cm_comps); |
1071 | | |
1072 | 114M | nc = ncomps; |
1073 | 114M | if (device_encodes_tags(dev)) |
1074 | 0 | nc--; |
1075 | | /* apply the transfer function(s); convert to color values */ |
1076 | 114M | if (pgs->effective_transfer_non_identity_count != 0) { |
1077 | 2.01M | int n = 0; |
1078 | 2.01M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1079 | 2.01M | n = nc < 3 ? nc : 3; |
1080 | 8.04M | for (i = 0; i < n; i++) |
1081 | 6.03M | cm_comps[i] = gx_map_color_frac(pgs, cm_comps[i], |
1082 | 2.01M | effective_transfer[i]); |
1083 | 2.01M | for (; i < nc; i++) |
1084 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1085 | 2.01M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1086 | 2.01M | } |
1087 | | |
1088 | 114M | 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]; |
1093 | 0 | pdc->type = gx_dc_type_devn; |
1094 | 114M | } else { |
1095 | 456M | for (i = 0; i < nc; i++) |
1096 | 342M | cv[i] = frac2cv(cm_comps[i]); |
1097 | 114M | if (i < ncomps) |
1098 | 0 | cv[i] = cm_comps[i]; |
1099 | | /* encode as a color index */ |
1100 | 114M | color = dev_proc(dev, encode_color)(dev, cv); |
1101 | | |
1102 | | /* check if the encoding was successful; we presume failure is rare */ |
1103 | 114M | if (color != gx_no_color_index) { |
1104 | 114M | color_set_pure(pdc, color); |
1105 | 114M | return; |
1106 | 114M | } |
1107 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1108 | 0 | &pgs->screen_phase[select]) == 1) |
1109 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1110 | 0 | } |
1111 | 114M | } |
1112 | | |
1113 | | /* ------ Render CMYK color. ------ */ |
1114 | | |
1115 | | static void |
1116 | | cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc, |
1117 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select, |
1118 | | const gs_color_space *source_pcs) |
1119 | 50.7M | { |
1120 | 50.7M | uchar i, nc, ncomps = dev->color_info.num_components; |
1121 | 50.7M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1122 | 50.7M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1123 | 50.7M | gx_color_index color; |
1124 | 50.7M | uint black_index; |
1125 | 50.7M | cmm_dev_profile_t *dev_profile; |
1126 | 50.7M | gsicc_colorbuffer_t src_space = gsUNDEFINED; |
1127 | 50.7M | bool gray_to_k; |
1128 | 50.7M | const gx_device *cmdev; |
1129 | 50.7M | const gx_cm_color_map_procs *cmprocs; |
1130 | | |
1131 | | /* map to the color model */ |
1132 | 50.7M | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1133 | 50.7M | cmprocs->map_cmyk(cmdev, c, m, y, k, cm_comps); |
1134 | | |
1135 | | /* apply the transfer function(s); convert to color values */ |
1136 | 50.7M | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
1137 | 25 | if (pgs->effective_transfer_non_identity_count != 0) |
1138 | 26 | for (i = 0; i < ncomps; i++) |
1139 | 13 | cm_comps[i] = gx_map_color_frac(pgs, |
1140 | 25 | cm_comps[i], effective_transfer[i]); |
1141 | 50.7M | } else { |
1142 | | /* Check if source space is gray. In this case we are to use only the |
1143 | | transfer function on the K channel. Do this only if gray to K is |
1144 | | also set */ |
1145 | 50.7M | dev_proc(dev, get_profile)(dev, &dev_profile); |
1146 | 50.7M | gray_to_k = dev_profile->devicegraytok; |
1147 | 50.7M | if (source_pcs != NULL && source_pcs->cmm_icc_profile_data != NULL) { |
1148 | 50.7M | src_space = source_pcs->cmm_icc_profile_data->data_cs; |
1149 | 50.7M | } else if (source_pcs != NULL && source_pcs->icc_equivalent != NULL) { |
1150 | 0 | src_space = source_pcs->icc_equivalent->cmm_icc_profile_data->data_cs; |
1151 | 0 | } |
1152 | 50.7M | if (src_space == gsGRAY && gray_to_k) { |
1153 | | /* Find the black channel location */ |
1154 | 916k | black_index = dev_proc(dev, get_color_comp_index)(dev, "Black", |
1155 | 916k | strlen("Black"), SEPARATION_NAME); |
1156 | 916k | cm_comps[black_index] = frac_1 - gx_map_color_frac(pgs, |
1157 | 916k | (frac)(frac_1 - cm_comps[black_index]), |
1158 | 916k | effective_transfer[black_index]); |
1159 | 49.8M | } else if (pgs->effective_transfer_non_identity_count != 0) |
1160 | 214M | for (i = 0; i < ncomps; i++) |
1161 | 171M | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1162 | 50.7M | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1163 | 50.7M | } |
1164 | | /* We make a test for direct vs. halftoned, rather than */ |
1165 | | /* duplicating most of the code of this procedure. */ |
1166 | 50.7M | if (gx_device_must_halftone(dev)) { |
1167 | 43.4M | if (gx_render_device_DeviceN(cm_comps, pdc, dev, |
1168 | 43.4M | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
1169 | 19.3M | gx_color_load_select(pdc, pgs, dev, select); |
1170 | 43.4M | return; |
1171 | 43.4M | } |
1172 | | /* if output device supports devn, we need to make sure we send it the |
1173 | | proper color type */ |
1174 | 7.29M | nc = ncomps; |
1175 | 7.29M | if (device_encodes_tags(dev)) |
1176 | 0 | nc--; |
1177 | 7.29M | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1178 | 38.6M | for (i = 0; i < nc; i++) |
1179 | 31.3M | pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); |
1180 | 7.29M | if (i < ncomps) |
1181 | 0 | pdc->colors.devn.values[i] = cm_comps[i]; |
1182 | 7.29M | pdc->type = gx_dc_type_devn; |
1183 | 7.29M | } else { |
1184 | 0 | for (i = 0; i < nc; i++) |
1185 | 0 | cv[i] = frac2cv(cm_comps[i]); |
1186 | 0 | if (i < ncomps) |
1187 | 0 | cv[i] = cm_comps[i]; |
1188 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1189 | 0 | if (color != gx_no_color_index) |
1190 | 0 | color_set_pure(pdc, color); |
1191 | 0 | else { |
1192 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, |
1193 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
1194 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1195 | 0 | } |
1196 | 0 | } |
1197 | 7.29M | return; |
1198 | 50.7M | } |
1199 | | |
1200 | | /* ------ Render Separation All color. ------ */ |
1201 | | |
1202 | | /* |
1203 | | * This routine maps DeviceN components into the order of the device's |
1204 | | * colorants. |
1205 | | * |
1206 | | * Parameters: |
1207 | | * pcc - Pointer to DeviceN components. |
1208 | | * pcolor_component_map - Map from DeviceN to the Devices colorants. |
1209 | | * A negative value indicates component is not to be mapped. |
1210 | | * plist - Pointer to list for mapped components |
1211 | | * num_comps - num_comps that we need to zero (may be more than |
1212 | | * is set if we are mapping values for an NCLR ICC profile |
1213 | | * via an alternate tint transform for a sep value) -- |
1214 | | * i.e. cmyk+og values and we may have some spots that |
1215 | | * are supported but may have reached the limit and |
1216 | | * using the alt tint values. Need to make sure to zero all. |
1217 | | * |
1218 | | * Returns: |
1219 | | * Mapped components in plist. |
1220 | | */ |
1221 | | static inline void |
1222 | | map_components_to_colorants(const frac * pcc, |
1223 | | const gs_devicen_color_map * pcolor_component_map, frac * plist, |
1224 | | int num_colorants) |
1225 | 372k | { |
1226 | 372k | int i; |
1227 | 372k | int pos; |
1228 | | |
1229 | | /* Clear all output colorants first */ |
1230 | 2.93M | for (i = num_colorants - 1; i >= 0; i--) { |
1231 | 2.56M | plist[i] = frac_0; |
1232 | 2.56M | } |
1233 | | |
1234 | | /* Map color components into output list */ |
1235 | 1.49M | for (i = pcolor_component_map->num_components - 1; i >= 0; i--) { |
1236 | 1.12M | pos = pcolor_component_map->color_map[i]; |
1237 | 1.12M | if (pos >= 0) |
1238 | 1.12M | plist[pos] = pcc[i]; |
1239 | 1.12M | } |
1240 | 372k | } |
1241 | | |
1242 | | static bool |
1243 | | named_color_supported(const gs_gstate * pgs) |
1244 | 372k | { |
1245 | 372k | gs_color_space *pcs = gs_currentcolorspace_inline(pgs); |
1246 | 372k | gs_color_space_index type = gs_color_space_get_index(pcs); |
1247 | | |
1248 | 372k | if (pgs->icc_manager->device_named == NULL) |
1249 | 372k | return false; |
1250 | | |
1251 | 0 | if (type == gs_color_space_index_Separation && pcs->params.separation.named_color_supported) |
1252 | 0 | return true; |
1253 | | |
1254 | 0 | if (type == gs_color_space_index_DeviceN && pcs->params.device_n.named_color_supported) |
1255 | 0 | return true; |
1256 | | |
1257 | 0 | return false; |
1258 | 0 | } |
1259 | | |
1260 | | /* Routines for handling CM of CMYK components of a DeviceN color space */ |
1261 | | static bool |
1262 | | devicen_has_cmyk(gx_device * dev, cmm_profile_t *des_profile) |
1263 | 372k | { |
1264 | 372k | gs_devn_params *devn_params; |
1265 | | |
1266 | 372k | devn_params = dev_proc(dev, ret_devn_params)(dev); |
1267 | 372k | if (devn_params == NULL) { |
1268 | 0 | if (des_profile != NULL && des_profile->data_cs == gsCMYK) |
1269 | 0 | return true; |
1270 | 0 | else |
1271 | 0 | return false; |
1272 | 0 | } |
1273 | 372k | return(devn_params->num_std_colorant_names == 4); |
1274 | 372k | } |
1275 | | |
1276 | | static void |
1277 | | devicen_sep_icc_cmyk(frac cm_comps[], const gs_gstate * pgs, |
1278 | | const gs_color_space * pcs, gx_device *dev) |
1279 | 372k | { |
1280 | 372k | gsicc_link_t *icc_link; |
1281 | 372k | gsicc_rendering_param_t rendering_params; |
1282 | 372k | unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1283 | 372k | unsigned short psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1284 | 372k | int k, code; |
1285 | 372k | unsigned short *psrc_temp; |
1286 | 372k | gsicc_rendering_param_t render_cond; |
1287 | 372k | cmm_dev_profile_t *dev_profile = NULL; |
1288 | 372k | cmm_profile_t *des_profile = NULL; |
1289 | 372k | cmm_profile_t *src_profile = pgs->icc_manager->default_cmyk; |
1290 | | |
1291 | 372k | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
1292 | | |
1293 | | /* If we can't transform them, we will just leave them as is. */ |
1294 | 372k | if (code < 0) |
1295 | 0 | return; |
1296 | | |
1297 | 372k | gsicc_extract_profile(dev->graphics_type_tag, |
1298 | 372k | dev_profile, &des_profile, &render_cond); |
1299 | | /* Define the rendering intents. */ |
1300 | 372k | rendering_params.black_point_comp = pgs->blackptcomp; |
1301 | 372k | rendering_params.graphics_type_tag = dev->graphics_type_tag; |
1302 | 372k | rendering_params.override_icc = false; |
1303 | 372k | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
1304 | 372k | rendering_params.rendering_intent = pgs->renderingintent; |
1305 | 372k | rendering_params.cmm = gsCMM_DEFAULT; |
1306 | | /* Sigh, frac to full 16 bit. Need to clean this up */ |
1307 | 1.86M | for (k = 0; k < 4; k++) { |
1308 | 1.48M | psrc[k] = frac2cv(cm_comps[k]); |
1309 | 1.48M | } |
1310 | | |
1311 | | /* Determine what src profile to use. First choice is the attributes |
1312 | | process color space if it is the correct type. Second choice is |
1313 | | the alternate tint transform color space if it is the correct type. |
1314 | | Third type is default_cmyk. If we have an issue with bad profiles then |
1315 | | the color values will just remain as they were from the source */ |
1316 | 372k | if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) { |
1317 | 364k | if (pcs->params.device_n.devn_process_space != NULL && |
1318 | 364k | pcs->params.device_n.devn_process_space->cmm_icc_profile_data != NULL && |
1319 | 364k | pcs->params.device_n.devn_process_space->cmm_icc_profile_data->data_cs == gsCMYK) { |
1320 | 844 | src_profile = pcs->params.device_n.devn_process_space->cmm_icc_profile_data; |
1321 | 364k | } else if (pcs->base_space != NULL && |
1322 | 364k | pcs->base_space->cmm_icc_profile_data != NULL && |
1323 | 364k | pcs->base_space->cmm_icc_profile_data->data_cs == gsCMYK && |
1324 | 364k | USE_ALT_MAP) { |
1325 | 0 | src_profile = pcs->base_space->cmm_icc_profile_data; |
1326 | 0 | } |
1327 | 364k | } else if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) { |
1328 | 7.30k | if (pcs->base_space != NULL && |
1329 | 7.30k | pcs->base_space->cmm_icc_profile_data != NULL && |
1330 | 7.30k | pcs->base_space->cmm_icc_profile_data->data_cs == gsCMYK && |
1331 | 7.30k | USE_ALT_MAP) { |
1332 | 0 | src_profile = pcs->base_space->cmm_icc_profile_data; |
1333 | 0 | } |
1334 | 7.30k | } |
1335 | | |
1336 | 372k | icc_link = gsicc_get_link_profile(pgs, dev, src_profile, des_profile, |
1337 | 372k | &rendering_params, pgs->memory, dev_profile->devicegraytok); |
1338 | | |
1339 | 372k | if (icc_link == NULL && src_profile != pgs->icc_manager->default_cmyk) { |
1340 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, |
1341 | 0 | pgs->icc_manager->default_cmyk, des_profile, |
1342 | 0 | &rendering_params, pgs->memory, dev_profile->devicegraytok); |
1343 | 0 | } |
1344 | | |
1345 | | /* If we can't transform them, we will just leave them as is. */ |
1346 | 372k | if (icc_link == NULL) |
1347 | 0 | return; |
1348 | | |
1349 | | /* Transform the color */ |
1350 | 372k | if (icc_link->is_identity) { |
1351 | 372k | psrc_temp = &(psrc[0]); |
1352 | 372k | } else { |
1353 | | /* Transform the color */ |
1354 | 0 | psrc_temp = &(psrc_cm[0]); |
1355 | 0 | (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2); |
1356 | 0 | } |
1357 | | /* This needs to be optimized */ |
1358 | 1.86M | for (k = 0; k < 4; k++) { |
1359 | 1.48M | cm_comps[k] = float2frac(((float)psrc_temp[k]) / 65535.0); |
1360 | 1.48M | } |
1361 | | /* Release the link */ |
1362 | 372k | gsicc_release_link(icc_link); |
1363 | 372k | } |
1364 | | |
1365 | | static void |
1366 | | cmap_separation_halftoned(frac all, gx_device_color * pdc, |
1367 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select, |
1368 | | const gs_color_space *pcs) |
1369 | 4.05k | { |
1370 | 4.05k | uint i, ncomps = dev->color_info.num_components; |
1371 | 4.05k | bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1372 | 4.05k | frac comp_value = all; |
1373 | 4.05k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1374 | 4.05k | gsicc_rendering_param_t render_cond; |
1375 | 4.05k | cmm_dev_profile_t *dev_profile = NULL; |
1376 | 4.05k | cmm_profile_t *des_profile = NULL; |
1377 | | |
1378 | 4.05k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1379 | 4.05k | gsicc_extract_profile(dev->graphics_type_tag, |
1380 | 4.05k | dev_profile, &des_profile, &render_cond); |
1381 | | |
1382 | 4.05k | if (pgs->color_component_map.sep_type == SEP_ALL) { |
1383 | | /* |
1384 | | * Invert the photometric interpretation for additive |
1385 | | * color spaces because separations are always subtractive. |
1386 | | */ |
1387 | 0 | if (additive) |
1388 | 0 | comp_value = frac_1 - comp_value; |
1389 | | |
1390 | | /* Use the "all" value for all components */ |
1391 | 0 | for (i = 0; i < pgs->color_component_map.num_colorants; i++) |
1392 | 0 | cm_comps[i] = comp_value; |
1393 | 4.05k | } else { |
1394 | 4.05k | if (pgs->color_component_map.sep_type == SEP_NONE) { |
1395 | 0 | color_set_null(pdc); |
1396 | 0 | return; |
1397 | 0 | } |
1398 | | |
1399 | | /* map to the color model */ |
1400 | 4.05k | map_components_to_colorants(&all, &(pgs->color_component_map), cm_comps, |
1401 | 4.05k | pgs->color_component_map.num_colorants); |
1402 | 4.05k | } |
1403 | | |
1404 | 4.05k | if (devicen_has_cmyk(dev, des_profile) && |
1405 | 4.05k | des_profile->data_cs == gsCMYK && |
1406 | 4.05k | !named_color_supported(pgs)) { |
1407 | 4.05k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1408 | 4.05k | } |
1409 | | |
1410 | | /* apply the transfer function(s); convert to color values */ |
1411 | 4.05k | if (pgs->effective_transfer_non_identity_count != 0) { |
1412 | 2.94k | int n = 0; |
1413 | 2.94k | if (additive) |
1414 | 0 | n = ncomps < 3 ? ncomps : 3; |
1415 | 2.94k | for (i = 0; i < n; i++) |
1416 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1417 | 2.94k | cm_comps[i], effective_transfer[i]); |
1418 | 15.7k | for (; i < ncomps; i++) |
1419 | 12.7k | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1420 | 2.94k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1421 | 2.94k | } |
1422 | | |
1423 | 4.05k | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1424 | 4.05k | &pgs->screen_phase[select]) == 1) |
1425 | 1.69k | gx_color_load_select(pdc, pgs, dev, select); |
1426 | 4.05k | } |
1427 | | |
1428 | | static void |
1429 | | cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs, |
1430 | | gx_device * dev, gs_color_select_t select, const gs_color_space *pcs) |
1431 | 3.25k | { |
1432 | 3.25k | uint i, nc, ncomps = dev->color_info.num_components; |
1433 | 3.25k | bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1434 | 3.25k | frac comp_value = all; |
1435 | 3.25k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1436 | 3.25k | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1437 | 3.25k | gx_color_index color; |
1438 | 3.25k | bool use_rgb2dev_icc = false; |
1439 | 3.25k | gsicc_rendering_param_t render_cond; |
1440 | 3.25k | cmm_dev_profile_t *dev_profile = NULL; |
1441 | 3.25k | cmm_profile_t *des_profile = NULL; |
1442 | 3.25k | int num_additives = additive ? dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0) : 0; |
1443 | | |
1444 | 3.25k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1445 | 3.25k | gsicc_extract_profile(dev->graphics_type_tag, |
1446 | 3.25k | dev_profile, &des_profile, &render_cond); |
1447 | 3.25k | if (pgs->color_component_map.sep_type == SEP_ALL) { |
1448 | | /* |
1449 | | * Invert the photometric interpretation for additive |
1450 | | * color spaces because separations are always subtractive. |
1451 | | */ |
1452 | 0 | if (additive && num_additives <= 0) { |
1453 | 0 | comp_value = frac_1 - comp_value; |
1454 | 0 | } |
1455 | | |
1456 | | /* Use the "all" value for all components */ |
1457 | 0 | for (i = 0; i < pgs->color_component_map.num_colorants; i++) |
1458 | 0 | cm_comps[i] = comp_value; |
1459 | | /* If our device space is CIELAB then we really want to treat this |
1460 | | as RGB during the fill up here of the separation value and then |
1461 | | go ahead and convert from RGB to CIELAB. The PDF spec is not clear |
1462 | | on how addivite devices should behave with the ALL option but it |
1463 | | is clear from testing the AR 10 does simply do the RGB = 1 - INK |
1464 | | type of mapping */ |
1465 | 0 | if (des_profile->data_cs == gsCIELAB || des_profile->islab) { |
1466 | 0 | use_rgb2dev_icc = true; |
1467 | 0 | } |
1468 | 3.25k | } else { |
1469 | 3.25k | if (pgs->color_component_map.sep_type == SEP_NONE) { |
1470 | 0 | color_set_null(pdc); |
1471 | 0 | return; |
1472 | 0 | } |
1473 | | |
1474 | | /* map to the color model */ |
1475 | 3.25k | map_components_to_colorants(&comp_value, &(pgs->color_component_map), cm_comps, |
1476 | 3.25k | pgs->color_component_map.num_colorants); |
1477 | 3.25k | } |
1478 | | |
1479 | | /* Check if we have the standard colorants. If yes, then we will apply |
1480 | | ICC color management to those colorants. */ |
1481 | 3.25k | if (devicen_has_cmyk(dev, des_profile) && des_profile->data_cs == gsCMYK && |
1482 | 3.25k | !named_color_supported(pgs) && pgs->color_component_map.sep_type != SEP_ALL) { |
1483 | | /* We need to do a CMYK to CMYK conversion here. This will always |
1484 | | use the default CMYK profile and the device's output profile. |
1485 | | We probably need to add some checking here |
1486 | | and possibly permute the colorants, much as is done on the input |
1487 | | side for the case when we add DeviceN icc source profiles for use |
1488 | | in PDF and PS data. Also, don't do this if we are doing mapping |
1489 | | through the named color mapping. */ |
1490 | 3.25k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1491 | 3.25k | } |
1492 | | |
1493 | | /* apply the transfer function(s); convert to color values */ |
1494 | 3.25k | nc = ncomps; |
1495 | 3.25k | if (device_encodes_tags(dev)) |
1496 | 0 | nc--; |
1497 | 3.25k | if (pgs->effective_transfer_non_identity_count != 0) { |
1498 | 0 | int n = 0; |
1499 | 0 | if (additive) |
1500 | 0 | n = nc < 3 ? nc : 3; |
1501 | 0 | for (i = 0; i < n; i++) |
1502 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1503 | 0 | cm_comps[i], effective_transfer[i]); |
1504 | 0 | for (; i < nc; i++) |
1505 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1506 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1507 | 0 | } |
1508 | 18.3k | for (i = 0; i < nc; i++) |
1509 | 15.0k | cv[i] = frac2cv(cm_comps[i]); |
1510 | | /* For additive devices, we should invert the process colors |
1511 | | * here! But how do we know how many process colors we have? For |
1512 | | * now we'll have to ask the device using a dso. */ |
1513 | 3.25k | if (additive) { |
1514 | 0 | int j; |
1515 | 0 | for (j = 0; j < num_additives; j++) |
1516 | 0 | cv[j] = 65535 - cv[j]; |
1517 | 0 | } |
1518 | | /* Copy tags untransformed. */ |
1519 | 3.25k | if (nc < ncomps) |
1520 | 0 | cv[nc] = cm_comps[nc]; |
1521 | | |
1522 | 3.25k | if (use_rgb2dev_icc && pgs->icc_manager->default_rgb != NULL) { |
1523 | | /* After the transfer function go ahead and do the mapping from RGB to |
1524 | | the device profile. */ |
1525 | 0 | gsicc_link_t *icc_link; |
1526 | 0 | gsicc_rendering_param_t rendering_params; |
1527 | 0 | unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
1528 | |
|
1529 | 0 | rendering_params.black_point_comp = pgs->blackptcomp; |
1530 | 0 | rendering_params.graphics_type_tag = dev->graphics_type_tag; |
1531 | 0 | rendering_params.override_icc = false; |
1532 | 0 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
1533 | 0 | rendering_params.rendering_intent = pgs->renderingintent; |
1534 | 0 | rendering_params.cmm = gsCMM_DEFAULT; |
1535 | |
|
1536 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, pgs->icc_manager->default_rgb, |
1537 | 0 | des_profile, &rendering_params, |
1538 | 0 | pgs->memory, dev_profile->devicegraytok); |
1539 | | /* Transform the color */ |
1540 | 0 | for (i = 0; i < ncomps; i++) { |
1541 | 0 | psrc[i] = cv[i]; |
1542 | 0 | } |
1543 | 0 | (icc_link->procs.map_color)(dev, icc_link, &(psrc[0]), &(psrc_cm[0]), 2); |
1544 | 0 | gsicc_release_link(icc_link); |
1545 | 0 | for (i = 0; i < ncomps; i++) { |
1546 | 0 | cv[i] = psrc_cm[i]; |
1547 | 0 | } |
1548 | 0 | } |
1549 | | /* if output device supports devn, we need to make sure we send it the |
1550 | | proper color type */ |
1551 | 3.25k | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1552 | 18.3k | for (i = 0; i < ncomps; i++) |
1553 | 15.0k | pdc->colors.devn.values[i] = cv[i]; |
1554 | 3.25k | pdc->type = gx_dc_type_devn; |
1555 | | |
1556 | | /* Let device set the tags if present */ |
1557 | 3.25k | if (device_encodes_tags(dev)) { |
1558 | 0 | const gx_device *cmdev; |
1559 | 0 | const gx_cm_color_map_procs *cmprocs; |
1560 | |
|
1561 | 0 | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1562 | 0 | cmprocs->map_cmyk(cmdev, 0, 0, 0, 0, cm_comps); |
1563 | 0 | pdc->colors.devn.values[ncomps - 1] = cm_comps[ncomps - 1]; |
1564 | 0 | } |
1565 | 3.25k | return; |
1566 | 3.25k | } |
1567 | | |
1568 | | /* encode as a color index */ |
1569 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1570 | | |
1571 | | /* check if the encoding was successful; we presume failure is rare */ |
1572 | 0 | if (color != gx_no_color_index) { |
1573 | 0 | color_set_pure(pdc, color); |
1574 | 0 | return; |
1575 | 0 | } |
1576 | | |
1577 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1578 | 0 | &pgs->screen_phase[select]) == 1) |
1579 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1580 | 0 | } |
1581 | | |
1582 | | /* ------ DeviceN color mapping */ |
1583 | | |
1584 | | /* |
1585 | | * This routine is called to map a DeviceN colorspace to a DeviceN |
1586 | | * output device which requires halftoning. T |
1587 | | */ |
1588 | | static void |
1589 | | cmap_devicen_halftoned(const frac * pcc, |
1590 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
1591 | | gs_color_select_t select, const gs_color_space *pcs) |
1592 | 364k | { |
1593 | 364k | uchar i, ncomps = dev->color_info.num_components; |
1594 | 364k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1595 | 364k | gsicc_rendering_param_t render_cond; |
1596 | 364k | cmm_dev_profile_t *dev_profile = NULL; |
1597 | 364k | cmm_profile_t *des_profile = NULL; |
1598 | | |
1599 | 364k | if (pcs->params.device_n.all_none == true) { |
1600 | 0 | color_set_null(pdc); |
1601 | 0 | return; |
1602 | 0 | } |
1603 | | |
1604 | 364k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1605 | 364k | gsicc_extract_profile(dev->graphics_type_tag, |
1606 | 364k | dev_profile, &des_profile, &render_cond); |
1607 | | /* map to the color model */ |
1608 | 364k | map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps, |
1609 | 364k | pgs->color_component_map.num_colorants); |
1610 | | /* See comments in cmap_devicen_direct for details on below operations */ |
1611 | 364k | if (devicen_has_cmyk(dev, des_profile) && |
1612 | 364k | des_profile->data_cs == gsCMYK && |
1613 | 364k | !named_color_supported(pgs)) { |
1614 | 364k | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1615 | 364k | } |
1616 | | /* apply the transfer function(s); convert to color values */ |
1617 | 364k | if (pgs->effective_transfer_non_identity_count != 0) { |
1618 | 364k | int n = 0; |
1619 | 364k | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1620 | 0 | n = ncomps < 3 ? ncomps : 3; |
1621 | 364k | for (i = 0; i < n; i++) |
1622 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1623 | 364k | cm_comps[i], effective_transfer[i]); |
1624 | 2.89M | for (; i < ncomps; i++) |
1625 | 2.52M | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1626 | 364k | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1627 | 364k | } |
1628 | | |
1629 | | /* We need to finish halftoning */ |
1630 | 364k | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1631 | 364k | &pgs->screen_phase[select]) == 1) |
1632 | 354k | gx_color_load_select(pdc, pgs, dev, select); |
1633 | 364k | } |
1634 | | |
1635 | | static void |
1636 | | encode_tags(const gx_device *dev, gx_device_color *pdc) |
1637 | 0 | { |
1638 | 0 | const gx_device *cmdev; |
1639 | 0 | const gx_cm_color_map_procs *cmprocs; |
1640 | 0 | uchar ncomps = dev->color_info.num_components; |
1641 | 0 | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1642 | |
|
1643 | 0 | cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
1644 | 0 | cmprocs->map_cmyk(cmdev, 0, 0, 0, 0, cm_comps); |
1645 | 0 | pdc->colors.devn.values[ncomps - 1] = cm_comps[ncomps - 1]; |
1646 | 0 | } |
1647 | | |
1648 | | /* |
1649 | | * This routine is called to map a DeviceN colorspace to a DeviceN |
1650 | | * output device which does not require halftoning. |
1651 | | */ |
1652 | | static void |
1653 | | cmap_devicen_direct(const frac * pcc, |
1654 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
1655 | | gs_color_select_t select, const gs_color_space *pcs) |
1656 | 401 | { |
1657 | 401 | uchar i, nc, ncomps = dev->color_info.num_components; |
1658 | 401 | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1659 | 401 | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1660 | 401 | gx_color_index color; |
1661 | 401 | gsicc_rendering_param_t render_cond; |
1662 | 401 | cmm_dev_profile_t *dev_profile = NULL; |
1663 | 401 | cmm_profile_t *des_profile = NULL; |
1664 | 401 | int additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
1665 | | |
1666 | 401 | if (pcs->params.device_n.all_none == true) { |
1667 | 0 | color_set_null(pdc); |
1668 | 0 | return; |
1669 | 0 | } |
1670 | | |
1671 | 401 | dev_proc(dev, get_profile)(dev, &dev_profile); |
1672 | 401 | gsicc_extract_profile(dev->graphics_type_tag, |
1673 | 401 | dev_profile, &des_profile, &render_cond); |
1674 | | /* See the comment below */ |
1675 | | /* map to the color model */ |
1676 | 401 | if (dev_profile->spotnames != NULL && dev_profile->spotnames->equiv_cmyk_set) { |
1677 | 0 | map_components_to_colorants(pcc, dev_profile->spotnames->color_map, |
1678 | 0 | cm_comps, ncomps); |
1679 | 401 | } else { |
1680 | 401 | map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps, |
1681 | 401 | pgs->color_component_map.num_colorants); |
1682 | 401 | } |
1683 | | /* Check if we have the standard colorants. If yes, then we will apply |
1684 | | ICC color management to those colorants. To understand why, consider |
1685 | | the example where I have a Device with CMYK + O and I have a |
1686 | | DeviceN color in the document that is specified for any set of |
1687 | | these colorants, and suppose that I let them pass through |
1688 | | witout any color management. This is probably not the |
1689 | | desired effect since I could have a DeviceN color fill that had 10% C, |
1690 | | 20% M 0% Y 0% K and 0% O. I would like this to look the same |
1691 | | as a CMYK color that will be color managed and specified with 10% C, |
1692 | | 20% M 0% Y 0% K. Hence the CMYK values should go through the same |
1693 | | color management as a stand alone CMYK value. */ |
1694 | 401 | if (devicen_has_cmyk(dev, des_profile) && des_profile->data_cs == gsCMYK && |
1695 | 401 | !named_color_supported(pgs)) { |
1696 | | /* We need to do a CMYK to CMYK conversion here. This will always |
1697 | | use the default CMYK profile and the device's output profile. |
1698 | | We probably need to add some checking here |
1699 | | and possibly permute the colorants, much as is done on the input |
1700 | | side for the case when we add DeviceN icc source profiles for use |
1701 | | in PDF and PS data. Also, don't do this if we are doing mapping |
1702 | | through the named color mapping. */ |
1703 | 401 | devicen_sep_icc_cmyk(cm_comps, pgs, pcs, dev); |
1704 | 401 | } |
1705 | 401 | nc = ncomps; |
1706 | 401 | if (device_encodes_tags(dev)) |
1707 | 0 | nc--; |
1708 | | /* apply the transfer function(s); convert to color values. |
1709 | | assign directly if output device supports devn */ |
1710 | 401 | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) { |
1711 | 401 | if (pgs->effective_transfer_non_identity_count == 0) |
1712 | 2.56k | for (i = 0; i < nc; i++) |
1713 | 2.16k | pdc->colors.devn.values[i] = frac2cv(cm_comps[i]); |
1714 | 0 | else { |
1715 | 0 | int n = 0; |
1716 | 0 | if (additive) |
1717 | 0 | n = nc < 3 ? nc : 3; |
1718 | 0 | for (i = 0; i < n; i++) |
1719 | 0 | pdc->colors.devn.values[i] = frac2cv(gx_map_color_frac(pgs, |
1720 | 0 | cm_comps[i], effective_transfer[i])); |
1721 | 0 | for (; i < nc; i++) |
1722 | 0 | pdc->colors.devn.values[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
1723 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); |
1724 | 0 | } |
1725 | 401 | if (i < ncomps) |
1726 | 0 | pdc->colors.devn.values[i] = cm_comps[i]; |
1727 | 401 | pdc->type = gx_dc_type_devn; |
1728 | | /* For additive devices, we should invert the process colors |
1729 | | * here! But how do we know how many process colors we have? |
1730 | | * Ask the device using a dso. */ |
1731 | 401 | if (additive) { |
1732 | 0 | int j, n = dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0); |
1733 | 0 | for (j = 0; j < n; j++) |
1734 | 0 | pdc->colors.devn.values[j] = 65535 - pdc->colors.devn.values[j]; |
1735 | 0 | } |
1736 | | |
1737 | | /* Let device set the tags if present */ |
1738 | 401 | if (device_encodes_tags(dev)) |
1739 | 0 | encode_tags(dev, pdc); |
1740 | | |
1741 | 401 | return; |
1742 | 401 | } |
1743 | | |
1744 | 0 | if (pgs->effective_transfer_non_identity_count != 0) { |
1745 | 0 | int n = 0; |
1746 | 0 | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
1747 | 0 | n = nc < 3 ? nc : 3; |
1748 | 0 | for (i = 0; i < n; i++) |
1749 | 0 | cm_comps[i] = gx_map_color_frac(pgs, |
1750 | 0 | cm_comps[i], effective_transfer[i]); |
1751 | 0 | for (; i < nc; i++) |
1752 | 0 | cm_comps[i] = frac_1 - gx_map_color_frac(pgs, |
1753 | 0 | (frac)(frac_1 - cm_comps[i]), effective_transfer[i]); |
1754 | 0 | } |
1755 | 0 | if (nc < ncomps) |
1756 | 0 | encode_tags(dev, pdc); |
1757 | | /* For additive devices, we should invert the process colors |
1758 | | * here! But how do we know how many process colors we have? |
1759 | | * Ask the device using a dso. */ |
1760 | 0 | if (additive) { |
1761 | 0 | int j, n = dev_proc(dev, dev_spec_op)(dev, gxdso_is_sep_supporting_additive_device, NULL, 0); |
1762 | 0 | for (j = 0; j < n; j++) |
1763 | 0 | cm_comps[j] = frac_1 - cm_comps[j]; |
1764 | 0 | } |
1765 | 0 | for (i = 0; i < nc; i++) |
1766 | 0 | cv[i] = frac2cv(cm_comps[i]); |
1767 | 0 | if(i < ncomps) |
1768 | 0 | cv[i] = cm_comps[i]; |
1769 | | /* encode as a color index */ |
1770 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
1771 | | /* check if the encoding was successful; we presume failure is rare */ |
1772 | 0 | if (color != gx_no_color_index) { |
1773 | 0 | color_set_pure(pdc, color); |
1774 | 0 | return; |
1775 | 0 | } |
1776 | 0 | if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs), |
1777 | 0 | &pgs->screen_phase[select]) == 1) |
1778 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
1779 | 0 | } |
1780 | | |
1781 | | /* ------ Halftoning check ----- */ |
1782 | | |
1783 | | static bool |
1784 | | cmap_halftoned_is_halftoned(const gs_gstate * pgs, gx_device * dev) |
1785 | 395k | { |
1786 | 395k | return true; |
1787 | 395k | } |
1788 | | |
1789 | | static bool |
1790 | | cmap_direct_is_halftoned(const gs_gstate * pgs, gx_device * dev) |
1791 | 4.11M | { |
1792 | 4.11M | return false; |
1793 | 4.11M | } |
1794 | | |
1795 | | /* ------ Transfer function mapping ------ */ |
1796 | | |
1797 | | /* Define an identity transfer function. */ |
1798 | | float |
1799 | | gs_identity_transfer(double value, const gx_transfer_map * pmap) |
1800 | 65.8M | { |
1801 | 65.8M | return (float) value; |
1802 | 65.8M | } |
1803 | | |
1804 | | /* Define the generic transfer function for the library layer. */ |
1805 | | /* This just returns what's already in the map. */ |
1806 | | float |
1807 | | gs_mapped_transfer(double value, const gx_transfer_map * pmap) |
1808 | 2 | { |
1809 | 2 | int index = (int)((value) * (transfer_map_size) + 0.5); |
1810 | 2 | if (index > transfer_map_size - 1) |
1811 | 0 | index = transfer_map_size - 1; |
1812 | 2 | return frac2float(pmap->values[index]); |
1813 | 2 | } |
1814 | | |
1815 | | /* Set a transfer map to the identity map. */ |
1816 | | void |
1817 | | gx_set_identity_transfer(gx_transfer_map *pmap) |
1818 | 1.66M | { |
1819 | 1.66M | int i; |
1820 | | |
1821 | 1.66M | pmap->proc = gs_identity_transfer; |
1822 | | /* We still have to fill in the cached values. */ |
1823 | 428M | for (i = 0; i < transfer_map_size; ++i) |
1824 | 426M | pmap->values[i] = bits2frac(i, log2_transfer_map_size); |
1825 | 1.66M | } |
1826 | | |
1827 | | #if FRAC_MAP_INTERPOLATE /* NOTA BENE */ |
1828 | | |
1829 | | /* Map a color fraction through a transfer map. */ |
1830 | | /* We only use this if we are interpolating. */ |
1831 | | frac |
1832 | | gx_color_frac_map(frac cv, const frac * values) |
1833 | 1.42G | { |
1834 | 1.42G | #define cp_frac_bits (frac_bits - log2_transfer_map_size) |
1835 | 1.42G | int cmi = frac2bits_floor(cv, log2_transfer_map_size); |
1836 | 1.42G | frac mv = values[cmi]; |
1837 | 1.42G | int rem, mdv; |
1838 | | |
1839 | | /* Interpolate between two adjacent values if needed. */ |
1840 | 1.42G | rem = cv - bits2frac(cmi, log2_transfer_map_size); |
1841 | 1.42G | if (rem == 0) |
1842 | 1.12G | return mv; |
1843 | 298M | mdv = values[cmi + 1] - mv; |
1844 | | #if ARCH_INTS_ARE_SHORT |
1845 | | /* Only use long multiplication if necessary. */ |
1846 | | if (mdv < -(1 << (16 - cp_frac_bits)) || |
1847 | | mdv > 1 << (16 - cp_frac_bits) |
1848 | | ) |
1849 | | return mv + (uint) (((ulong) rem * mdv) >> cp_frac_bits); |
1850 | | #endif |
1851 | 298M | return mv + ((rem * mdv) >> cp_frac_bits); |
1852 | 1.42G | #undef cp_frac_bits |
1853 | 1.42G | } |
1854 | | |
1855 | | #endif /* FRAC_MAP_INTERPOLATE */ |
1856 | | |
1857 | | /* ------ Default device color mapping ------ */ |
1858 | | /* White-on-black */ |
1859 | | gx_color_index |
1860 | | gx_default_w_b_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1861 | 345 | { /* Map values >= 1/2 to 1, < 1/2 to 0. */ |
1862 | 345 | int i, ncomps = dev->color_info.num_components; |
1863 | 345 | gx_color_value cv_all = 0; |
1864 | | |
1865 | 690 | for (i = 0; i < ncomps; i++) |
1866 | 345 | cv_all |= cv[i]; |
1867 | 345 | return cv_all > gx_max_color_value / 2 ? (gx_color_index)1 |
1868 | 345 | : (gx_color_index)0; |
1869 | | |
1870 | 345 | } |
1871 | | |
1872 | | int |
1873 | | gx_default_w_b_map_color_rgb(gx_device * dev, gx_color_index color, |
1874 | | gx_color_value prgb[3]) |
1875 | 903k | { /* Map 1 to max_value, 0 to 0. */ |
1876 | 903k | prgb[0] = prgb[1] = prgb[2] = -(gx_color_value) color; |
1877 | 903k | return 0; |
1878 | 903k | } |
1879 | | |
1880 | | gx_color_index |
1881 | | gx_default_w_b_mono_encode_color(gx_device *dev, const gx_color_value cv[]) |
1882 | 0 | { |
1883 | 0 | return cv[0] > gx_max_color_value / 2 ? (gx_color_index)1 |
1884 | 0 | : (gx_color_index)0; |
1885 | 0 | } |
1886 | | |
1887 | | int |
1888 | | gx_default_w_b_mono_decode_color(gx_device * dev, gx_color_index color, |
1889 | | gx_color_value pgray[]) |
1890 | 0 | { /* Map 0 to max_value, 1 to 0. */ |
1891 | 0 | pgray[0] = -(gx_color_value) color; |
1892 | 0 | return 0; |
1893 | 0 | } |
1894 | | |
1895 | | /* Black-on-white */ |
1896 | | gx_color_index |
1897 | | gx_default_b_w_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1898 | 143M | { |
1899 | 143M | uchar i, ncomps = dev->color_info.num_components; |
1900 | 143M | gx_color_value cv_all = 0; |
1901 | | |
1902 | 286M | for (i = 0; i < ncomps; i++) |
1903 | 143M | cv_all |= cv[i]; |
1904 | 143M | return cv_all > gx_max_color_value / 2 ? (gx_color_index)0 |
1905 | 143M | : (gx_color_index)1; |
1906 | 143M | } |
1907 | | |
1908 | | int |
1909 | | gx_default_b_w_map_color_rgb(gx_device * dev, gx_color_index color, |
1910 | | gx_color_value prgb[3]) |
1911 | 131k | { /* Map 0 to max_value, 1 to 0. */ |
1912 | 131k | prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1); |
1913 | 131k | return 0; |
1914 | 131k | } |
1915 | | |
1916 | | gx_color_index |
1917 | | gx_default_b_w_mono_encode_color(gx_device *dev, const gx_color_value cv[]) |
1918 | 0 | { |
1919 | 0 | return cv[0] > gx_max_color_value / 2 ? (gx_color_index)0 |
1920 | 0 | : (gx_color_index)1; |
1921 | 0 | } |
1922 | | |
1923 | | int |
1924 | | gx_default_b_w_mono_decode_color(gx_device * dev, gx_color_index color, |
1925 | | gx_color_value pgray[]) |
1926 | 0 | { /* Map 0 to max_value, 1 to 0. */ |
1927 | 0 | pgray[0] = -((gx_color_value) color ^ 1); |
1928 | 0 | return 0; |
1929 | 0 | } |
1930 | | |
1931 | | /* RGB mapping for gray-scale devices */ |
1932 | | |
1933 | | gx_color_index |
1934 | | gx_default_gray_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
1935 | 9.24M | { /* We round the value rather than truncating it. */ |
1936 | 9.24M | gx_color_value gray = |
1937 | 9.24M | (((cv[0] * (ulong) lum_red_weight) + |
1938 | 9.24M | (cv[1] * (ulong) lum_green_weight) + |
1939 | 9.24M | (cv[2] * (ulong) lum_blue_weight) + |
1940 | 9.24M | (lum_all_weights / 2)) / lum_all_weights |
1941 | 9.24M | * dev->color_info.max_gray + |
1942 | 9.24M | (gx_max_color_value / 2)) / gx_max_color_value; |
1943 | | |
1944 | 9.24M | return gray; |
1945 | 9.24M | } |
1946 | | |
1947 | | int |
1948 | | gx_default_gray_map_color_rgb(gx_device * dev, gx_color_index color, |
1949 | | gx_color_value prgb[3]) |
1950 | 7.42M | { |
1951 | 7.42M | gx_color_value gray = (gx_color_value) |
1952 | 7.42M | (color * gx_max_color_value / dev->color_info.max_gray); |
1953 | | |
1954 | 7.42M | prgb[0] = gray; |
1955 | 7.42M | prgb[1] = gray; |
1956 | 7.42M | prgb[2] = gray; |
1957 | 7.42M | return 0; |
1958 | 7.42M | } |
1959 | | |
1960 | | gx_color_index |
1961 | | gx_default_gray_encode_color(gx_device * dev, const gx_color_value cv[]) |
1962 | 0 | { |
1963 | 0 | gx_color_value gray = (cv[0] * dev->color_info.max_gray + |
1964 | 0 | (gx_max_color_value / 2)) / gx_max_color_value; |
1965 | |
|
1966 | 0 | return gray; |
1967 | 0 | } |
1968 | | |
1969 | | int |
1970 | | gx_default_gray_decode_color(gx_device * dev, gx_color_index color, |
1971 | | gx_color_value *cv) |
1972 | 0 | { |
1973 | 0 | gx_color_value gray = (gx_color_value) |
1974 | 0 | (color * gx_max_color_value / dev->color_info.max_gray); |
1975 | |
|
1976 | 0 | cv[0] = gray; |
1977 | 0 | return 0; |
1978 | 0 | } |
1979 | | |
1980 | | gx_color_index |
1981 | | gx_default_8bit_map_gray_color(gx_device * dev, const gx_color_value cv[]) |
1982 | 37.7M | { |
1983 | 37.7M | gx_color_index color = gx_color_value_to_byte(cv[0]); |
1984 | | |
1985 | 37.7M | return color; |
1986 | 37.7M | } |
1987 | | |
1988 | | int |
1989 | | gx_default_8bit_map_color_gray(gx_device * dev, gx_color_index color, |
1990 | | gx_color_value pgray[]) |
1991 | 0 | { |
1992 | 0 | pgray[0] = (gx_color_value)(color * gx_max_color_value / 255); |
1993 | 0 | return 0; |
1994 | 0 | } |
1995 | | |
1996 | | /* RGB mapping for 24-bit true (RGB) color devices */ |
1997 | | |
1998 | | gx_color_index |
1999 | | gx_default_rgb_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
2000 | 122M | { |
2001 | 122M | if (dev->color_info.depth == 24) |
2002 | 122M | return gx_color_value_to_byte(cv[2]) + |
2003 | 122M | ((uint) gx_color_value_to_byte(cv[1]) << 8) + |
2004 | 122M | ((ulong) gx_color_value_to_byte(cv[0]) << 16); |
2005 | 0 | else { |
2006 | 0 | COLROUND_VARS; |
2007 | 0 | int bpc = dev->color_info.depth / 3; |
2008 | 0 | COLROUND_SETUP(bpc); |
2009 | |
|
2010 | 0 | return (((COLROUND_ROUND(cv[0]) << bpc) + |
2011 | 0 | COLROUND_ROUND(cv[1])) << bpc) + |
2012 | 0 | COLROUND_ROUND(cv[2]); |
2013 | 0 | } |
2014 | 122M | } |
2015 | | |
2016 | | /* Map a color index to a r-g-b color. */ |
2017 | | int |
2018 | | gx_default_rgb_map_color_rgb(gx_device * dev, gx_color_index color, |
2019 | | gx_color_value prgb[3]) |
2020 | 3.47M | { |
2021 | 3.47M | if (dev->color_info.depth == 24) { |
2022 | 3.47M | prgb[0] = gx_color_value_from_byte(color >> 16); |
2023 | 3.47M | prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff); |
2024 | 3.47M | prgb[2] = gx_color_value_from_byte(color & 0xff); |
2025 | 3.47M | } else { |
2026 | 0 | uint bits_per_color = dev->color_info.depth / 3; |
2027 | 0 | uint color_mask = (1 << bits_per_color) - 1; |
2028 | |
|
2029 | 0 | prgb[0] = ((color >> (bits_per_color * 2)) & color_mask) * |
2030 | 0 | (ulong) gx_max_color_value / color_mask; |
2031 | 0 | prgb[1] = ((color >> (bits_per_color)) & color_mask) * |
2032 | 0 | (ulong) gx_max_color_value / color_mask; |
2033 | 0 | prgb[2] = (color & color_mask) * |
2034 | 0 | (ulong) gx_max_color_value / color_mask; |
2035 | 0 | } |
2036 | 3.47M | return 0; |
2037 | 3.47M | } |
2038 | | |
2039 | | /* CMYK mapping for RGB devices (should never be called!) */ |
2040 | | |
2041 | | gx_color_index |
2042 | | gx_default_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2043 | 0 | { /* Convert to RGB */ |
2044 | 0 | frac rgb[3]; |
2045 | 0 | gx_color_value rgb_cv[3]; |
2046 | 0 | color_cmyk_to_rgb(cv2frac(cv[0]), cv2frac(cv[1]), cv2frac(cv[2]), cv2frac(cv[3]), |
2047 | 0 | NULL, rgb, dev->memory); |
2048 | 0 | rgb_cv[0] = frac2cv(rgb[0]); |
2049 | 0 | rgb_cv[1] = frac2cv(rgb[1]); |
2050 | 0 | rgb_cv[2] = frac2cv(rgb[2]); |
2051 | 0 | return (*dev_proc(dev, map_rgb_color)) (dev, rgb_cv); |
2052 | 0 | } |
2053 | | |
2054 | | /* Mapping for CMYK devices */ |
2055 | | |
2056 | | gx_color_index |
2057 | | cmyk_1bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2058 | 0 | { |
2059 | 0 | #define CV_BIT(v) ((v) >> (gx_color_value_bits - 1)) |
2060 | 0 | return (gx_color_index) |
2061 | 0 | (CV_BIT(cv[3]) + (CV_BIT(cv[2]) << 1) + (CV_BIT(cv[1]) << 2) + (CV_BIT(cv[0]) << 3)); |
2062 | 0 | #undef CV_BIT |
2063 | 0 | } |
2064 | | |
2065 | | /* Shouldn't be called: decode_color should be cmyk_1bit_map_color_cmyk */ |
2066 | | int |
2067 | | cmyk_1bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2068 | | gx_color_value prgb[3]) |
2069 | 0 | { |
2070 | 0 | if (color & 1) |
2071 | 0 | prgb[0] = prgb[1] = prgb[2] = 0; |
2072 | 0 | else { |
2073 | 0 | prgb[0] = (color & 8 ? 0 : gx_max_color_value); |
2074 | 0 | prgb[1] = (color & 4 ? 0 : gx_max_color_value); |
2075 | 0 | prgb[2] = (color & 2 ? 0 : gx_max_color_value); |
2076 | 0 | } |
2077 | 0 | return 0; |
2078 | 0 | } |
2079 | | |
2080 | | int |
2081 | | cmyk_1bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2082 | | gx_color_value pcv[]) |
2083 | 0 | { |
2084 | 0 | pcv[0] = (color & 8 ? 0 : gx_max_color_value); |
2085 | 0 | pcv[1] = (color & 4 ? 0 : gx_max_color_value); |
2086 | 0 | pcv[2] = (color & 2 ? 0 : gx_max_color_value); |
2087 | 0 | pcv[3] = (color & 1 ? 0 : gx_max_color_value); |
2088 | 0 | return 0; |
2089 | 0 | } |
2090 | | |
2091 | | gx_color_index |
2092 | | cmyk_8bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2093 | 0 | { |
2094 | 0 | gx_color_index color = |
2095 | 0 | gx_color_value_to_byte(cv[3]) + |
2096 | 0 | ((uint)gx_color_value_to_byte(cv[2]) << 8) + |
2097 | 0 | ((uint)gx_color_value_to_byte(cv[1]) << 16) + |
2098 | 0 | ((uint)gx_color_value_to_byte(cv[0]) << 24); |
2099 | |
|
2100 | 0 | #if ARCH_SIZEOF_GX_COLOR_INDEX > 4 |
2101 | 0 | return color; |
2102 | | #else |
2103 | | return (color == gx_no_color_index ? color ^ 1 : color); |
2104 | | #endif |
2105 | 0 | } |
2106 | | |
2107 | | gx_color_index |
2108 | | cmyk_16bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[]) |
2109 | 0 | { |
2110 | 0 | gx_color_index color = |
2111 | 0 | (uint64_t)cv[3] + |
2112 | 0 | ((uint64_t)cv[2] << 16) + |
2113 | 0 | ((uint64_t)cv[1] << 32) + |
2114 | 0 | ((uint64_t)cv[0] << 48); |
2115 | |
|
2116 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
2117 | 0 | } |
2118 | | |
2119 | | /* Shouldn't be called: decode_color should be cmyk_8bit_map_color_cmyk */ |
2120 | | int |
2121 | | cmyk_8bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2122 | | gx_color_value prgb[3]) |
2123 | 0 | { |
2124 | 0 | int |
2125 | 0 | not_k = (int) (~color & 0xff), |
2126 | 0 | r = not_k - (int) (color >> 24), |
2127 | 0 | g = not_k - (int) ((color >> 16) & 0xff), |
2128 | 0 | b = not_k - (int) ((color >> 8) & 0xff); |
2129 | |
|
2130 | 0 | prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r)); |
2131 | 0 | prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g)); |
2132 | 0 | prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b)); |
2133 | 0 | return 0; |
2134 | 0 | } |
2135 | | |
2136 | | int |
2137 | | cmyk_8bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2138 | | gx_color_value pcv[]) |
2139 | 0 | { |
2140 | 0 | pcv[0] = gx_color_value_from_byte((color >> 24) & 0xff); |
2141 | 0 | pcv[1] = gx_color_value_from_byte((color >> 16) & 0xff); |
2142 | 0 | pcv[2] = gx_color_value_from_byte((color >> 8) & 0xff); |
2143 | 0 | pcv[3] = gx_color_value_from_byte(color & 0xff); |
2144 | 0 | return 0; |
2145 | 0 | } |
2146 | | |
2147 | | int |
2148 | | cmyk_16bit_map_color_cmyk(gx_device * dev, gx_color_index color, |
2149 | | gx_color_value pcv[]) |
2150 | 0 | { |
2151 | 0 | pcv[0] = ((color >> 24) >> 24) & 0xffff; |
2152 | 0 | pcv[1] = ((color >> 16) >> 16) & 0xffff; |
2153 | 0 | pcv[2] = ( color >> 16) & 0xffff; |
2154 | 0 | pcv[3] = ( color ) & 0xffff; |
2155 | 0 | return 0; |
2156 | 0 | } |
2157 | | |
2158 | | int |
2159 | | cmyk_16bit_map_color_rgb(gx_device * dev, gx_color_index color, |
2160 | | gx_color_value prgb[3]) |
2161 | 0 | { |
2162 | 0 | gx_color_value c = ((color >> 24) >> 24) & 0xffff; |
2163 | 0 | gx_color_value m = ((color >> 16) >> 16) & 0xffff; |
2164 | 0 | gx_color_value y = ( color >> 16) & 0xffff; |
2165 | 0 | gx_color_value not_k = (~color ) & 0xffff; |
2166 | 0 | int r = not_k - c; |
2167 | 0 | int g = not_k - m; |
2168 | 0 | int b = not_k - y; |
2169 | |
|
2170 | 0 | prgb[0] = (r < 0 ? 0 : r); |
2171 | 0 | prgb[1] = (g < 0 ? 0 : g); |
2172 | 0 | prgb[2] = (b < 0 ? 0 : b); |
2173 | 0 | return 0; |
2174 | 0 | } |
2175 | | |
2176 | | frac |
2177 | | gx_unit_frac(float fvalue) |
2178 | 6.42M | { |
2179 | 6.42M | frac f = frac_0; |
2180 | 6.42M | if (is_fneg(fvalue)) |
2181 | 0 | f = frac_0; |
2182 | 6.42M | else if (is_fge1(fvalue)) |
2183 | 251k | f = frac_1; |
2184 | 6.17M | else |
2185 | 6.17M | f = float2frac(fvalue); |
2186 | 6.42M | return f; |
2187 | 6.42M | } |
2188 | | |
2189 | | static void |
2190 | | cmapper_transfer_halftone_add(gx_cmapper_t *data) |
2191 | 896k | { |
2192 | 896k | gx_color_value *pconc = &data->conc[0]; |
2193 | 896k | const gs_gstate * pgs = data->pgs; |
2194 | 896k | gx_device * dev = data->dev; |
2195 | 896k | gs_color_select_t select = data->select; |
2196 | 896k | uchar ncomps = dev->color_info.num_components; |
2197 | 896k | frac frac_value; |
2198 | 896k | uchar i; |
2199 | 896k | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2200 | | |
2201 | | /* apply the transfer function(s) */ |
2202 | 1.79M | for (i = 0; i < ncomps; i++) { |
2203 | 896k | frac_value = cv2frac(pconc[i]); |
2204 | 896k | cv_frac[i] = gx_map_color_frac(pgs, frac_value, effective_transfer[i]); |
2205 | 896k | } |
2206 | | /* Halftoning */ |
2207 | 896k | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2208 | 896k | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2209 | 594k | gx_color_load_select(&data->devc, pgs, dev, select); |
2210 | 896k | } |
2211 | | |
2212 | | static void |
2213 | | cmapper_transfer_halftone_op(gx_cmapper_t *data) |
2214 | 0 | { |
2215 | 0 | gx_color_value *pconc = &data->conc[0]; |
2216 | 0 | const gs_gstate * pgs = data->pgs; |
2217 | 0 | gx_device * dev = data->dev; |
2218 | 0 | gs_color_select_t select = data->select; |
2219 | 0 | uchar ncomps = dev->color_info.num_components; |
2220 | 0 | frac frac_value; |
2221 | 0 | uchar i; |
2222 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2223 | | |
2224 | | /* apply the transfer function(s) */ |
2225 | 0 | uint k = dev->color_info.black_component; |
2226 | 0 | for (i = 0; i < ncomps; i++) { |
2227 | 0 | frac_value = cv2frac(pconc[i]); |
2228 | 0 | if (i == k) { |
2229 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2230 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2231 | 0 | } else { |
2232 | 0 | cv_frac[i] = frac_value; /* Ignore transfer, see PLRM3 p. 494 */ |
2233 | 0 | } |
2234 | 0 | } |
2235 | | /* Halftoning */ |
2236 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2237 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2238 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2239 | 0 | } |
2240 | | |
2241 | | static void |
2242 | | cmapper_transfer_halftone_sub(gx_cmapper_t *data) |
2243 | 0 | { |
2244 | 0 | gx_color_value *pconc = &data->conc[0]; |
2245 | 0 | const gs_gstate * pgs = data->pgs; |
2246 | 0 | gx_device * dev = data->dev; |
2247 | 0 | gs_color_select_t select = data->select; |
2248 | 0 | uchar ncomps = dev->color_info.num_components; |
2249 | 0 | frac frac_value; |
2250 | 0 | uchar i; |
2251 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2252 | | |
2253 | | /* apply the transfer function(s) */ |
2254 | 0 | for (i = 0; i < ncomps; i++) { |
2255 | 0 | frac_value = cv2frac(pconc[i]); |
2256 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2257 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2258 | 0 | } |
2259 | | /* Halftoning */ |
2260 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2261 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2262 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2263 | 0 | } |
2264 | | |
2265 | | static void |
2266 | | cmapper_transfer_add(gx_cmapper_t *data) |
2267 | 51.3M | { |
2268 | 51.3M | gx_color_value *pconc = &data->conc[0]; |
2269 | 51.3M | const gs_gstate * pgs = data->pgs; |
2270 | 51.3M | gx_device * dev = data->dev; |
2271 | 51.3M | uchar ncomps = dev->color_info.num_components; |
2272 | 51.3M | frac frac_value; |
2273 | 51.3M | uchar i; |
2274 | 51.3M | gx_color_index color; |
2275 | | |
2276 | | /* apply the transfer function(s) */ |
2277 | 51.3M | if (device_encodes_tags(dev)) |
2278 | 0 | ncomps--; |
2279 | 201M | for (i = 0; i < ncomps; i++) { |
2280 | 149M | frac_value = cv2frac(pconc[i]); |
2281 | 149M | frac_value = gx_map_color_frac(pgs, |
2282 | 149M | frac_value, effective_transfer[i]); |
2283 | 149M | pconc[i] = frac2cv(frac_value); |
2284 | 149M | } |
2285 | | /* Halftoning */ |
2286 | 51.3M | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2287 | | /* check if the encoding was successful; we presume failure is rare */ |
2288 | 51.3M | if (color != gx_no_color_index) |
2289 | 51.3M | color_set_pure(&data->devc, color); |
2290 | 51.3M | } |
2291 | | |
2292 | | static void |
2293 | | cmapper_transfer_op(gx_cmapper_t *data) |
2294 | 0 | { |
2295 | 0 | gx_color_value *pconc = &data->conc[0]; |
2296 | 0 | const gs_gstate * pgs = data->pgs; |
2297 | 0 | gx_device * dev = data->dev; |
2298 | 0 | frac frac_value; |
2299 | 0 | gx_color_index color; |
2300 | |
|
2301 | 0 | uint k = dev->color_info.black_component; |
2302 | | /* Ignore transfer for non blacks, see PLRM3 p. 494 */ |
2303 | 0 | frac_value = cv2frac(pconc[k]); |
2304 | 0 | frac_value = frac_1 - gx_map_color_frac(pgs, |
2305 | 0 | (frac)(frac_1 - frac_value), effective_transfer[k]); |
2306 | 0 | pconc[k] = frac2cv(frac_value); |
2307 | | /* Halftoning */ |
2308 | 0 | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2309 | | /* check if the encoding was successful; we presume failure is rare */ |
2310 | 0 | if (color != gx_no_color_index) |
2311 | 0 | color_set_pure(&data->devc, color); |
2312 | 0 | } |
2313 | | |
2314 | | static void |
2315 | | cmapper_transfer_sub(gx_cmapper_t *data) |
2316 | 0 | { |
2317 | 0 | gx_color_value *pconc = &data->conc[0]; |
2318 | 0 | const gs_gstate * pgs = data->pgs; |
2319 | 0 | gx_device * dev = data->dev; |
2320 | 0 | uchar ncomps = dev->color_info.num_components; |
2321 | 0 | frac frac_value; |
2322 | 0 | uchar i; |
2323 | 0 | gx_color_index color; |
2324 | | |
2325 | | /* apply the transfer function(s) */ |
2326 | 0 | if (device_encodes_tags(dev)) |
2327 | 0 | ncomps--; |
2328 | 0 | for (i = 0; i < ncomps; i++) { |
2329 | 0 | frac_value = cv2frac(pconc[i]); |
2330 | 0 | frac_value = frac_1 - gx_map_color_frac(pgs, |
2331 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2332 | 0 | pconc[i] = frac2cv(frac_value); |
2333 | 0 | } |
2334 | | /* Halftoning */ |
2335 | 0 | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2336 | | /* check if the encoding was successful; we presume failure is rare */ |
2337 | 0 | if (color != gx_no_color_index) |
2338 | 0 | color_set_pure(&data->devc, color); |
2339 | 0 | } |
2340 | | |
2341 | | /* This is used by image color render to handle the cases where we need to |
2342 | | perform either a transfer function or halftoning on the color values |
2343 | | during an ICC color flow. In this case, the color is already in the |
2344 | | device color space but in 16bpp color values. */ |
2345 | | static void |
2346 | | cmapper_halftone(gx_cmapper_t *data) |
2347 | 0 | { |
2348 | 0 | gx_color_value *pconc = &data->conc[0]; |
2349 | 0 | const gs_gstate * pgs = data->pgs; |
2350 | 0 | gx_device * dev = data->dev; |
2351 | 0 | gs_color_select_t select = data->select; |
2352 | 0 | uchar ncomps = dev->color_info.num_components; |
2353 | 0 | uchar i; |
2354 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2355 | | |
2356 | | /* We need this to be in frac form */ |
2357 | 0 | for (i = 0; i < ncomps; i++) { |
2358 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2359 | 0 | } |
2360 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev, |
2361 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2362 | 0 | gx_color_load_select(&data->devc, pgs, dev, select); |
2363 | 0 | } |
2364 | | |
2365 | | /* This is used by image color render to handle the cases where we need to |
2366 | | perform either a transfer function or halftoning on the color values |
2367 | | during an ICC color flow. In this case, the color is already in the |
2368 | | device color space but in 16bpp color values. */ |
2369 | | static void |
2370 | | cmapper_vanilla(gx_cmapper_t *data) |
2371 | 371M | { |
2372 | 371M | gx_color_value *pconc = &data->conc[0]; |
2373 | 371M | gx_device * dev = data->dev; |
2374 | 371M | gx_color_index color; |
2375 | | |
2376 | 371M | color = dev_proc(dev, encode_color)(dev, &(pconc[0])); |
2377 | | /* check if the encoding was successful; we presume failure is rare */ |
2378 | 371M | if (color != gx_no_color_index) |
2379 | 371M | color_set_pure(&data->devc, color); |
2380 | 371M | } |
2381 | | |
2382 | | void |
2383 | | gx_get_cmapper(gx_cmapper_t *data, const gs_gstate *pgs, |
2384 | | gx_device *dev, bool has_transfer, bool has_halftone, |
2385 | | gs_color_select_t select) |
2386 | 10.3M | { |
2387 | 10.3M | memset(&(data->conc[0]), 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS])); |
2388 | 10.3M | data->pgs = pgs; |
2389 | 10.3M | data->dev = dev; |
2390 | 10.3M | data->select = select; |
2391 | 10.3M | data->devc.type = gx_dc_type_none; |
2392 | 10.3M | data->direct = 0; |
2393 | | /* Per spec. Images with soft mask, and the mask, do not use transfer function */ |
2394 | 10.3M | if (pgs->effective_transfer_non_identity_count == 0 || |
2395 | 10.3M | (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0) |
2396 | 9.95M | has_transfer = 0; |
2397 | 10.3M | if (has_transfer) { |
2398 | 363k | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2399 | 363k | if (has_halftone) |
2400 | 11.2k | data->set_color = cmapper_transfer_halftone_add; |
2401 | 352k | else |
2402 | 352k | data->set_color = cmapper_transfer_add; |
2403 | 363k | } else if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { |
2404 | 0 | if (has_halftone) |
2405 | 0 | data->set_color = cmapper_transfer_halftone_op; |
2406 | 0 | else |
2407 | 0 | data->set_color = cmapper_transfer_op; |
2408 | 0 | } else { |
2409 | 0 | if (has_halftone) |
2410 | 0 | data->set_color = cmapper_transfer_halftone_sub; |
2411 | 0 | else |
2412 | 0 | data->set_color = cmapper_transfer_sub; |
2413 | 0 | } |
2414 | 9.95M | } else { |
2415 | 9.95M | if (has_halftone) |
2416 | 0 | data->set_color = cmapper_halftone; |
2417 | 9.95M | else { |
2418 | 9.95M | int code = dev_proc(dev, dev_spec_op)(dev, gxdso_is_encoding_direct, NULL, 0); |
2419 | 9.95M | data->set_color = cmapper_vanilla; |
2420 | 9.95M | data->direct = (code == 1); |
2421 | 9.95M | } |
2422 | 9.95M | } |
2423 | 10.3M | } |
2424 | | |
2425 | | /* This is used by image color render to handle the cases where we need to |
2426 | | perform either a transfer function or halftoning on the color values |
2427 | | during an ICC color flow. In this case, the color is already in the |
2428 | | device color space but in 16bpp color values. */ |
2429 | | void |
2430 | | cmap_transfer_halftone(gx_color_value *pconc, gx_device_color * pdc, |
2431 | | const gs_gstate * pgs, gx_device * dev, bool has_transfer, |
2432 | | bool has_halftone, gs_color_select_t select) |
2433 | 0 | { |
2434 | 0 | uchar nc, ncomps = dev->color_info.num_components; |
2435 | 0 | frac frac_value; |
2436 | 0 | uchar i; |
2437 | 0 | frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2438 | 0 | gx_color_index color; |
2439 | 0 | gx_color_value color_val[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
2440 | | |
2441 | | /* apply the transfer function(s) */ |
2442 | 0 | nc = ncomps; |
2443 | 0 | if (device_encodes_tags(dev)) |
2444 | 0 | nc--; |
2445 | 0 | if (has_transfer) { |
2446 | 0 | if (pgs->effective_transfer_non_identity_count == 0) { |
2447 | 0 | for (i = 0; i < nc; i++) |
2448 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2449 | 0 | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2450 | 0 | for (i = 0; i < nc; i++) { |
2451 | 0 | frac_value = cv2frac(pconc[i]); |
2452 | 0 | cv_frac[i] = gx_map_color_frac(pgs, |
2453 | 0 | frac_value, effective_transfer[i]); |
2454 | 0 | } |
2455 | 0 | } else { |
2456 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2457 | 0 | uint k = dev->color_info.black_component; |
2458 | 0 | for (i = 0; i < nc; i++) { |
2459 | 0 | frac_value = cv2frac(pconc[i]); |
2460 | 0 | if (i == k) { |
2461 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2462 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2463 | 0 | } else { |
2464 | 0 | cv_frac[i] = cv2frac(pconc[i]); /* Ignore transfer, see PLRM3 p. 494 */ |
2465 | 0 | } |
2466 | 0 | } |
2467 | 0 | } else { |
2468 | 0 | for (i = 0; i < nc; i++) { |
2469 | 0 | frac_value = cv2frac(pconc[i]); |
2470 | 0 | cv_frac[i] = frac_1 - gx_map_color_frac(pgs, |
2471 | 0 | (frac)(frac_1 - frac_value), effective_transfer[i]); |
2472 | 0 | } |
2473 | 0 | } |
2474 | 0 | } |
2475 | 0 | if (nc < ncomps) |
2476 | 0 | cv_frac[nc] = pconc[nc]; |
2477 | 0 | } else { |
2478 | 0 | if (has_halftone) { |
2479 | | /* We need this to be in frac form */ |
2480 | 0 | for (i = 0; i < nc; i++) { |
2481 | 0 | cv_frac[i] = cv2frac(pconc[i]); |
2482 | 0 | } |
2483 | 0 | if (nc < ncomps) |
2484 | 0 | cv_frac[nc] = pconc[nc]; |
2485 | 0 | } |
2486 | 0 | } |
2487 | | /* Halftoning */ |
2488 | 0 | if (has_halftone) { |
2489 | 0 | if (gx_render_device_DeviceN(&(cv_frac[0]), pdc, dev, |
2490 | 0 | gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1) |
2491 | 0 | gx_color_load_select(pdc, pgs, dev, select); |
2492 | 0 | } else { |
2493 | | /* We have a frac value from the transfer function. Do the encode. |
2494 | | which does not take a frac value... */ |
2495 | 0 | for (i = 0; i < nc; i++) { |
2496 | 0 | color_val[i] = frac2cv(cv_frac[i]); |
2497 | 0 | } |
2498 | 0 | if (i < ncomps) |
2499 | 0 | color_val[i] = cv_frac[i]; |
2500 | 0 | color = dev_proc(dev, encode_color)(dev, &(color_val[0])); |
2501 | | /* check if the encoding was successful; we presume failure is rare */ |
2502 | 0 | if (color != gx_no_color_index) |
2503 | 0 | color_set_pure(pdc, color); |
2504 | 0 | } |
2505 | 0 | } |
2506 | | |
2507 | | /* This is used by image color render to apply only the transfer function. |
2508 | | We follow this up with threshold rendering. */ |
2509 | | void |
2510 | | cmap_transfer(gx_color_value *pconc, const gs_gstate * pgs, gx_device * dev) |
2511 | 0 | { |
2512 | 0 | uchar ncomps = dev->color_info.num_components; |
2513 | 0 | uchar i; |
2514 | | |
2515 | | /* apply the transfer function(s) */ |
2516 | 0 | if (device_encodes_tags(dev)) |
2517 | 0 | ncomps--; |
2518 | 0 | if (pgs->effective_transfer_non_identity_count == 0) { |
2519 | | /* No transfer function to apply */ |
2520 | 0 | } else if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
2521 | 0 | for (i = 0; i < ncomps; i++) |
2522 | 0 | pconc[i] = frac2cv(gx_map_color_frac(pgs, |
2523 | 0 | cv2frac(pconc[i]), effective_transfer[i])); |
2524 | 0 | else { |
2525 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2526 | 0 | i = dev->color_info.black_component; |
2527 | 0 | if (i < ncomps) |
2528 | 0 | pconc[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
2529 | 0 | (frac)(frac_1 - cv2frac(pconc[i])), effective_transfer[i])); |
2530 | 0 | } else { |
2531 | 0 | for (i = 0; i < ncomps; i++) |
2532 | 0 | pconc[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, |
2533 | 0 | (frac)(frac_1 - cv2frac(pconc[i])), effective_transfer[i])); |
2534 | 0 | } |
2535 | 0 | } |
2536 | 0 | } |
2537 | | |
2538 | | /* A planar version which applies only one transfer function */ |
2539 | | void |
2540 | | cmap_transfer_plane(gx_color_value *pconc, const gs_gstate *pgs, |
2541 | | gx_device *dev, int plane) |
2542 | 0 | { |
2543 | 0 | frac frac_value; |
2544 | 0 | frac cv_frac; |
2545 | | |
2546 | | /* apply the transfer function(s) */ |
2547 | 0 | if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
2548 | 0 | frac_value = cv2frac(pconc[0]); |
2549 | 0 | cv_frac = gx_map_color_frac(pgs, frac_value, effective_transfer[plane]); |
2550 | 0 | pconc[0] = frac2cv(cv_frac); |
2551 | 0 | } else { |
2552 | 0 | if (gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED) { /* CMYK-like color space */ |
2553 | 0 | uint k = dev->color_info.black_component; |
2554 | 0 | if (plane == k) { |
2555 | 0 | frac_value = cv2frac(pconc[0]); |
2556 | 0 | cv_frac = frac_1 - gx_map_color_frac(pgs, |
2557 | 0 | (frac)(frac_1 - frac_value), effective_transfer[plane]); |
2558 | 0 | pconc[0] = frac2cv(cv_frac); |
2559 | 0 | } |
2560 | 0 | } else { |
2561 | 0 | frac_value = cv2frac(pconc[0]); |
2562 | 0 | cv_frac = frac_1 - gx_map_color_frac(pgs, |
2563 | 0 | (frac)(frac_1 - frac_value), effective_transfer[plane]); |
2564 | 0 | pconc[0] = frac2cv(cv_frac); |
2565 | 0 | } |
2566 | 0 | } |
2567 | 0 | } |
2568 | | |
2569 | | |
2570 | | bool |
2571 | | gx_device_uses_std_cmap_procs(gx_device * dev, const gs_gstate * pgs) |
2572 | 1.28M | { |
2573 | 1.28M | const gx_cm_color_map_procs *pprocs; |
2574 | 1.28M | gsicc_rendering_param_t render_cond; |
2575 | 1.28M | cmm_dev_profile_t *dev_profile = NULL; |
2576 | 1.28M | cmm_profile_t *des_profile = NULL; |
2577 | | |
2578 | 1.28M | dev_proc(dev, get_profile)(dev, &dev_profile); |
2579 | 1.28M | gsicc_extract_profile(dev->graphics_type_tag, |
2580 | 1.28M | dev_profile, &des_profile, &render_cond); |
2581 | | |
2582 | 1.28M | if (des_profile != NULL) { |
2583 | 1.28M | const gx_device *cmdev; |
2584 | | |
2585 | 1.28M | pprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev); |
2586 | | /* Check if they are forwarding procs */ |
2587 | 1.28M | switch(des_profile->num_comps) { |
2588 | 157k | case 1: |
2589 | 157k | if (pprocs == &DeviceGray_procs) { |
2590 | 155k | return true; |
2591 | 155k | } |
2592 | 1.41k | break; |
2593 | 1.07M | case 3: |
2594 | 1.07M | if (pprocs == &DeviceRGB_procs) { |
2595 | 835k | return true; |
2596 | 835k | } |
2597 | 243k | break; |
2598 | 243k | case 4: |
2599 | 52.4k | if (pprocs == &DeviceCMYK_procs) { |
2600 | 0 | return true; |
2601 | 0 | } |
2602 | 52.4k | break; |
2603 | 52.4k | default: |
2604 | 0 | break; |
2605 | 1.28M | } |
2606 | 1.28M | } |
2607 | 296k | return false; |
2608 | 1.28M | } |