File: zicc.c

package info (click to toggle)
ghostscript 8.71~dfsg2-9+squeeze1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 79,896 kB
  • ctags: 80,654
  • sloc: ansic: 501,432; sh: 25,689; python: 4,853; cpp: 3,633; perl: 3,597; tcl: 1,480; makefile: 1,187; lisp: 407; asm: 284; xml: 263; awk: 66; csh: 17; yacc: 15
file content (214 lines) | stat: -rw-r--r-- 7,451 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/* Copyright (C) 2001-2008 Artifex Software, Inc.
   All Rights Reserved.
  
   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied, modified
   or distributed except as expressly authorized under the terms of that
   license.  Refer to licensing information at http://www.artifex.com/
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
*/

/* $Id: zicc.c 9380 2009-01-21 15:34:55Z ken $ */
/* ICCBased color operators */

#include "math_.h"
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "gsstruct.h"
#include "gxcspace.h"		/* gscolor2.h requires gscspace.h */
#include "stream.h"
#include "files.h"
#include "gscolor2.h"
#include "icc.h"			
#include "gsicc.h"
#include "estack.h"
#include "idict.h"
#include "idparam.h"
#include "igstate.h"
#include "icie.h"
#include "ialloc.h"
#include "zicc.h"

int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
{
    os_ptr                  op = osp;
    int edepth = ref_stack_count(&e_stack);
    int                     code, reuse_op = 0;
    gs_color_space *        pcs;
    gs_color_space *  palt_cs;
    int                     i;
    gs_cie_icc *            picc_info;
    ref *                   pstrmval;
    stream *                s = 0L;

    palt_cs = gs_currentcolorspace(igs);
    /* verify the DataSource entry */
    if (dict_find_string(ICCdict, "DataSource", &pstrmval) <= 0)
        return_error(e_undefined);
    check_read_file(s, pstrmval);

    /* build the color space object */
    code = gs_cspace_build_CIEICC(&pcs, NULL, gs_state_memory(igs));
    if (code < 0)
        return code;
    picc_info = pcs->params.icc.picc_info;
    picc_info->num_components = ncomps;
    picc_info->instrp = s;
    picc_info->file_id = (s->read_id | s->write_id);
    for (i = 0; i < ncomps; i++) {
        picc_info->Range.ranges[i].rmin = range_buff[2 * i];
        picc_info->Range.ranges[i].rmax = range_buff[2 * i + 1];

    }

    /* record the current space as the alternative color space */
    pcs->base_space = palt_cs;
    rc_increment(palt_cs);

    code = gx_load_icc_profile(picc_info);
    if (code < 0)
	return code;

    /* If the input space to this profile is CIELAB, then we need to adjust the limits */
    /* See ICC spec ICC.1:2004-10 Section 6.3.4.2 and 6.4 */
    if(picc_info->plu->e_inSpace == icSigLabData)
    {
        picc_info->Range.ranges[0].rmin = 0.0;
        picc_info->Range.ranges[0].rmax = 100.0;

        picc_info->Range.ranges[1].rmin = -128.0;
        picc_info->Range.ranges[1].rmax = 127.0;

        picc_info->Range.ranges[2].rmin = -128.0;
        picc_info->Range.ranges[2].rmax = 127.0;

    } 
    /* If the input space is icSigXYZData, then we should do the limits based upon the white point of the profile.  */
    if(picc_info->plu->e_inSpace == icSigXYZData)
    {
	for (i = 0; i < 3; i++) 
	{
	    picc_info->Range.ranges[i].rmin = 0;
	}

	picc_info->Range.ranges[0].rmax = picc_info->common.points.WhitePoint.u;
	picc_info->Range.ranges[1].rmax = picc_info->common.points.WhitePoint.v;
    	picc_info->Range.ranges[2].rmax = picc_info->common.points.WhitePoint.w;
    }

    code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs,
			   (gs_cie_common *)picc_info, igs);
    if (code < 0)
	return code;

    return cie_set_finish( i_ctx_p,
                           pcs,
                           &istate->colorspace[0].procs.cie,
                           edepth,
                           code );
}

/*
 *   <dict>  .seticcspace  -
 *
 * Create an ICCBased color space and set it to be the current color space.
 *
 * The PostScript structure of an ICCBased color space is that same as that
 * for a CIEBased* color space:
 *
 *     [ /ICCBased <dictionary> ]
 *
 * As is the for other .setcie*space operators, the operand dictionary rather
 * than the complete color space array is on the stack when this operator
 * is inovked.
 *
 * At the time this procedure is called, the alternative color space for
 * the ICCBased color space is expected to be the current color space,
 * whether that space was explicitly specified or implied by the number
 * of components in the ICCBased color space dictionary. This is consistent
 * with the handling of alternative spaces in Separation, DeviceN, and
 * Indexed color spaces. Unlike the "zset*space" routines for those spaces,
 * however, the current code does not attempt to build the color space
 * "in place" in the graphic state.
 *
 * The procedure that invokes this operator will already have checked that
 * the operand is a dictionary, is readable, and defines the key /N
 * (number of components).
 */
static int
zseticcspace(i_ctx_t * i_ctx_p)
{
    os_ptr                  op = osp;
    int                     code;
    gs_color_space *  palt_cs;
    ref *                   pnval;
    ref *                   pstrmval;
    stream *                s;
    int                     i, ncomps;
    float                   range_buff[8];
    static const float      dflt_range[8] = { 0, 1,   0, 1,   0, 1,   0, 1 };

    code = dict_find_string(op, "N", &pnval);
    if (code < 0)
	return code;

    ncomps = pnval->value.intval;

    if (2*ncomps > sizeof(range_buff)/sizeof(range_buff[0]))
        return_error(e_rangecheck);

    /* verify the DataSource entry */
    if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
        return_error(e_undefined);
    check_read_file(s, pstrmval);

    /*
     * Verify that the current color space can be a alternative color space.
     * The check for ICCBased color space is a hack to avoid introducing yet
     * another category indicator into the gs_color_space_type structur.
     */
    palt_cs = gs_currentcolorspace(igs);
    if ( !palt_cs->type->can_be_alt_space                                ||
         gs_color_space_get_index(palt_cs) == gs_color_space_index_CIEICC  )
        return_error(e_rangecheck);

    /*
     * Fetch and verify the Range array.
     *
     * The PDF documentation is unclear as to the purpose of this array.
     * Essentially all that is stated is that "These values must match the
     * information in the ICC profile" (PDF Reference, 2nd ed., p. 174).
     * If that is the case, why not use the information in the profile?
     * The only reason we can think of is range specification is intended
     * to be used to limit the range of values passed to the alternate
     * color space (the range may be smaller than the native range of values
     * provided by that color space).
     *
     * Because the icclib code will perform normalization based on color
     * space, we use the range values only to restrict the set of input
     * values; they are not used for normalization.
     */
    code = dict_floats_param( imemory, 
			      op,
                              "Range",
                              2 * ncomps,
                              range_buff,
                              dflt_range );
    for (i = 0; i < 2 * ncomps && range_buff[i + 1] >= range_buff[i]; i += 2)
        ;
    if (i != 2 * ncomps)
        return_error(e_rangecheck);

    return seticc(i_ctx_p, ncomps, op, range_buff);
}


const op_def    zicc_ll3_op_defs[] = {
    op_def_begin_ll3(),
    { "1.seticcspace", zseticcspace },
    op_def_end(0)
};