1 /* Copyright (C) 2001-2012 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., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Implementation of the ICCBased color space family */
18
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsstruct.h"
24 #include "stream.h"
25 #include "gxcspace.h" /* for gxcie.c */
26 #include "gxarith.h"
27 #include "gxcie.h"
28 #include "gzstate.h"
29 #include "gsicc.h"
30 #include "gsicc_cache.h"
31 #include "gsicc_cms.h"
32 #include "gxdevice.h"
33
34 #define SAVEICCPROFILE 0
35
36 /*
37 * Color space methods for ICCBased color spaces.
38 ICC spaces are now considered to be concrete in that
39 they always provide a mapping to a specified destination
40 profile. As such they will have their own remap functions.
41 These will simply potentially implement the transfer function,
42 apply any alpha value, and or end up going through halftoning.
43 There will not be any heuristic remap of rgb to gray etc */
44
45 static cs_proc_num_components(gx_num_components_ICC);
46 static cs_proc_init_color(gx_init_ICC);
47 static cs_proc_restrict_color(gx_restrict_ICC);
48 static cs_proc_concretize_color(gx_concretize_ICC);
49 static cs_proc_remap_color(gx_remap_ICC);
50 static cs_proc_install_cspace(gx_install_ICC);
51 static cs_proc_remap_concrete_color(gx_remap_concrete_ICC);
52 static cs_proc_final(gx_final_ICC);
53 static cs_proc_serialize(gx_serialize_ICC);
54 static cs_proc_is_linear(gx_cspace_is_linear_ICC);
55 static cs_proc_set_overprint(gx_set_overprint_ICC);
56 cs_proc_remap_color(gx_remap_ICC_imagelab);
57
58 const gs_color_space_type gs_color_space_type_ICC = {
59 gs_color_space_index_ICC, /* index */
60 true, /* can_be_base_space */
61 true, /* can_be_alt_space */
62 &st_base_color_space, /* stype - structure descriptor */
63 gx_num_components_ICC, /* num_components */
64 gx_init_ICC, /* init_color */
65 gx_restrict_ICC, /* restrict_color */
66 gx_same_concrete_space, /* concrete_space */
67 gx_concretize_ICC, /* concreteize_color */
68 gx_remap_concrete_ICC, /* remap_concrete_color */
69 gx_remap_ICC, /* remap_color */
70 gx_install_ICC, /* install_cpsace */
71 gx_set_overprint_ICC, /* set_overprint */
72 gx_final_ICC, /* final */
73 gx_no_adjust_color_count, /* adjust_color_count */
74 gx_serialize_ICC, /* serialize */
75 gx_cspace_is_linear_ICC
76 };
77
78 static inline void
gsicc_remap_fast(gx_device * dev,unsigned short * psrc,unsigned short * psrc_cm,gsicc_link_t * icc_link)79 gsicc_remap_fast(gx_device *dev, unsigned short *psrc, unsigned short *psrc_cm,
80 gsicc_link_t *icc_link)
81 {
82 (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_cm, 2);
83 }
84
85 /* ICC color mapping linearity check, a 2-points case. Check only the 1/2 point */
86 static int
gx_icc_is_linear_in_line(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,float smoothness,gsicc_link_t * icclink)87 gx_icc_is_linear_in_line(const gs_color_space *cs, const gs_imager_state * pis,
88 gx_device *dev,
89 const gs_client_color *c0, const gs_client_color *c1,
90 float smoothness, gsicc_link_t *icclink)
91 {
92 int nsrc = cs->type->num_components(cs);
93 cmm_dev_profile_t *dev_profile;
94 int ndes;
95 int code;
96 unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
97 unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
98 unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
99 unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
100 unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
101 unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
102 unsigned short interp_des;
103 unsigned short max_diff = (unsigned short) max(1, 65535 * smoothness);
104 int k;
105
106 code = dev_proc(dev, get_profile)(dev, &(dev_profile));
107 ndes = gsicc_get_device_profile_comps(dev_profile);
108
109 /* Get us to ushort and get mid point */
110 for (k = 0; k < nsrc; k++) {
111 src0[k] = (unsigned short) (c0->paint.values[k]*65535);
112 src1[k] = (unsigned short) (c1->paint.values[k]*65535);
113 src01[k] = ((unsigned int) src0[k] + (unsigned int) src1[k]) >> 1;
114 }
115 /* Transform the end points and the interpolated point */
116 gsicc_remap_fast(dev, &(src0[0]), &(des0[0]), icclink);
117 gsicc_remap_fast(dev, &(src1[0]), &(des1[0]), icclink);
118 gsicc_remap_fast(dev, &(src01[0]), &(des01[0]), icclink);
119 /* Interpolate 1/2 value in des space and compare */
120 for (k = 0; k < ndes; k++) {
121 interp_des = (des0[k] + des1[k]) >> 1;
122 if (any_abs((signed int) interp_des - (signed int) des01[k]) > max_diff)
123 return false;
124 }
125 return 1;
126 }
127
128 /* Default icc color mapping linearity check, a triangle case. */
129 static int
gx_icc_is_linear_in_triangle(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,const gs_client_color * c2,float smoothness,gsicc_link_t * icclink)130 gx_icc_is_linear_in_triangle(const gs_color_space *cs, const gs_imager_state * pis,
131 gx_device *dev,
132 const gs_client_color *c0, const gs_client_color *c1,
133 const gs_client_color *c2, float smoothness, gsicc_link_t *icclink)
134 {
135 /* Check 4 points middle points of 3 sides and middle of one side with
136 other point. We avoid divisions this way. */
137 unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
138 unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
139 unsigned short src2[GS_CLIENT_COLOR_MAX_COMPONENTS];
140 unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
141 unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
142 unsigned short des2[GS_CLIENT_COLOR_MAX_COMPONENTS];
143 unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
144 unsigned short src12[GS_CLIENT_COLOR_MAX_COMPONENTS];
145 unsigned short src02[GS_CLIENT_COLOR_MAX_COMPONENTS];
146 unsigned short src012[GS_CLIENT_COLOR_MAX_COMPONENTS];
147 unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
148 unsigned short des12[GS_CLIENT_COLOR_MAX_COMPONENTS];
149 unsigned short des02[GS_CLIENT_COLOR_MAX_COMPONENTS];
150 unsigned short des012[GS_CLIENT_COLOR_MAX_COMPONENTS];
151 int nsrc = cs->type->num_components(cs);
152 int ndes, code;
153 unsigned short max_diff = (unsigned short) max(1, 65535 * smoothness);
154 unsigned int interp_des;
155 int k;
156 cmm_dev_profile_t *dev_profile;
157
158 code = dev_proc(dev, get_profile)(dev, &(dev_profile));
159 ndes = gsicc_get_device_profile_comps(dev_profile);
160
161 /* This needs to be optimized. And range corrected */
162 for (k = 0; k < nsrc; k++){
163 src0[k] = (unsigned short) (c0->paint.values[k]*65535);
164 src1[k] = (unsigned short) (c1->paint.values[k]*65535);
165 src2[k] = (unsigned short) (c2->paint.values[k]*65535);
166 src01[k] = (src0[k] + src1[k]) >> 1;
167 src02[k] = (src0[k] + src2[k]) >> 1;
168 src12[k] = (src1[k] + src2[k]) >> 1;
169 src012[k] = (src12[k] + src0[k]) >> 1;
170 }
171 /* Map the points */
172 gsicc_remap_fast(dev, &(src0[0]), &(des0[0]), icclink);
173 gsicc_remap_fast(dev, &(src1[0]), &(des1[0]), icclink);
174 gsicc_remap_fast(dev, &(src2[0]), &(des2[0]), icclink);
175 gsicc_remap_fast(dev, &(src01[0]), &(des01[0]), icclink);
176 gsicc_remap_fast(dev, &(src12[0]), &(des12[0]), icclink);
177 gsicc_remap_fast(dev, &(src02[0]), &(des02[0]), icclink);
178 gsicc_remap_fast(dev, &(src012[0]), &(des012[0]), icclink);
179 /* Interpolate in des space and check it */
180 for (k = 0; k < ndes; k++){
181 interp_des = (des0[k] + des1[k]) >> 1;
182 if (any_abs((signed int) interp_des - (signed int) des01[k]) > max_diff)
183 return false;
184 interp_des = (des0[k] + des2[k]) >> 1;
185 if (any_abs((signed int) interp_des - (signed int) des02[k]) > max_diff)
186 return false;
187 interp_des = (des1[k] + des2[k]) >> 1;
188 if (any_abs((signed int) interp_des - (signed int) des12[k]) > max_diff)
189 return false;
190 /* 12 with 0 */
191 interp_des = (des0[k] + interp_des) >> 1;
192 if (any_abs((signed int) interp_des - (signed int) des012[k]) > max_diff)
193 return false;
194 }
195 return 1;
196 }
197
198 /* ICC color mapping linearity check. */
199 int
gx_cspace_is_linear_ICC(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,const gs_client_color * c2,const gs_client_color * c3,float smoothness,gsicc_link_t * icclink)200 gx_cspace_is_linear_ICC(const gs_color_space *cs, const gs_imager_state * pis,
201 gx_device *dev,
202 const gs_client_color *c0, const gs_client_color *c1,
203 const gs_client_color *c2, const gs_client_color *c3,
204 float smoothness, gsicc_link_t *icclink)
205 {
206 /* Assuming 2 <= nc <= 4. We don't need other cases. */
207 /* With nc == 4 assuming a convex plain quadrangle in the client color space. */
208 int code;
209
210 /* Do a quick check if we are in a halftone situation. If yes,
211 then we should not be doing this linear check */
212 if (gx_device_must_halftone(dev)) return 0;
213 if (icclink->is_identity) return 1; /* Transform is identity, linear! */
214
215 if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
216 return_error(gs_error_rangecheck);
217 if (c2 == NULL)
218 return gx_icc_is_linear_in_line(cs, pis, dev, c0, c1, smoothness, icclink);
219 code = gx_icc_is_linear_in_triangle(cs, pis, dev, c0, c1, c2,
220 smoothness, icclink);
221 if (code <= 0)
222 return code;
223 if (c3 == NULL)
224 return 1;
225 return gx_icc_is_linear_in_triangle(cs, pis, dev, c1, c2, c3,
226 smoothness, icclink);
227 }
228 /*
229 * Return the number of components used by a ICCBased color space - 1, 3, or 4
230 */
231 static int
gx_num_components_ICC(const gs_color_space * pcs)232 gx_num_components_ICC(const gs_color_space * pcs)
233 {
234 return pcs->cmm_icc_profile_data->num_comps;
235 }
236
237 /*
238 * Set the initial client color for an ICCBased color space. The convention
239 * suggested by the ICC specification is to set all components to 0.
240 */
241 static void
gx_init_ICC(gs_client_color * pcc,const gs_color_space * pcs)242 gx_init_ICC(gs_client_color * pcc, const gs_color_space * pcs)
243 {
244 int i, ncomps = pcs->cmm_icc_profile_data->num_comps;
245
246 for (i = 0; i < ncomps; ++i)
247 pcc->paint.values[i] = 0.0;
248
249 /* make sure that [ 0, ... 0] is in range */
250 gx_restrict_ICC(pcc, pcs);
251 }
252
253 /*
254 * Restrict an color to the range specified for an ICCBased color space.
255 */
256 static void
gx_restrict_ICC(gs_client_color * pcc,const gs_color_space * pcs)257 gx_restrict_ICC(gs_client_color * pcc, const gs_color_space * pcs)
258 {
259 int i, ncomps = pcs->cmm_icc_profile_data->num_comps;
260 const gs_range * ranges = pcs->cmm_icc_profile_data->Range.ranges;
261
262 for (i = 0; i < ncomps; ++i) {
263 floatp v = pcc->paint.values[i];
264 floatp rmin = ranges[i].rmin, rmax = ranges[i].rmax;
265
266 if (v < rmin)
267 pcc->paint.values[i] = rmin;
268 else if (v > rmax)
269 pcc->paint.values[i] = rmax;
270 }
271 }
272
273 /* If the color is already concretized, then we are in the color space
274 defined by the device profile. The remaining things to do would
275 be to potentially apply alpha, apply the transfer function, and
276 do any halftoning. The remap is based upon the ICC profile defined
277 in the device profile entry of the profile manager. */
278 int
gx_remap_concrete_ICC(const frac * pconc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)279 gx_remap_concrete_ICC(const frac * pconc, const gs_color_space * pcs,
280 gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
281 gs_color_select_t select)
282 {
283 int num_colorants;
284 int code;
285 cmm_dev_profile_t *dev_profile;
286
287 code = dev_proc(dev, get_profile)(dev, &dev_profile);
288 num_colorants = gsicc_get_device_profile_comps(dev_profile);
289 switch( num_colorants ) {
290 case 1:
291 code = gx_remap_concrete_DGray(pconc, pcs, pdc, pis, dev, select);
292 break;
293 case 3:
294 code = gx_remap_concrete_DRGB(pconc, pcs, pdc, pis, dev, select);
295 break;
296 case 4:
297 code = gx_remap_concrete_DCMYK(pconc, pcs, pdc, pis, dev, select);
298 break;
299 default:
300 /* Need to do some work on integrating DeviceN and the new ICC flow */
301 /* code = gx_remap_concrete_DeviceN(pconc, pcs, pdc, pis, dev, select); */
302 code = -1;
303 break;
304 }
305 return code;
306 }
307
308 /*
309 * To device space
310 */
311 int
gx_remap_ICC(const gs_client_color * pcc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)312 gx_remap_ICC(const gs_client_color * pcc, const gs_color_space * pcs,
313 gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
314 gs_color_select_t select)
315 {
316 gsicc_link_t *icc_link;
317 gsicc_rendering_param_t rendering_params;
318 unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
319 unsigned short *psrc_temp;
320 frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
321 int k,i;
322 #ifdef DEBUG
323 int num_src_comps;
324 #endif
325 int num_des_comps;
326 int code;
327 cmm_dev_profile_t *dev_profile;
328
329 code = dev_proc(dev, get_profile)(dev, &dev_profile);
330 num_des_comps = gsicc_get_device_profile_comps(dev_profile);
331 rendering_params.black_point_comp = BP_ON;
332 rendering_params.graphics_type_tag = dev->graphics_type_tag;
333 /* Need to figure out which one rules here on rendering intent. The
334 source of the device */
335 rendering_params.rendering_intent = pis->renderingintent;
336
337 /* Need to clear out psrc_cm in case we have separation bands that are
338 not color managed */
339 memset(psrc_cm,0,sizeof(unsigned short)*GS_CLIENT_COLOR_MAX_COMPONENTS);
340
341 /* This needs to be optimized */
342 if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB ||
343 pcs->cmm_icc_profile_data->islab) {
344 psrc[0] = (unsigned short) (pcc->paint.values[0]*65535.0/100.0);
345 psrc[1] = (unsigned short) ((pcc->paint.values[1]+128)/255.0*65535.0);
346 psrc[2] = (unsigned short) ((pcc->paint.values[2]+128)/255.0*65535.0);
347 } else {
348 for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++){
349 psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
350 }
351 }
352 /* Get a link from the cache, or create if it is not there. Need to get 16 bit profile */
353 icc_link = gsicc_get_link(pis, dev, pcs, NULL, &rendering_params, pis->memory);
354 if (icc_link == NULL) {
355 return gs_rethrow(-1, "Could not create ICC link: Check profiles");
356 }
357 if (icc_link->is_identity) {
358 psrc_temp = &(psrc[0]);
359 } else {
360 /* Transform the color */
361 psrc_temp = &(psrc_cm[0]);
362 (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
363 }
364 #ifdef DEBUG
365 if (!icc_link->is_identity) {
366 num_src_comps = pcs->cmm_icc_profile_data->num_comps;
367 if_debug0(gs_debug_flag_icc,"[icc] remap [ ");
368 for (k = 0; k < num_src_comps; k++) {
369 if_debug1(gs_debug_flag_icc, "%d ",psrc[k]);
370 }
371 if_debug0(gs_debug_flag_icc,"] --> [ ");
372 for (k = 0; k < num_des_comps; k++) {
373 if_debug1(gs_debug_flag_icc, "%d ",psrc_temp[k]);
374 }
375 if_debug0(gs_debug_flag_icc,"]\n");
376 }
377 #endif
378 /* Release the link */
379 gsicc_release_link(icc_link);
380 /* Now do the remap for ICC which amounts to the alpha application
381 the transfer function and potentially the halftoning */
382 /* Right now we need to go from unsigned short to frac. I really
383 would like to avoid this sort of stuff. That will come. */
384 for ( k = 0; k < num_des_comps; k++){
385 conc[k] = ushort2frac(psrc_temp[k]);
386 }
387 gx_remap_concrete_ICC(conc, pcs, pdc, pis, dev, select);
388
389 /* Save original color space and color info into dev color */
390 i = pcs->cmm_icc_profile_data->num_comps;
391 for (i--; i >= 0; i--)
392 pdc->ccolor.paint.values[i] = pcc->paint.values[i];
393 pdc->ccolor_valid = true;
394 return 0;
395 }
396
397 /*
398 * Same as above, but there is no rescale of CIELAB colors. This is needed
399 since the rescale is not needed when the source data is image based.
400 The DeviceN image rendering case uses the remap proc vs. the ICC based method
401 which handles the remapping itself.
402 */
403 int
gx_remap_ICC_imagelab(const gs_client_color * pcc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)404 gx_remap_ICC_imagelab(const gs_client_color * pcc, const gs_color_space * pcs,
405 gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
406 gs_color_select_t select)
407 {
408 gsicc_link_t *icc_link;
409 gsicc_rendering_param_t rendering_params;
410 unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
411 unsigned short *psrc_temp;
412 frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
413 int k,i;
414 int num_des_comps;
415 int code;
416 cmm_dev_profile_t *dev_profile;
417
418 code = dev_proc(dev, get_profile)(dev, &dev_profile);
419 num_des_comps = gsicc_get_device_profile_comps(dev_profile);
420 rendering_params.black_point_comp = BP_ON;
421 rendering_params.graphics_type_tag = dev->graphics_type_tag;
422 /* Need to figure out which one rules here on rendering intent. The
423 source of the device */
424 rendering_params.rendering_intent = pis->renderingintent;
425
426 /* Need to clear out psrc_cm in case we have separation bands that are
427 not color managed */
428 memset(psrc_cm,0,sizeof(unsigned short)*GS_CLIENT_COLOR_MAX_COMPONENTS);
429
430 for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++)
431 psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
432
433 /* Get a link from the cache, or create if it is not there. Need to get 16 bit profile */
434 icc_link = gsicc_get_link(pis, dev, pcs, NULL, &rendering_params, pis->memory);
435 if (icc_link == NULL) {
436 return gs_rethrow(-1, "Could not create ICC link: Check profiles");
437 }
438 if (icc_link->is_identity) {
439 psrc_temp = &(psrc[0]);
440 } else {
441 /* Transform the color */
442 psrc_temp = &(psrc_cm[0]);
443 (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
444 }
445 /* Release the link */
446 gsicc_release_link(icc_link);
447 /* Now do the remap for ICC which amounts to the alpha application
448 the transfer function and potentially the halftoning */
449 /* Right now we need to go from unsigned short to frac. I really
450 would like to avoid this sort of stuff. That will come. */
451 for ( k = 0; k < num_des_comps; k++){
452 conc[k] = ushort2frac(psrc_temp[k]);
453 }
454 gx_remap_concrete_ICC(conc, pcs, pdc, pis, dev, select);
455
456 /* Save original color space and color info into dev color */
457 i = pcs->cmm_icc_profile_data->num_comps;
458 for (i--; i >= 0; i--)
459 pdc->ccolor.paint.values[i] = pcc->paint.values[i];
460 pdc->ccolor_valid = true;
461 return 0;
462 }
463
464 /* Convert an ICCBased color space to a concrete color space. */
465
466 static int
gx_concretize_ICC(const gs_client_color * pcc,const gs_color_space * pcs,frac * pconc,const gs_imager_state * pis,gx_device * dev)467 gx_concretize_ICC(
468 const gs_client_color * pcc,
469 const gs_color_space * pcs,
470 frac * pconc,
471 const gs_imager_state * pis,
472 gx_device *dev)
473 {
474
475 gsicc_link_t *icc_link;
476 gsicc_rendering_param_t rendering_params;
477 unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
478 int k;
479 unsigned short *psrc_temp;
480 int num_des_comps;
481 int code;
482 cmm_dev_profile_t *dev_profile;
483
484 code = dev_proc(dev, get_profile)(dev, &dev_profile);
485 num_des_comps = gsicc_get_device_profile_comps(dev_profile);
486 /* Define the rendering intents. MJV to fix */
487 rendering_params.black_point_comp = BP_ON;
488 rendering_params.graphics_type_tag = dev->graphics_type_tag;
489 rendering_params.rendering_intent = pis->renderingintent;
490 for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++) {
491 psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
492 }
493 /* Get a link from the cache, or create if it is not there. Get 16 bit profile */
494 icc_link = gsicc_get_link(pis, dev, pcs, NULL, &rendering_params, pis->memory);
495 if (icc_link == NULL) {
496 return gs_rethrow(-1, "Could not create ICC link: Check profiles");
497 }
498 /* Transform the color */
499 if (icc_link->is_identity) {
500 psrc_temp = &(psrc[0]);
501 } else {
502 /* Transform the color */
503 psrc_temp = &(psrc_cm[0]);
504 (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
505 }
506 /* This needs to be optimized */
507 for (k = 0; k < num_des_comps; k++){
508 pconc[k] = float2frac(((float) psrc_temp[k])/65535.0);
509 }
510 /* Release the link */
511 gsicc_release_link(icc_link);
512 return 0;
513 }
514
515 /*
516 * Finalize the contents of an ICC color space. Now that color space
517 * objects have straightforward reference counting discipline, there's
518 * nothing special about it. In the previous state of affairs, the
519 * argument in favor of correct reference counting spoke of "an
520 * unintuitive but otherwise legitimate state of affairs".
521 */
522 static void
gx_final_ICC(const gs_color_space * pcs)523 gx_final_ICC(const gs_color_space * pcs)
524 {
525 if (pcs->cmm_icc_profile_data != NULL) {
526 rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_ICC");
527 }
528 }
529
530 /*
531 * Install an ICCBased color space.
532 *
533 * Note that an ICCBased color space must be installed before it is known if
534 * the ICC profile or the alternate color space is to be used.
535 */
536 static int
gx_install_ICC(gs_color_space * pcs,gs_state * pgs)537 gx_install_ICC(gs_color_space * pcs, gs_state * pgs)
538 {
539 /* update the stub information used by the joint caches */
540 return 0;
541 }
542
543 /*
544 * Constructor for ICCBased color space. As with the other color space
545 * constructors, this provides only minimal initialization.
546 */
547 int
gs_cspace_build_ICC(gs_color_space ** ppcspace,void * client_data,gs_memory_t * pmem)548 gs_cspace_build_ICC(
549 gs_color_space ** ppcspace,
550 void * client_data,
551 gs_memory_t * pmem )
552 {
553 gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC);
554 *ppcspace = pcspace;
555
556 return 0;
557 }
558
559 /* ---------------- Serialization. -------------------------------- */
560
561 static int
gx_serialize_ICC(const gs_color_space * pcs,stream * s)562 gx_serialize_ICC(const gs_color_space * pcs, stream * s)
563 {
564 gsicc_serialized_profile_t *profile__serial;
565 uint n;
566 int code = gx_serialize_cspace_type(pcs, s);
567
568 if (code < 0)
569 return code;
570 profile__serial = (gsicc_serialized_profile_t*) pcs->cmm_icc_profile_data;
571 code = sputs(s, (byte *)profile__serial, sizeof(gsicc_serialized_profile_t), &n);
572 return(code);
573 }
574
575 /* Overprint. Here we may have either spot colors or CMYK colors. */
576 static int
gx_set_overprint_ICC(const gs_color_space * pcs,gs_state * pgs)577 gx_set_overprint_ICC(const gs_color_space * pcs, gs_state * pgs)
578 {
579 gx_device * dev = pgs->device;
580 gx_device_color_info * pcinfo = (dev == 0 ? 0 : &dev->color_info);
581
582 /* check if we require special handling */
583 if ( !pgs->overprint ||
584 pgs->overprint_mode != 1 ||
585 pcinfo == 0 ||
586 pcs->cmm_icc_profile_data->data_cs != gsCMYK ||
587 pcinfo->opmode == GX_CINFO_OPMODE_NOT )
588 return gx_spot_colors_set_overprint(pcs, pgs);
589
590 if (pcinfo->opmode == GX_CINFO_OPMODE_RGB ||
591 pcinfo->opmode == GC_CINFO_OPMODE_RGB_SET) {
592 return gx_set_overprint_rgb(pcs, pgs);
593 } else {
594 return gx_set_overprint_cmyk(pcs, pgs);
595 }
596 }
597
598 int
gx_default_get_profile(gx_device * dev,cmm_dev_profile_t ** profile)599 gx_default_get_profile(gx_device *dev, cmm_dev_profile_t **profile)
600 {
601 *profile = dev->icc_struct;
602 return 0;
603 }
604