1 /* Copyright (C) 2001-2008 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, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: zicc.c 9380 2009-01-21 15:34:55Z ken $ */
15 /* ICCBased color operators */
16
17 #include "math_.h"
18 #include "memory_.h"
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsstruct.h"
22 #include "gxcspace.h" /* gscolor2.h requires gscspace.h */
23 #include "stream.h"
24 #include "files.h"
25 #include "gscolor2.h"
26 #include "icc.h"
27 #include "gsicc.h"
28 #include "estack.h"
29 #include "idict.h"
30 #include "idparam.h"
31 #include "igstate.h"
32 #include "icie.h"
33 #include "ialloc.h"
34 #include "zicc.h"
35
seticc(i_ctx_t * i_ctx_p,int ncomps,ref * ICCdict,float * range_buff)36 int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
37 {
38 os_ptr op = osp;
39 int edepth = ref_stack_count(&e_stack);
40 int code, reuse_op = 0;
41 gs_color_space * pcs;
42 gs_color_space * palt_cs;
43 int i;
44 gs_cie_icc * picc_info;
45 ref * pstrmval;
46 stream * s = 0L;
47
48 palt_cs = gs_currentcolorspace(igs);
49 /* verify the DataSource entry */
50 if (dict_find_string(ICCdict, "DataSource", &pstrmval) <= 0)
51 return_error(e_undefined);
52 check_read_file(s, pstrmval);
53
54 /* build the color space object */
55 code = gs_cspace_build_CIEICC(&pcs, NULL, gs_state_memory(igs));
56 if (code < 0)
57 return code;
58 picc_info = pcs->params.icc.picc_info;
59 picc_info->num_components = ncomps;
60 picc_info->instrp = s;
61 picc_info->file_id = (s->read_id | s->write_id);
62 for (i = 0; i < ncomps; i++) {
63 picc_info->Range.ranges[i].rmin = range_buff[2 * i];
64 picc_info->Range.ranges[i].rmax = range_buff[2 * i + 1];
65
66 }
67
68 /* record the current space as the alternative color space */
69 pcs->base_space = palt_cs;
70 rc_increment(palt_cs);
71
72 code = gx_load_icc_profile(picc_info);
73 if (code < 0)
74 return code;
75
76 /* If the input space to this profile is CIELAB, then we need to adjust the limits */
77 /* See ICC spec ICC.1:2004-10 Section 6.3.4.2 and 6.4 */
78 if(picc_info->plu->e_inSpace == icSigLabData)
79 {
80 picc_info->Range.ranges[0].rmin = 0.0;
81 picc_info->Range.ranges[0].rmax = 100.0;
82
83 picc_info->Range.ranges[1].rmin = -128.0;
84 picc_info->Range.ranges[1].rmax = 127.0;
85
86 picc_info->Range.ranges[2].rmin = -128.0;
87 picc_info->Range.ranges[2].rmax = 127.0;
88
89 }
90 /* If the input space is icSigXYZData, then we should do the limits based upon the white point of the profile. */
91 if(picc_info->plu->e_inSpace == icSigXYZData)
92 {
93 for (i = 0; i < 3; i++)
94 {
95 picc_info->Range.ranges[i].rmin = 0;
96 }
97
98 picc_info->Range.ranges[0].rmax = picc_info->common.points.WhitePoint.u;
99 picc_info->Range.ranges[1].rmax = picc_info->common.points.WhitePoint.v;
100 picc_info->Range.ranges[2].rmax = picc_info->common.points.WhitePoint.w;
101 }
102
103 code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs,
104 (gs_cie_common *)picc_info, igs);
105 if (code < 0)
106 return code;
107
108 return cie_set_finish( i_ctx_p,
109 pcs,
110 &istate->colorspace.procs.cie,
111 edepth,
112 code );
113 }
114
115 /*
116 * <dict> .seticcspace -
117 *
118 * Create an ICCBased color space and set it to be the current color space.
119 *
120 * The PostScript structure of an ICCBased color space is that same as that
121 * for a CIEBased* color space:
122 *
123 * [ /ICCBased <dictionary> ]
124 *
125 * As is the for other .setcie*space operators, the operand dictionary rather
126 * than the complete color space array is on the stack when this operator
127 * is inovked.
128 *
129 * At the time this procedure is called, the alternative color space for
130 * the ICCBased color space is expected to be the current color space,
131 * whether that space was explicitly specified or implied by the number
132 * of components in the ICCBased color space dictionary. This is consistent
133 * with the handling of alternative spaces in Separation, DeviceN, and
134 * Indexed color spaces. Unlike the "zset*space" routines for those spaces,
135 * however, the current code does not attempt to build the color space
136 * "in place" in the graphic state.
137 *
138 * The procedure that invokes this operator will already have checked that
139 * the operand is a dictionary, is readable, and defines the key /N
140 * (number of components).
141 */
142 static int
zseticcspace(i_ctx_t * i_ctx_p)143 zseticcspace(i_ctx_t * i_ctx_p)
144 {
145 os_ptr op = osp;
146 int code;
147 gs_color_space * palt_cs;
148 ref * pnval;
149 ref * pstrmval;
150 stream * s;
151 int i, ncomps;
152 float range_buff[8];
153 static const float dflt_range[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
154
155 code = dict_find_string(op, "N", &pnval);
156 if (code < 0)
157 return code;
158
159 ncomps = pnval->value.intval;
160
161 if (2*ncomps > sizeof(range_buff)/sizeof(range_buff[0]))
162 return_error(e_rangecheck);
163
164 /* verify the DataSource entry */
165 if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
166 return_error(e_undefined);
167 check_read_file(s, pstrmval);
168
169 /*
170 * Verify that the current color space can be a alternative color space.
171 * The check for ICCBased color space is a hack to avoid introducing yet
172 * another category indicator into the gs_color_space_type structur.
173 */
174 palt_cs = gs_currentcolorspace(igs);
175 if ( !palt_cs->type->can_be_alt_space ||
176 gs_color_space_get_index(palt_cs) == gs_color_space_index_CIEICC )
177 return_error(e_rangecheck);
178
179 /*
180 * Fetch and verify the Range array.
181 *
182 * The PDF documentation is unclear as to the purpose of this array.
183 * Essentially all that is stated is that "These values must match the
184 * information in the ICC profile" (PDF Reference, 2nd ed., p. 174).
185 * If that is the case, why not use the information in the profile?
186 * The only reason we can think of is range specification is intended
187 * to be used to limit the range of values passed to the alternate
188 * color space (the range may be smaller than the native range of values
189 * provided by that color space).
190 *
191 * Because the icclib code will perform normalization based on color
192 * space, we use the range values only to restrict the set of input
193 * values; they are not used for normalization.
194 */
195 code = dict_floats_param( imemory,
196 op,
197 "Range",
198 2 * ncomps,
199 range_buff,
200 dflt_range );
201 for (i = 0; i < 2 * ncomps && range_buff[i + 1] >= range_buff[i]; i += 2)
202 ;
203 if (i != 2 * ncomps)
204 return_error(e_rangecheck);
205
206 return seticc(i_ctx_p, ncomps, op, range_buff);
207 }
208
209
210 const op_def zicc_ll3_op_defs[] = {
211 op_def_begin_ll3(),
212 { "1.seticcspace", zseticcspace },
213 op_def_end(0)
214 };
215