1 /* Copyright (C) 2001 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zicc.c,v 1.7 2004/08/04 19:36:13 stefan Exp $ */
18 /* ICCBased color operators */
19
20 #include "math_.h"
21 #include "memory_.h"
22 #include "ghost.h"
23 #include "oper.h"
24 #include "gsstruct.h"
25 #include "gxcspace.h" /* gscolor2.h requires gscspace.h */
26 #include "stream.h"
27 #include "files.h"
28 #include "gscolor2.h"
29 #include "gsicc.h"
30 #include "estack.h"
31 #include "idict.h"
32 #include "idparam.h"
33 #include "igstate.h"
34 #include "icie.h"
35 #include "ialloc.h"
36
37 /*
38 * <dict> .seticcspace -
39 *
40 * Create an ICCBased color space and set it to be the current color space.
41 *
42 * The PostScript structure of an ICCBased color space is that same as that
43 * for a CIEBased* color space:
44 *
45 * [ /ICCBased <dictionary> ]
46 *
47 * As is the for other .setcie*space operators, the operand dictionary rather
48 * than the complete color space array is on the stack when this operator
49 * is inovked.
50 *
51 * At the time this procedure is called, the alternative color space for
52 * the ICCBased color space is expected to be the current color space,
53 * whether that space was explicitly specified or implied by the number
54 * of components in the ICCBased color space dictionary. This is consistent
55 * with the handling of alternative spaces in Separation, DeviceN, and
56 * Indexed color spaces. Unlike the "zset*space" routines for those spaces,
57 * however, the current code does not attempt to build the color space
58 * "in place" in the graphic state.
59 *
60 * The procedure that invokes this operator will already have checked that
61 * the operand is a dictionary, is readable, and defines the key /N
62 * (number of components).
63 */
64 private int
zseticcspace(i_ctx_t * i_ctx_p)65 zseticcspace(i_ctx_t * i_ctx_p)
66 {
67 os_ptr op = osp;
68 int edepth = ref_stack_count(&e_stack);
69 int code;
70 gs_color_space * pcs;
71 const gs_color_space * palt_cs;
72 ref * pnval;
73 ref * pstrmval;
74 stream * s;
75 int i, ncomps;
76 gs_cie_icc * picc_info;
77 float range_buff[8];
78 static const float dflt_range[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
79
80 dict_find_string(op, "N", &pnval);
81 ncomps = pnval->value.intval;
82
83 /* verify the DataSource entry */
84 if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
85 return_error(e_undefined);
86 check_read_file(s, pstrmval);
87
88 /*
89 * Verify that the current color space can be a alternative color space.
90 * The check for ICCBased color space is a hack to avoid introducing yet
91 * another category indicator into the gs_color_space_type structur.
92 */
93 palt_cs = gs_currentcolorspace(igs);
94 if ( !palt_cs->type->can_be_alt_space ||
95 gs_color_space_get_index(palt_cs) == gs_color_space_index_CIEICC )
96 return_error(e_rangecheck);
97
98 /*
99 * Fetch and verify the Range array.
100 *
101 * The PDF documentation is unclear as to the purpose of this array.
102 * Essentially all that is stated is that "These values must match the
103 * information in the ICC profile" (PDF Reference, 2nd ed., p. 174).
104 * If that is the case, why not use the information in the profile?
105 * The only reason we can think of is range specification is intended
106 * to be used to limit the range of values passed to the alternate
107 * color space (the range may be smaller than the native range of values
108 * provided by that color space).
109 *
110 * Because the icclib code will perform normalization based on color
111 * space, we use the range values only to restrict the set of input
112 * values; they are not used for normalization.
113 */
114 code = dict_floats_param( imemory,
115 op,
116 "Range",
117 2 * ncomps,
118 range_buff,
119 dflt_range );
120 for (i = 0; i < 2 * ncomps && range_buff[i + 1] >= range_buff[i]; i += 2)
121 ;
122 if (i != 2 * ncomps)
123 return_error(e_rangecheck);
124
125 /* build the color space object */
126 code = gs_cspace_build_CIEICC(&pcs, NULL, gs_state_memory(igs));
127 if (code < 0)
128 return code;
129 picc_info = pcs->params.icc.picc_info;
130 picc_info->num_components = ncomps;
131 picc_info->instrp = s;
132 picc_info->file_id = (s->read_id | s->write_id);
133 for (i = 0; i < ncomps; i++) {
134 picc_info->Range.ranges[i].rmin = range_buff[2 * i];
135 picc_info->Range.ranges[i].rmax = range_buff[2 * i + 1];
136
137 }
138
139 /* record the current space as the alternative color space */
140 memmove( &pcs->params.icc.alt_space,
141 palt_cs,
142 sizeof(pcs->params.icc.alt_space) );
143 /*
144 * Increment reference counts for current cspace since it is the
145 * alternate color space for the ICC space.
146 */
147 gx_increment_cspace_count(palt_cs);
148
149 code = gx_load_icc_profile(picc_info);
150 if (code < 0)
151 return code;
152
153 code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs,
154 (gs_cie_common *)picc_info, igs);
155 if (code < 0)
156 return code;
157
158 return cie_set_finish( i_ctx_p,
159 pcs,
160 &istate->colorspace.procs.cie,
161 edepth,
162 code );
163 }
164
165
166 const op_def zicc_ll3_op_defs[] = {
167 op_def_begin_ll3(),
168 { "1.seticcspace", zseticcspace },
169 op_def_end(0)
170 };
171