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