13ff48bf5SDavid du Colombier /* Copyright (C) 2001 Aladdin Enterprises. All rights reserved.
23ff48bf5SDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
53ff48bf5SDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
93ff48bf5SDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
153ff48bf5SDavid du Colombier */
163ff48bf5SDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: zicc.c,v 1.7 2004/08/04 19:36:13 stefan Exp $ */
183ff48bf5SDavid du Colombier /* ICCBased color operators */
19*593dc095SDavid du Colombier
203ff48bf5SDavid du Colombier #include "math_.h"
213ff48bf5SDavid du Colombier #include "memory_.h"
223ff48bf5SDavid du Colombier #include "ghost.h"
233ff48bf5SDavid du Colombier #include "oper.h"
243ff48bf5SDavid du Colombier #include "gsstruct.h"
253ff48bf5SDavid du Colombier #include "gxcspace.h" /* gscolor2.h requires gscspace.h */
263ff48bf5SDavid du Colombier #include "stream.h"
273ff48bf5SDavid du Colombier #include "files.h"
283ff48bf5SDavid du Colombier #include "gscolor2.h"
293ff48bf5SDavid du Colombier #include "gsicc.h"
303ff48bf5SDavid du Colombier #include "estack.h"
313ff48bf5SDavid du Colombier #include "idict.h"
323ff48bf5SDavid du Colombier #include "idparam.h"
333ff48bf5SDavid du Colombier #include "igstate.h"
343ff48bf5SDavid du Colombier #include "icie.h"
35*593dc095SDavid du Colombier #include "ialloc.h"
363ff48bf5SDavid du Colombier
373ff48bf5SDavid du Colombier /*
383ff48bf5SDavid du Colombier * <dict> .seticcspace -
393ff48bf5SDavid du Colombier *
403ff48bf5SDavid du Colombier * Create an ICCBased color space and set it to be the current color space.
413ff48bf5SDavid du Colombier *
423ff48bf5SDavid du Colombier * The PostScript structure of an ICCBased color space is that same as that
433ff48bf5SDavid du Colombier * for a CIEBased* color space:
443ff48bf5SDavid du Colombier *
453ff48bf5SDavid du Colombier * [ /ICCBased <dictionary> ]
463ff48bf5SDavid du Colombier *
473ff48bf5SDavid du Colombier * As is the for other .setcie*space operators, the operand dictionary rather
483ff48bf5SDavid du Colombier * than the complete color space array is on the stack when this operator
493ff48bf5SDavid du Colombier * is inovked.
503ff48bf5SDavid du Colombier *
513ff48bf5SDavid du Colombier * At the time this procedure is called, the alternative color space for
523ff48bf5SDavid du Colombier * the ICCBased color space is expected to be the current color space,
533ff48bf5SDavid du Colombier * whether that space was explicitly specified or implied by the number
543ff48bf5SDavid du Colombier * of components in the ICCBased color space dictionary. This is consistent
553ff48bf5SDavid du Colombier * with the handling of alternative spaces in Separation, DeviceN, and
563ff48bf5SDavid du Colombier * Indexed color spaces. Unlike the "zset*space" routines for those spaces,
573ff48bf5SDavid du Colombier * however, the current code does not attempt to build the color space
583ff48bf5SDavid du Colombier * "in place" in the graphic state.
593ff48bf5SDavid du Colombier *
603ff48bf5SDavid du Colombier * The procedure that invokes this operator will already have checked that
613ff48bf5SDavid du Colombier * the operand is a dictionary, is readable, and defines the key /N
623ff48bf5SDavid du Colombier * (number of components).
633ff48bf5SDavid du Colombier */
643ff48bf5SDavid du Colombier private int
zseticcspace(i_ctx_t * i_ctx_p)653ff48bf5SDavid du Colombier zseticcspace(i_ctx_t * i_ctx_p)
663ff48bf5SDavid du Colombier {
673ff48bf5SDavid du Colombier os_ptr op = osp;
683ff48bf5SDavid du Colombier int edepth = ref_stack_count(&e_stack);
693ff48bf5SDavid du Colombier int code;
703ff48bf5SDavid du Colombier gs_color_space * pcs;
713ff48bf5SDavid du Colombier const gs_color_space * palt_cs;
723ff48bf5SDavid du Colombier ref * pnval;
733ff48bf5SDavid du Colombier ref * pstrmval;
743ff48bf5SDavid du Colombier stream * s;
753ff48bf5SDavid du Colombier int i, ncomps;
763ff48bf5SDavid du Colombier gs_cie_icc * picc_info;
773ff48bf5SDavid du Colombier float range_buff[8];
783ff48bf5SDavid du Colombier static const float dflt_range[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
793ff48bf5SDavid du Colombier
803ff48bf5SDavid du Colombier dict_find_string(op, "N", &pnval);
813ff48bf5SDavid du Colombier ncomps = pnval->value.intval;
823ff48bf5SDavid du Colombier
833ff48bf5SDavid du Colombier /* verify the DataSource entry */
843ff48bf5SDavid du Colombier if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
853ff48bf5SDavid du Colombier return_error(e_undefined);
863ff48bf5SDavid du Colombier check_read_file(s, pstrmval);
873ff48bf5SDavid du Colombier
883ff48bf5SDavid du Colombier /*
893ff48bf5SDavid du Colombier * Verify that the current color space can be a alternative color space.
903ff48bf5SDavid du Colombier * The check for ICCBased color space is a hack to avoid introducing yet
913ff48bf5SDavid du Colombier * another category indicator into the gs_color_space_type structur.
923ff48bf5SDavid du Colombier */
933ff48bf5SDavid du Colombier palt_cs = gs_currentcolorspace(igs);
943ff48bf5SDavid du Colombier if ( !palt_cs->type->can_be_alt_space ||
953ff48bf5SDavid du Colombier gs_color_space_get_index(palt_cs) == gs_color_space_index_CIEICC )
963ff48bf5SDavid du Colombier return_error(e_rangecheck);
973ff48bf5SDavid du Colombier
983ff48bf5SDavid du Colombier /*
993ff48bf5SDavid du Colombier * Fetch and verify the Range array.
1003ff48bf5SDavid du Colombier *
1013ff48bf5SDavid du Colombier * The PDF documentation is unclear as to the purpose of this array.
1023ff48bf5SDavid du Colombier * Essentially all that is stated is that "These values must match the
1033ff48bf5SDavid du Colombier * information in the ICC profile" (PDF Reference, 2nd ed., p. 174).
1043ff48bf5SDavid du Colombier * If that is the case, why not use the information in the profile?
1053ff48bf5SDavid du Colombier * The only reason we can think of is range specification is intended
1063ff48bf5SDavid du Colombier * to be used to limit the range of values passed to the alternate
1073ff48bf5SDavid du Colombier * color space (the range may be smaller than the native range of values
1083ff48bf5SDavid du Colombier * provided by that color space).
1093ff48bf5SDavid du Colombier *
1103ff48bf5SDavid du Colombier * Because the icclib code will perform normalization based on color
1113ff48bf5SDavid du Colombier * space, we use the range values only to restrict the set of input
1123ff48bf5SDavid du Colombier * values; they are not used for normalization.
1133ff48bf5SDavid du Colombier */
114*593dc095SDavid du Colombier code = dict_floats_param( imemory,
115*593dc095SDavid du Colombier op,
1163ff48bf5SDavid du Colombier "Range",
1173ff48bf5SDavid du Colombier 2 * ncomps,
1183ff48bf5SDavid du Colombier range_buff,
1193ff48bf5SDavid du Colombier dflt_range );
1203ff48bf5SDavid du Colombier for (i = 0; i < 2 * ncomps && range_buff[i + 1] >= range_buff[i]; i += 2)
1213ff48bf5SDavid du Colombier ;
1223ff48bf5SDavid du Colombier if (i != 2 * ncomps)
1233ff48bf5SDavid du Colombier return_error(e_rangecheck);
1243ff48bf5SDavid du Colombier
1253ff48bf5SDavid du Colombier /* build the color space object */
1263ff48bf5SDavid du Colombier code = gs_cspace_build_CIEICC(&pcs, NULL, gs_state_memory(igs));
1273ff48bf5SDavid du Colombier if (code < 0)
1283ff48bf5SDavid du Colombier return code;
1293ff48bf5SDavid du Colombier picc_info = pcs->params.icc.picc_info;
1303ff48bf5SDavid du Colombier picc_info->num_components = ncomps;
1313ff48bf5SDavid du Colombier picc_info->instrp = s;
1323ff48bf5SDavid du Colombier picc_info->file_id = (s->read_id | s->write_id);
1333ff48bf5SDavid du Colombier for (i = 0; i < ncomps; i++) {
1343ff48bf5SDavid du Colombier picc_info->Range.ranges[i].rmin = range_buff[2 * i];
1353ff48bf5SDavid du Colombier picc_info->Range.ranges[i].rmax = range_buff[2 * i + 1];
1363ff48bf5SDavid du Colombier
1373ff48bf5SDavid du Colombier }
1383ff48bf5SDavid du Colombier
1393ff48bf5SDavid du Colombier /* record the current space as the alternative color space */
1403ff48bf5SDavid du Colombier memmove( &pcs->params.icc.alt_space,
1413ff48bf5SDavid du Colombier palt_cs,
1423ff48bf5SDavid du Colombier sizeof(pcs->params.icc.alt_space) );
143*593dc095SDavid du Colombier /*
144*593dc095SDavid du Colombier * Increment reference counts for current cspace since it is the
145*593dc095SDavid du Colombier * alternate color space for the ICC space.
146*593dc095SDavid du Colombier */
147*593dc095SDavid du Colombier gx_increment_cspace_count(palt_cs);
1483ff48bf5SDavid du Colombier
1493ff48bf5SDavid du Colombier code = gx_load_icc_profile(picc_info);
1503ff48bf5SDavid du Colombier if (code < 0)
1513ff48bf5SDavid du Colombier return code;
1523ff48bf5SDavid du Colombier
1533ff48bf5SDavid du Colombier code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs,
1543ff48bf5SDavid du Colombier (gs_cie_common *)picc_info, igs);
1553ff48bf5SDavid du Colombier if (code < 0)
1563ff48bf5SDavid du Colombier return code;
1573ff48bf5SDavid du Colombier
1583ff48bf5SDavid du Colombier return cie_set_finish( i_ctx_p,
1593ff48bf5SDavid du Colombier pcs,
1603ff48bf5SDavid du Colombier &istate->colorspace.procs.cie,
1613ff48bf5SDavid du Colombier edepth,
1623ff48bf5SDavid du Colombier code );
1633ff48bf5SDavid du Colombier }
1643ff48bf5SDavid du Colombier
1653ff48bf5SDavid du Colombier
1663ff48bf5SDavid du Colombier const op_def zicc_ll3_op_defs[] = {
1673ff48bf5SDavid du Colombier op_def_begin_ll3(),
1683ff48bf5SDavid du Colombier { "1.seticcspace", zseticcspace },
1693ff48bf5SDavid du Colombier op_def_end(0)
1703ff48bf5SDavid du Colombier };
171