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 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