1 /* Copyright (C) 2001-2019 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., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* ICCBased color operators */
18
19 #include "math_.h"
20 #include "memory_.h"
21 #include "ghost.h"
22 #include "oper.h"
23 #include "gsstruct.h"
24 #include "gxcspace.h" /* gscolor2.h requires gscspace.h */
25 #include "stream.h"
26 #include "files.h"
27 #include "gscolor2.h"
28 #include "gsicc.h"
29 #include "estack.h"
30 #include "idict.h"
31 #include "idparam.h"
32 #include "igstate.h"
33 #include "icie.h"
34 #include "ialloc.h"
35 #include "store.h"
36 #include "zicc.h"
37 #include "gsicc_manage.h"
38 #include "gx.h"
39 #include "gxgstate.h"
40 #include "gsicc_create.h"
41 #include "gsicc_profilecache.h"
42 #include "gxdevice.h" /* for output intent setting */
43 #include "gsicc_cache.h"
44
seticc(i_ctx_t * i_ctx_p,int ncomps,ref * ICCdict,float * range_buff)45 int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
46 {
47 int code, k;
48 gs_color_space * pcs;
49 ref * pstrmval;
50 ref * phashval = NULL;
51 stream * s = 0L;
52 cmm_profile_t *picc_profile = NULL;
53 int i, expected = 0;
54 ref * pnameval;
55 static const char *const icc_std_profile_names[] = {
56 GSICC_STANDARD_PROFILES
57 };
58 static const char *const icc_std_profile_keys[] = {
59 GSICC_STANDARD_PROFILES_KEYS
60 };
61
62 /* If we are override ICC mode, we won't use the profile */
63 if (!gs_currentoverrideicc(igs) &&
64 dict_find_string(ICCdict, ".hash", &phashval) == 1 &&
65 r_has_type(phashval, t_integer)) {
66 pcs = gsicc_find_cs(phashval->value.intval, igs);
67 if (pcs != NULL) {
68 /* Set the color space. We are done. */
69 code = gs_setcolorspace(igs, pcs);
70 /* Remove the ICC dict from the stack */
71 pop(1);
72 return code;
73 }
74 }
75
76 /* verify the DataSource entry */
77 if (dict_find_string(ICCdict, "DataSource", &pstrmval) <= 0)
78 return_error(gs_error_undefined);
79 check_read_file(i_ctx_p, s, pstrmval);
80
81 /* build the color space object */
82 code = gs_cspace_build_ICC(&pcs, NULL, gs_gstate_memory(igs)->stable_memory);
83 if (code < 0)
84 return gs_rethrow(code, "building color space object");
85 /* For now, dump the profile into a buffer
86 and obtain handle from the buffer when we need it.
87 We may want to change this later.
88 This depends to some degree on what the CMS is capable of doing.
89 I don't want to get bogged down on stream I/O at this point.
90 Note also, if we are going to be putting these into the clist we will
91 want to have this buffer. */
92 /* Check if we have the /Name entry. This is used to associate with
93 specs that have enumerated types to indicate sRGB sGray etc */
94 if (dict_find_string(ICCdict, "Name", &pnameval) > 0 && r_has_type(pnameval, t_string)){
95 uint size = r_size(pnameval);
96 char *str = (char *)gs_alloc_bytes(gs_gstate_memory(igs), size+1, "seticc");
97 memcpy(str, (const char *)pnameval->value.bytes, size);
98 str[size] = 0;
99
100 /* Compare this to the standard profile names */
101 for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
102 if ( strcmp( str, icc_std_profile_keys[k] ) == 0 ) {
103 picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
104 strlen(icc_std_profile_names[k]), gs_gstate_memory(igs));
105 break;
106 }
107 }
108 gs_free_object(gs_gstate_memory(igs), str, "seticc");
109 } else {
110 picc_profile = gsicc_profile_new(s, gs_gstate_memory(igs), NULL, 0);
111 if (picc_profile == NULL)
112 return gs_throw(gs_error_VMerror, "Creation of ICC profile failed");
113 /* We have to get the profile handle due to the fact that we need to know
114 if it has a data space that is CIELAB */
115 picc_profile->profile_handle =
116 gsicc_get_profile_handle_buffer(picc_profile->buffer,
117 picc_profile->buffer_size,
118 gs_gstate_memory(igs));
119 }
120 if (picc_profile == NULL || picc_profile->profile_handle == NULL) {
121 /* Free up everything, the profile is not valid. We will end up going
122 ahead and using a default based upon the number of components */
123 rc_decrement(picc_profile,"seticc");
124 rc_decrement(pcs,"seticc");
125 return -1;
126 }
127 code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(igs));
128 if (code < 0) {
129 rc_decrement(picc_profile,"seticc");
130 rc_decrement(pcs,"seticc");
131 return code;
132 }
133 picc_profile->num_comps = ncomps;
134
135 picc_profile->data_cs =
136 gscms_get_profile_data_space(picc_profile->profile_handle,
137 picc_profile->memory);
138 switch (picc_profile->data_cs) {
139 case gsCIEXYZ:
140 case gsCIELAB:
141 case gsRGB:
142 expected = 3;
143 break;
144 case gsGRAY:
145 expected = 1;
146 break;
147 case gsCMYK:
148 expected = 4;
149 break;
150 case gsNCHANNEL:
151 case gsNAMED: /* Silence warnings */
152 case gsUNDEFINED: /* Silence warnings */
153 break;
154 }
155 if (!expected || ncomps != expected) {
156 rc_decrement(picc_profile,"seticc");
157 rc_decrement(pcs,"seticc");
158 return_error(gs_error_rangecheck);
159 }
160
161 /* Lets go ahead and get the hash code and check if we match one of the default spaces */
162 /* Later we may want to delay this, but for now lets go ahead and do it */
163 gsicc_init_hash_cs(picc_profile, igs);
164
165 /* Set the range according to the data type that is associated with the
166 ICC input color type. Occasionally, we will run into CIELAB to CIELAB
167 profiles for spot colors in PDF documents. These spot colors are typically described
168 as separation colors with tint transforms that go from a tint value
169 to a linear mapping between the CIELAB white point and the CIELAB tint
170 color. This results in a CIELAB value that we need to use to fill. We
171 need to detect this to make sure we do the proper scaling of the data. For
172 CIELAB images in PDF, the source is always normal 8 or 16 bit encoded data
173 in the range from 0 to 255 or 0 to 65535. In that case, there should not
174 be any encoding and decoding to CIELAB. The PDF content will not include
175 an ICC profile but will set the color space to \Lab. In this case, we use
176 our seticc_lab operation to install the LAB to LAB profile, but we detect
177 that we did that through the use of the is_lab flag in the profile descriptor.
178 When then avoid the CIELAB encode and decode */
179 if (picc_profile->data_cs == gsCIELAB) {
180 /* If the input space to this profile is CIELAB, then we need to adjust the limits */
181 /* See ICC spec ICC.1:2004-10 Section 6.3.4.2 and 6.4. I don't believe we need to
182 worry about CIEXYZ profiles or any of the other odds ones. Need to check that though
183 at some point. */
184 picc_profile->Range.ranges[0].rmin = 0.0;
185 picc_profile->Range.ranges[0].rmax = 100.0;
186 picc_profile->Range.ranges[1].rmin = -128.0;
187 picc_profile->Range.ranges[1].rmax = 127.0;
188 picc_profile->Range.ranges[2].rmin = -128.0;
189 picc_profile->Range.ranges[2].rmax = 127.0;
190 picc_profile->islab = true;
191 } else {
192 for (i = 0; i < ncomps; i++) {
193 picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
194 picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
195 }
196 }
197 /* Now see if we are in an overide situation. We have to wait until now
198 in case this is an LAB profile which we will not overide */
199 if (gs_currentoverrideicc(igs) && picc_profile->data_cs != gsCIELAB) {
200 /* Free up the profile structure */
201 switch( picc_profile->data_cs ) {
202 case gsRGB:
203 pcs->cmm_icc_profile_data = igs->icc_manager->default_rgb;
204 break;
205 case gsGRAY:
206 pcs->cmm_icc_profile_data = igs->icc_manager->default_gray;
207 break;
208 case gsCMYK:
209 pcs->cmm_icc_profile_data = igs->icc_manager->default_cmyk;
210 break;
211 default:
212 break;
213 }
214 /* Have one increment from the color space. Having these tied
215 together is not really correct. Need to fix that. ToDo. MJV */
216 rc_adjust(picc_profile, -2, "seticc"); /* NB: May free the profile and set picc_profile to 0 */
217 rc_increment(pcs->cmm_icc_profile_data);
218 }
219 /* Set the color space. We are done. */
220 code = gs_setcolorspace(igs, pcs);
221 /* The context has taken a reference to the colorspace. We no longer need
222 * ours, so drop it. */
223 rc_decrement_only(pcs, "seticc");
224 if (picc_profile != NULL) {
225 /* In this case, we already have a ref count of 2 on the icc profile
226 one for when it was created and one for when it was set. We really
227 only want one here so adjust */
228 rc_decrement(picc_profile,"seticc");
229 if (code >= 0) {
230 /* Save this colorspace in the iccprofile_cache */
231 gsicc_add_cs(igs, pcs, picc_profile->hashcode);
232 /* should be an integer, but if for some reason it isn't, don't update */
233 if (phashval && r_has_type(phashval, t_integer))
234 phashval->value.intval = picc_profile->hashcode;
235 }
236 }
237 /* Remove the ICC dict from the stack */
238 pop(1);
239 return code;
240 }
241
242 /*
243 * <dict> .set_outputintent -
244 *
245 * Set and use the specified output intent.
246 *
247 */
248 static int
zset_outputintent(i_ctx_t * i_ctx_p)249 zset_outputintent(i_ctx_t * i_ctx_p)
250 {
251 os_ptr op = osp;
252 int code = 0;
253 gx_device *dev = gs_currentdevice(igs);
254 cmm_dev_profile_t *dev_profile;
255 stream * s = 0L;
256 ref * pnval;
257 ref * pstrmval;
258 int ncomps, dev_comps;
259 cmm_profile_t *picc_profile;
260 int expected = 0;
261 gs_color_space_index index;
262 gsicc_manager_t *icc_manager = igs->icc_manager;
263 cmm_profile_t *source_profile = NULL;
264
265 check_type(*op, t_dictionary);
266 check_dict_read(*op);
267 if_debug0m(gs_debug_flag_icc, imemory, "[icc] Using OutputIntent\n");
268
269 /* Get the device structure */
270 code = dev_proc(dev, get_profile)(dev, &dev_profile);
271 if (code < 0)
272 return code;
273
274 if (dev_profile == NULL) {
275 code = gsicc_init_device_profile_struct(dev, NULL, 0);
276 if (code < 0)
277 return code;
278 code = dev_proc(dev, get_profile)(dev, &dev_profile);
279 if (code < 0)
280 return code;
281 }
282 if (dev_profile->oi_profile != NULL) {
283 return 0; /* Allow only one setting of this object */
284 }
285 code = dict_find_string(op, "N", &pnval);
286 if (code < 0)
287 return code;
288 if (code == 0)
289 return_error(gs_error_undefined);
290 if (r_type(pnval) != t_integer)
291 return gs_note_error(gs_error_typecheck);
292 ncomps = pnval->value.intval;
293
294 /* verify the DataSource entry. Creat profile from stream */
295 if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
296 return_error(gs_error_undefined);
297 check_read_file(i_ctx_p, s, pstrmval);
298
299 picc_profile = gsicc_profile_new(s, gs_gstate_memory(igs), NULL, 0);
300 if (picc_profile == NULL)
301 return gs_throw(gs_error_VMerror, "Creation of ICC profile failed");
302 picc_profile->num_comps = ncomps;
303 picc_profile->profile_handle =
304 gsicc_get_profile_handle_buffer(picc_profile->buffer,
305 picc_profile->buffer_size,
306 gs_gstate_memory(igs));
307 if (picc_profile->profile_handle == NULL) {
308 rc_decrement(picc_profile,"zset_outputintent");
309 return -1;
310 }
311 picc_profile->data_cs =
312 gscms_get_profile_data_space(picc_profile->profile_handle,
313 picc_profile->memory);
314 switch (picc_profile->data_cs) {
315 case gsCIEXYZ:
316 case gsCIELAB:
317 case gsRGB:
318 expected = 3;
319 source_profile = icc_manager->default_rgb;
320 break;
321 case gsGRAY:
322 expected = 1;
323 source_profile = icc_manager->default_gray;
324 break;
325 case gsCMYK:
326 expected = 4;
327 source_profile = icc_manager->default_cmyk;
328 break;
329 case gsNCHANNEL:
330 expected = 0;
331 break;
332 case gsNAMED:
333 case gsUNDEFINED:
334 break;
335 }
336 if (expected && ncomps != expected) {
337 rc_decrement(picc_profile,"zset_outputintent");
338 return_error(gs_error_rangecheck);
339 }
340 gsicc_init_hash_cs(picc_profile, igs);
341
342 /* All is well with the profile. Lets set the stuff that needs to be set */
343 dev_profile->oi_profile = picc_profile;
344 picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
345 MAX_DEFAULT_ICC_LENGTH,
346 "zset_outputintent");
347 strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
348 picc_profile->name[strlen(OI_PROFILE)] = 0;
349 picc_profile->name_length = strlen(OI_PROFILE);
350 /* Set the range of the profile */
351 gsicc_set_icc_range(&picc_profile);
352
353 /* If the output device has a different number of componenets, then we are
354 going to set the output intent as the proofing profile, unless the
355 proofing profile has already been set.
356
357 If the device has the same number of components (and color model) then as
358 the profile we will use this as the output profile, unless someone has
359 explicitly set the output profile.
360
361 Finally, we will use the output intent profile for the default profile
362 of the proper Device profile in the icc manager, again, unless someone
363 has explicitly set this default profile. */
364
365 dev_comps = dev_profile->device_profile[0]->num_comps;
366 index = gsicc_get_default_type(dev_profile->device_profile[0]);
367 if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
368 /* The OI profile is the same type as the profile for the device and a
369 "default" profile for the device was not externally set. So we go
370 ahead and use the OI profile as the device profile. Care needs to be
371 taken here to keep from screwing up any device parameters. We will
372 use a keyword of OIProfile for the user/device parameter to indicate
373 its usage. Also, note conflicts if one is setting object dependent
374 color management */
375 rc_assign(dev_profile->device_profile[0], picc_profile,
376 "zset_outputintent");
377 if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used for device profile\n");
378 } else {
379 if (dev_profile->proof_profile == NULL) {
380 /* This means that we should use the OI profile as the proofing
381 profile. Note that if someone already has specified a
382 proofing profile it is unclear what they are trying to do
383 with the output intent. In this case, we will use it
384 just for the source data below */
385 dev_profile->proof_profile = picc_profile;
386 rc_increment(picc_profile);
387 if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used for proof profile\n");
388 }
389 }
390 /* Now the source colors. See which source color space needs to use the
391 output intent ICC profile */
392 index = gsicc_get_default_type(source_profile);
393 if (index < gs_color_space_index_DevicePixel) {
394 /* source_profile is currently the default. Set it to the OI profile */
395 switch (picc_profile->data_cs) {
396 case gsGRAY:
397 if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source Gray\n");
398 rc_assign(icc_manager->default_gray, picc_profile,
399 "zset_outputintent");
400 break;
401 case gsRGB:
402 if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source RGB\n");
403 rc_assign(icc_manager->default_rgb, picc_profile,
404 "zset_outputintent");
405 break;
406 case gsCMYK:
407 if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source CMYK\n");
408 rc_assign(icc_manager->default_cmyk, picc_profile,
409 "zset_outputintent");
410 break;
411 default:
412 break;
413 }
414 }
415 /* Remove the output intent dict from the stack */
416 pop(1);
417 return code;
418 }
419
420 /* Install a ICC type color space and use the ICC LABLUT profile. */
421 int
seticc_lab(i_ctx_t * i_ctx_p,float * white,float * black,float * range_buff)422 seticc_lab(i_ctx_t * i_ctx_p, float *white, float *black, float *range_buff)
423 {
424 int code;
425 gs_color_space * pcs;
426 int i;
427
428 /* build the color space object */
429 code = gs_cspace_build_ICC(&pcs, NULL, gs_gstate_memory(igs));
430 if (code < 0)
431 return gs_rethrow(code, "building color space object");
432 /* record the current space as the alternative color space */
433 /* Get the lab profile. It may already be set in the icc manager.
434 If not then lets populate it. */
435 if (igs->icc_manager->lab_profile == NULL ) {
436 /* This can't happen as the profile
437 should be initialized during the
438 setting of the user params */
439 return gs_rethrow(code, "cannot find lab icc profile");
440 }
441 /* Assign the LAB to LAB profile to this color space */
442 code = gsicc_set_gscs_profile(pcs, igs->icc_manager->lab_profile, gs_gstate_memory(igs));
443 if (code < 0)
444 return gs_rethrow(code, "installing the lab profile");
445 pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
446 pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
447 for (i = 1; i < 3; i++) {
448 pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
449 range_buff[2 * (i-1)];
450 pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
451 range_buff[2 * (i-1) + 1];
452 }
453 /* Set the color space. We are done. */
454 code = gs_setcolorspace(igs, pcs);
455 return code;
456 }
457
458 /* Install an ICC space from the PDF CalRGB or CalGray types */
459 int
seticc_cal(i_ctx_t * i_ctx_p,float * white,float * black,float * gamma,float * matrix,int num_colorants,ulong dictkey)460 seticc_cal(i_ctx_t * i_ctx_p, float *white, float *black, float *gamma,
461 float *matrix, int num_colorants, ulong dictkey)
462 {
463 int code;
464 gs_color_space * pcs;
465 gs_memory_t *mem = igs->memory;
466 int i;
467 cmm_profile_t *cal_profile;
468
469 /* See if the color space is in the profile cache */
470 pcs = gsicc_find_cs(dictkey, igs);
471 if (pcs == NULL ) {
472 /* build the color space object. Since this is cached
473 in the profile cache which is a member variable
474 of the graphic state, we will want to use stable
475 memory here */
476 code = gs_cspace_build_ICC(&pcs, NULL, mem->stable_memory);
477 if (code < 0)
478 return gs_rethrow(code, "building color space object");
479 /* There is no alternate for this. Perhaps we should set DeviceRGB? */
480 pcs->base_space = NULL;
481 /* Create the ICC profile from the CalRGB or CalGray parameters */
482 cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
483 mem->stable_memory, num_colorants);
484 if (cal_profile == NULL)
485 return gs_rethrow(gs_error_VMerror, "creating the cal profile failed");
486 /* Assign the profile to this color space */
487 code = gsicc_set_gscs_profile(pcs, cal_profile, mem->stable_memory);
488 /* profile is created with ref count of 1, gsicc_set_gscs_profile()
489 * increments the ref count, so we need to decrement it here.
490 */
491 rc_decrement(cal_profile, "seticc_cal");
492 if (code < 0)
493 return gs_rethrow(code, "installing the cal profile");
494 for (i = 0; i < num_colorants; i++) {
495 pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
496 pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
497 }
498 /* Add the color space to the profile cache */
499 gsicc_add_cs(igs, pcs,dictkey);
500 }
501 /* Set the color space. We are done. */
502 code = gs_setcolorspace(igs, pcs);
503 return code;
504 }
505
506 static int
znumicc_components(i_ctx_t * i_ctx_p)507 znumicc_components(i_ctx_t * i_ctx_p)
508 {
509 ref * pnval;
510 ref * pstrmval;
511 stream * s;
512 int ncomps, expected = 0, code;
513 cmm_profile_t *picc_profile;
514 os_ptr op = osp;
515
516 check_type(*op, t_dictionary);
517 check_dict_read(*op);
518
519 code = dict_find_string(op, "N", &pnval);
520 if (code < 0)
521 return code;
522 if (code == 0)
523 return_error(gs_error_undefined);
524 if (r_type(pnval) != t_integer)
525 return gs_note_error(gs_error_typecheck);
526 ncomps = pnval->value.intval;
527 /* verify the DataSource entry. Create profile from stream */
528 if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
529 return_error(gs_error_undefined);
530 check_read_file(i_ctx_p, s, pstrmval);
531
532 picc_profile = gsicc_profile_new(s, gs_gstate_memory(igs), NULL, 0);
533 if (picc_profile == NULL)
534 return gs_throw(gs_error_VMerror, "Creation of ICC profile failed");
535
536 picc_profile->num_comps = ncomps;
537 picc_profile->profile_handle =
538 gsicc_get_profile_handle_buffer(picc_profile->buffer,
539 picc_profile->buffer_size,
540 gs_gstate_memory(igs));
541 if (picc_profile->profile_handle == NULL) {
542 rc_decrement(picc_profile,"znumicc_components");
543 make_int(op, expected);
544 return 0;
545 }
546 picc_profile->data_cs =
547 gscms_get_profile_data_space(picc_profile->profile_handle,
548 picc_profile->memory);
549
550 switch (picc_profile->data_cs) {
551 case gsCIEXYZ:
552 case gsCIELAB:
553 case gsRGB:
554 expected = 3;
555 break;
556 case gsGRAY:
557 expected = 1;
558 break;
559 case gsCMYK:
560 expected = 4;
561 break;
562 case gsNCHANNEL:
563 expected = 0;
564 break;
565 case gsNAMED:
566 case gsUNDEFINED:
567 expected = -1;
568 break;
569 }
570
571 make_int(op, expected);
572
573 rc_decrement(picc_profile,"zset_outputintent");
574 return 0;
575 }
576
577 const op_def zicc_op_defs[] = {
578 { "1.set_outputintent", zset_outputintent },
579 { "1.numicc_components", znumicc_components },
580 op_def_end(0)
581 };
582