Coverage Report

Created: 2025-12-31 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gsicc.c
Line
Count
Source
1
/* Copyright (C) 2001-2024 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,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Implementation of the ICCBased color space family */
18
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsstruct.h"
24
#include "stream.h"
25
#include "gxcspace.h"   /* for gxcie.c */
26
#include "gxarith.h"
27
#include "gxcie.h"
28
#include "gzstate.h"
29
#include "gsicc.h"
30
#include "gsicc_cache.h"
31
#include "gsicc_cms.h"
32
#include "gsicc_manage.h"
33
#include "gxdevice.h"
34
#include "gsccolor.h"
35
#include "gxdevsop.h"
36
37
#define SAVEICCPROFILE 0
38
39
/*
40
 * Color space methods for ICCBased color spaces.
41
   ICC spaces are now considered to be concrete in that
42
   they always provide a mapping to a specified destination
43
   profile.  As such they will have their own remap functions.
44
   These will simply potentially implement the transfer function,
45
   apply any alpha value, and or end up going through halftoning.
46
   There will not be any heuristic remap of rgb to gray etc */
47
48
static cs_proc_num_components(gx_num_components_ICC);
49
static cs_proc_init_color(gx_init_ICC);
50
static cs_proc_restrict_color(gx_restrict_ICC);
51
static cs_proc_concretize_color(gx_concretize_ICC);
52
static cs_proc_remap_color(gx_remap_ICC);
53
static cs_proc_install_cspace(gx_install_ICC);
54
static cs_proc_remap_concrete_color(gx_remap_concrete_ICC);
55
static cs_proc_final(gx_final_ICC);
56
static cs_proc_serialize(gx_serialize_ICC);
57
static cs_proc_is_linear(gx_cspace_is_linear_ICC);
58
static cs_proc_set_overprint(gx_set_overprint_ICC);
59
static cs_proc_polarity(gx_polarity_ICC);
60
cs_proc_remap_color(gx_remap_ICC_imagelab);
61
62
const gs_color_space_type gs_color_space_type_ICC = {
63
    gs_color_space_index_ICC,       /* index */
64
    true,                           /* can_be_base_space */
65
    true,                           /* can_be_alt_space */
66
    &st_base_color_space,           /* stype - structure descriptor */
67
    gx_num_components_ICC,          /* num_components */
68
    gx_init_ICC,                    /* init_color */
69
    gx_restrict_ICC,                /* restrict_color */
70
    gx_same_concrete_space,         /* concrete_space */
71
    gx_concretize_ICC,              /* concreteize_color */
72
    gx_remap_concrete_ICC,          /* remap_concrete_color */
73
    gx_remap_ICC,                   /* remap_color */
74
    gx_install_ICC,                 /* install_cpsace */
75
    gx_set_overprint_ICC,           /* set_overprint */
76
    gx_final_ICC,                   /* final */
77
    gx_no_adjust_color_count,       /* adjust_color_count */
78
    gx_serialize_ICC,               /* serialize */
79
    gx_cspace_is_linear_ICC,
80
    gx_polarity_ICC
81
};
82
83
static inline void
84
gsicc_remap_fast(gx_device *dev, unsigned short *psrc, unsigned short *psrc_cm,
85
                 gsicc_link_t *icc_link)
86
174M
{
87
174M
    (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_cm, 2);
88
174M
}
89
90
/* ICC color mapping linearity check, a 2-points case. Check only the 1/2 point */
91
static int
92
gx_icc_is_linear_in_line(const gs_color_space *cs, const gs_gstate * pgs,
93
                        gx_device *dev,
94
                        const gs_client_color *c0, const gs_client_color *c1,
95
                        float smoothness, gsicc_link_t *icclink)
96
17.7M
{
97
17.7M
    int nsrc = cs->type->num_components(cs);
98
17.7M
    cmm_dev_profile_t *dev_profile;
99
17.7M
    int ndes;
100
17.7M
    int code;
101
17.7M
    unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
102
17.7M
    unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
103
17.7M
    unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
104
17.7M
    unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
105
17.7M
    unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
106
17.7M
    unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
107
17.7M
    unsigned short interp_des;
108
17.7M
    unsigned short max_diff = (unsigned short) max(1, 65535 * smoothness);
109
17.7M
    int k;
110
111
17.7M
    code = dev_proc(dev, get_profile)(dev, &(dev_profile));
112
17.7M
    if (code < 0)
113
0
        return code;
114
17.7M
    ndes = gsicc_get_device_profile_comps(dev_profile);
115
116
    /* Get us to ushort and get mid point */
117
86.6M
    for (k = 0; k < nsrc; k++) {
118
68.9M
        src0[k] = (unsigned short) (c0->paint.values[k]*65535);
119
68.9M
        src1[k] = (unsigned short) (c1->paint.values[k]*65535);
120
68.9M
        src01[k] = ((unsigned int) src0[k] + (unsigned int) src1[k]) >> 1;
121
68.9M
    }
122
    /* Transform the end points and the interpolated point */
123
17.7M
    gsicc_remap_fast(dev, &(src0[0]), &(des0[0]), icclink);
124
17.7M
    gsicc_remap_fast(dev, &(src1[0]), &(des1[0]), icclink);
125
17.7M
    gsicc_remap_fast(dev, &(src01[0]), &(des01[0]), icclink);
126
    /* Interpolate 1/2 value in des space and compare */
127
53.5M
    for (k = 0; k < ndes; k++) {
128
35.9M
        interp_des = (des0[k] + des1[k]) >> 1;
129
35.9M
        if (any_abs((signed int) interp_des - (signed int) des01[k]) > max_diff)
130
86.7k
            return false;
131
35.9M
    }
132
17.6M
    return 1;
133
17.7M
}
134
135
/* Default icc color mapping linearity check, a triangle case. */
136
static int
137
gx_icc_is_linear_in_triangle(const gs_color_space *cs, const gs_gstate * pgs,
138
                gx_device *dev,
139
                const gs_client_color *c0, const gs_client_color *c1,
140
                const gs_client_color *c2, float smoothness, gsicc_link_t *icclink)
141
17.3M
{
142
    /* Check 4 points middle points of 3 sides and middle of one side with
143
       other point.  We avoid divisions this way. */
144
17.3M
    unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
145
17.3M
    unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
146
17.3M
    unsigned short src2[GS_CLIENT_COLOR_MAX_COMPONENTS];
147
17.3M
    unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
148
17.3M
    unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
149
17.3M
    unsigned short des2[GS_CLIENT_COLOR_MAX_COMPONENTS];
150
17.3M
    unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
151
17.3M
    unsigned short src12[GS_CLIENT_COLOR_MAX_COMPONENTS];
152
17.3M
    unsigned short src02[GS_CLIENT_COLOR_MAX_COMPONENTS];
153
17.3M
    unsigned short src012[GS_CLIENT_COLOR_MAX_COMPONENTS];
154
17.3M
    unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
155
17.3M
    unsigned short des12[GS_CLIENT_COLOR_MAX_COMPONENTS];
156
17.3M
    unsigned short des02[GS_CLIENT_COLOR_MAX_COMPONENTS];
157
17.3M
    unsigned short des012[GS_CLIENT_COLOR_MAX_COMPONENTS];
158
17.3M
    int nsrc = cs->type->num_components(cs);
159
17.3M
    int ndes, code;
160
17.3M
    unsigned short max_diff = (unsigned short) max(1, 65535 * smoothness);
161
17.3M
    unsigned int interp_des;
162
17.3M
    int k;
163
17.3M
    cmm_dev_profile_t *dev_profile;
164
165
17.3M
    code = dev_proc(dev, get_profile)(dev, &(dev_profile));
166
17.3M
    if (code < 0)
167
0
        return code;
168
17.3M
    ndes = gsicc_get_device_profile_comps(dev_profile);
169
170
    /* This needs to be optimized. And range corrected */
171
85.6M
    for (k = 0; k < nsrc; k++){
172
68.3M
        src0[k] = (unsigned short) (c0->paint.values[k]*65535);
173
68.3M
        src1[k] = (unsigned short) (c1->paint.values[k]*65535);
174
68.3M
        src2[k] = (unsigned short) (c2->paint.values[k]*65535);
175
68.3M
        src01[k] = (src0[k] + src1[k]) >> 1;
176
68.3M
        src02[k] = (src0[k] + src2[k]) >> 1;
177
68.3M
        src12[k] = (src1[k] + src2[k]) >> 1;
178
68.3M
        src012[k] = (src12[k] + src0[k]) >> 1;
179
68.3M
    }
180
    /* Map the points */
181
17.3M
    gsicc_remap_fast(dev, &(src0[0]), &(des0[0]), icclink);
182
17.3M
    gsicc_remap_fast(dev, &(src1[0]), &(des1[0]), icclink);
183
17.3M
    gsicc_remap_fast(dev, &(src2[0]), &(des2[0]), icclink);
184
17.3M
    gsicc_remap_fast(dev, &(src01[0]), &(des01[0]), icclink);
185
17.3M
    gsicc_remap_fast(dev, &(src12[0]), &(des12[0]), icclink);
186
17.3M
    gsicc_remap_fast(dev, &(src02[0]), &(des02[0]), icclink);
187
17.3M
    gsicc_remap_fast(dev, &(src012[0]), &(des012[0]), icclink);
188
    /* Interpolate in des space and check it */
189
52.3M
    for (k = 0; k < ndes; k++){
190
35.1M
        interp_des = (des0[k] + des1[k]) >> 1;
191
35.1M
        if (any_abs((signed int) interp_des - (signed int) des01[k]) > max_diff)
192
48.8k
            return false;
193
35.0M
        interp_des = (des0[k] + des2[k]) >> 1;
194
35.0M
        if (any_abs((signed int) interp_des - (signed int) des02[k]) > max_diff)
195
25.5k
            return false;
196
35.0M
        interp_des = (des1[k] + des2[k]) >> 1;
197
35.0M
        if (any_abs((signed int) interp_des - (signed int) des12[k]) > max_diff)
198
598
            return false;
199
        /* 12 with 0 */
200
35.0M
        interp_des = (des0[k] + interp_des) >> 1;
201
35.0M
        if (any_abs((signed int) interp_des - (signed int) des012[k]) > max_diff)
202
3.16k
            return false;
203
35.0M
    }
204
17.2M
    return 1;
205
17.3M
}
206
207
/* ICC color mapping linearity check. */
208
int
209
gx_cspace_is_linear_ICC(const gs_color_space *cs, const gs_gstate * pgs,
210
                gx_device *dev,
211
                const gs_client_color *c0, const gs_client_color *c1,
212
                const gs_client_color *c2, const gs_client_color *c3,
213
                float smoothness, gsicc_link_t *icclink)
214
42.2M
{
215
    /* Assuming 2 <= nc <= 4. We don't need other cases. */
216
    /* With nc == 4 assuming a convex plain quadrangle in the client color space. */
217
42.2M
    int code;
218
219
    /* Do a quick check if we are in a halftone situation. If yes,
220
       then we should not be doing this linear check */
221
42.2M
    if (gx_device_must_halftone(dev)) return 0;
222
42.2M
    if (icclink->is_identity) return 1; /* Transform is identity, linear! */
223
224
35.0M
    if (!colors_are_separable_and_linear(&dev->color_info))
225
0
        return_error(gs_error_rangecheck);
226
35.0M
    if (c2 == NULL)
227
17.7M
        return gx_icc_is_linear_in_line(cs, pgs, dev, c0, c1, smoothness, icclink);
228
17.3M
    code = gx_icc_is_linear_in_triangle(cs, pgs, dev, c0, c1, c2,
229
17.3M
                                            smoothness, icclink);
230
17.3M
    if (code <= 0)
231
78.2k
        return code;
232
17.2M
    if (c3 == NULL)
233
17.2M
        return 1;
234
0
    return gx_icc_is_linear_in_triangle(cs, pgs, dev, c1, c2, c3,
235
0
                                                smoothness, icclink);
236
17.2M
}
237
/*
238
 * Return the number of components used by a ICCBased color space - 1, 3, or 4
239
 */
240
static int
241
gx_num_components_ICC(const gs_color_space * pcs)
242
107M
{
243
107M
    return pcs->cmm_icc_profile_data->num_comps;
244
107M
}
245
246
/* Get the polarity of the ICC Based space */
247
static gx_color_polarity_t
248
gx_polarity_ICC(const gs_color_space * pcs)
249
3
{
250
3
    switch (pcs->cmm_icc_profile_data->data_cs) {
251
0
        case gsUNDEFINED:
252
0
        case gsNAMED:
253
0
            return GX_CINFO_POLARITY_UNKNOWN;
254
0
        case gsGRAY:
255
3
        case gsRGB:
256
3
        case gsCIELAB:
257
3
        case gsCIEXYZ:
258
3
            return GX_CINFO_POLARITY_ADDITIVE;
259
0
        case gsCMYK:
260
0
        case gsNCHANNEL:
261
0
            return GX_CINFO_POLARITY_SUBTRACTIVE;
262
0
        default:
263
0
            return GX_CINFO_POLARITY_UNKNOWN;
264
3
    }
265
3
}
266
267
/*
268
 * Set the initial client color for an ICCBased color space. The convention
269
 * suggested by the ICC specification is to set all components to 0.
270
 */
271
static void
272
gx_init_ICC(gs_client_color * pcc, const gs_color_space * pcs)
273
37.2M
{
274
37.2M
    int     i, ncomps = pcs->cmm_icc_profile_data->num_comps;
275
276
108M
    for (i = 0; i < ncomps; ++i)
277
70.8M
        pcc->paint.values[i] = 0.0;
278
279
    /* make sure that [ 0, ... 0] is in range */
280
37.2M
    gx_restrict_ICC(pcc, pcs);
281
37.2M
}
282
283
/*
284
 * Restrict an color to the range specified for an ICCBased color space.
285
 */
286
static void
287
gx_restrict_ICC(gs_client_color * pcc, const gs_color_space * pcs)
288
170M
{
289
170M
    int                 i, ncomps = pcs->cmm_icc_profile_data->num_comps;
290
170M
    const gs_range *    ranges = pcs->cmm_icc_profile_data->Range.ranges;
291
292
636M
    for (i = 0; i < ncomps; ++i) {
293
466M
        double  v = pcc->paint.values[i];
294
466M
        double  rmin = ranges[i].rmin, rmax = ranges[i].rmax;
295
296
466M
        if (v < rmin)
297
720k
            pcc->paint.values[i] = rmin;
298
465M
        else if (v > rmax)
299
6.79M
            pcc->paint.values[i] = rmax;
300
466M
    }
301
170M
}
302
303
static int
304
gx_remap_concrete_icc_devicen(const gs_color_space * pcs, const frac * pconc,
305
                              gx_device_color * pdc, const gs_gstate * pgs,
306
                              gx_device * dev, gs_color_select_t select,
307
                              const cmm_dev_profile_t *dev_profile)
308
0
{
309
    /* Check if this is a device with a DeviceN ICC profile.  In this case,
310
       we need to do some special stuff */
311
0
    int code = 0;
312
313
0
    if (dev_profile->spotnames != NULL  &&
314
0
        !dev_profile->spotnames->equiv_cmyk_set) {
315
        /* This means that someone has specified a DeviceN (Ncolor)
316
           ICC destination profile for this device and we still need to set
317
           up the equivalent CMYK colors for the spot colors that are present.
318
           This allows us to have some sort of composite viewing of the spot
319
           colors as they would colorimetrically appear. */
320
0
        code = gsicc_set_devicen_equiv_colors(dev, pgs,
321
0
                        dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
322
0
        dev_profile->spotnames->equiv_cmyk_set = true;
323
0
    }
324
0
    gx_remap_concrete_devicen(pconc, pdc, pgs, dev, select, pcs);
325
0
    return code;
326
0
}
327
328
/* If the color is already concretized, then we are in the color space
329
   defined by the device profile.  The remaining things to do would
330
   be to potentially apply alpha, apply the transfer function, and
331
   do any halftoning.  The remap is based upon the ICC profile defined
332
   in the device profile entry of the profile manager. */
333
int
334
gx_remap_concrete_ICC(const gs_color_space * pcs, const frac * pconc,
335
                      gx_device_color * pdc, const gs_gstate * pgs,
336
                      gx_device * dev, gs_color_select_t select,
337
                      const cmm_dev_profile_t *dev_profile)
338
1.61G
{
339
1.61G
    switch (gsicc_get_device_profile_comps(dev_profile)) {
340
52.8M
        case 1:
341
52.8M
            return gx_remap_concrete_DGray(pcs, pconc, pdc, pgs, dev, select, dev_profile);
342
1.44G
        case 3:
343
1.44G
            return gx_remap_concrete_DRGB(pcs, pconc, pdc, pgs, dev, select, dev_profile);
344
116M
        case 4:
345
116M
            return gx_remap_concrete_DCMYK(pcs, pconc, pdc, pgs, dev, select, dev_profile);
346
0
        default:
347
            /* This is a special case where we have a source color and our
348
               output profile must be DeviceN.   We will need to map our
349
               colorants to the proper planes */
350
0
            return gx_remap_concrete_icc_devicen(pcs, pconc, pdc, pgs, dev, select, dev_profile);
351
1.61G
    }
352
1.61G
}
353
354
/*
355
 * To device space
356
 */
357
int
358
gx_remap_ICC_with_link(const gs_client_color * pcc, const gs_color_space * pcs,
359
        gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev,
360
                gs_color_select_t select, gsicc_link_t *icc_link)
361
1.56G
{
362
1.56G
    cmm_dev_profile_t *dev_profile;
363
1.56G
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
364
1.56G
    unsigned short *psrc_temp;
365
1.56G
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
366
1.56G
    int k,i;
367
#ifdef DEBUG
368
    int num_src_comps;
369
#endif
370
1.56G
    int num_des_comps;
371
1.56G
    int code;
372
373
1.56G
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
374
1.56G
    if (code < 0)
375
0
        return code;
376
1.56G
    if (dev_profile == NULL)
377
0
        return gs_throw(gs_error_Fatal, "Attempting to do ICC remap with no profile");
378
1.56G
    if (icc_link == NULL)
379
0
        return gs_throw(gs_error_Fatal, "Attempting to do ICC remap with no link");
380
381
    /* Need to clear out psrc_cm in case we have separation bands that are
382
       not color managed */
383
1.56G
    memset(psrc_cm,0,sizeof(unsigned short)*GS_CLIENT_COLOR_MAX_COMPONENTS);
384
385
     /* This needs to be optimized */
386
1.56G
    if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB ||
387
1.56G
        pcs->cmm_icc_profile_data->islab) {
388
1.05k
        psrc[0] = (unsigned short) (pcc->paint.values[0]*65535.0/100.0);
389
1.05k
        psrc[1] = (unsigned short) ((pcc->paint.values[1]+128)/255.0*65535.0);
390
1.05k
        psrc[2] = (unsigned short) ((pcc->paint.values[2]+128)/255.0*65535.0);
391
1.56G
    } else {
392
6.30G
        for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++){
393
4.73G
            psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
394
4.73G
        }
395
1.56G
    }
396
1.56G
    num_des_comps = gsicc_get_device_profile_comps(dev_profile);
397
1.56G
    if (icc_link->is_identity) {
398
1.37G
        psrc_temp = &(psrc[0]);
399
1.37G
    } else {
400
        /* Transform the color */
401
190M
        psrc_temp = &(psrc_cm[0]);
402
190M
        (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
403
190M
    }
404
#ifdef DEBUG
405
    if (!icc_link->is_identity) {
406
        num_src_comps = pcs->cmm_icc_profile_data->num_comps;
407
        if_debug0m(gs_debug_flag_icc, dev->memory, "[icc] remap [ ");
408
        for (k = 0; k < num_src_comps; k++) {
409
            if_debug1m(gs_debug_flag_icc, dev->memory, "%d ", psrc[k]);
410
        }
411
        if_debug0m(gs_debug_flag_icc, dev->memory, "] --> [ ");
412
        for (k = 0; k < num_des_comps; k++) {
413
            if_debug1m(gs_debug_flag_icc, dev->memory, "%d ", psrc_temp[k]);
414
        }
415
        if_debug0m(gs_debug_flag_icc, dev->memory, "]\n");
416
    } else {
417
        num_src_comps = pcs->cmm_icc_profile_data->num_comps;
418
        if_debug0m(gs_debug_flag_icc, dev->memory, "[icc] Identity mapping\n");
419
        if_debug0m(gs_debug_flag_icc, dev->memory, "[icc] [ ");
420
        for (k = 0; k < num_src_comps; k++) {
421
            if_debug1m(gs_debug_flag_icc, dev->memory, "%d ", psrc[k]);
422
        }
423
        if_debug0m(gs_debug_flag_icc, dev->memory, "]\n");
424
    }
425
#endif
426
    /* Now do the remap for ICC which amounts to the alpha application
427
       the transfer function and potentially the halftoning */
428
    /* Right now we need to go from unsigned short to frac.  I really
429
       would like to avoid this sort of stuff.  That will come. */
430
6.26G
    for (k = 0; k < num_des_comps; k++){
431
4.70G
        conc[k] = ushort2frac(psrc_temp[k]);
432
4.70G
    }
433
    /* In case there are extra components beyond the ICC ones */
434
1.56G
    for (k = num_des_comps; k < dev->color_info.num_components; k++) {
435
2.93M
        conc[k] = 0;
436
2.93M
    }
437
1.56G
    gx_remap_concrete_ICC(pcs, conc, pdc, pgs, dev, select, dev_profile);
438
439
    /* Save original color space and color info into dev color */
440
1.56G
    i = pcs->cmm_icc_profile_data->num_comps;
441
6.30G
    for (i--; i >= 0; i--)
442
4.73G
        pdc->ccolor.paint.values[i] = pcc->paint.values[i];
443
1.56G
    pdc->ccolor_valid = true;
444
1.56G
    return 0;
445
1.56G
}
446
447
int
448
gx_remap_ICC(const gs_client_color * pcc, const gs_color_space * pcs,
449
        gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev,
450
                gs_color_select_t select)
451
189M
{
452
189M
    gsicc_link_t *icc_link;
453
189M
    gsicc_rendering_param_t rendering_params;
454
189M
    cmm_dev_profile_t *dev_profile;
455
189M
    int code;
456
457
189M
    color_replace_t param;
458
189M
    param.pcc = pcc;
459
189M
    param.pcs = pcs;
460
189M
    param.pdc = pdc;
461
189M
    param.pgs = pgs;
462
189M
    param.pdf14_iccprofile = NULL;
463
464
    /* Try color replacement. If successful (>0) then no
465
       ICC color management for this color. */
466
189M
    if (dev_proc(pgs->device, dev_spec_op)(pgs->device,
467
189M
        gxdso_replacecolor, &param, sizeof(color_replace_t)) > 0)
468
0
        return 0;
469
470
189M
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
471
189M
    if (code < 0)
472
0
        return code;
473
189M
    if (dev_profile == NULL)
474
0
        return gs_throw(gs_error_Fatal, "Attempting to do ICC remap with no profile");
475
476
189M
    rendering_params.black_point_comp = pgs->blackptcomp;
477
189M
    rendering_params.graphics_type_tag = dev->graphics_type_tag;
478
189M
    rendering_params.override_icc = false;
479
189M
    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
480
189M
    rendering_params.rendering_intent = pgs->renderingintent;
481
189M
    rendering_params.cmm = gsCMM_DEFAULT;
482
    /* Get a link from the cache, or create if it is not there. Need to get 16 bit profile */
483
189M
    icc_link = gsicc_get_link(pgs, dev, pcs, NULL, &rendering_params, pgs->memory);
484
189M
    if (icc_link == NULL) {
485
#ifdef DEBUG
486
        gs_warn("Could not create ICC link:  Check profiles");
487
#endif
488
172k
        return_error(gs_error_unknownerror);
489
172k
    }
490
491
189M
    code = gx_remap_ICC_with_link(pcc, pcs, pdc, pgs, dev, select, icc_link);
492
    /* Release the link */
493
189M
    gsicc_release_link(icc_link);
494
189M
    return code;
495
189M
}
496
497
/*
498
 * Same as above, but there is no rescale of CIELAB colors.  This is needed
499
   since the rescale is not needed when the source data is image based.
500
   The DeviceN image rendering case uses the remap proc vs. the ICC based method
501
   which handles the remapping itself.
502
 */
503
int
504
gx_remap_ICC_imagelab(const gs_client_color * pcc, const gs_color_space * pcs,
505
        gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev,
506
                gs_color_select_t select)
507
0
{
508
0
    gsicc_link_t *icc_link;
509
0
    gsicc_rendering_param_t rendering_params;
510
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
511
0
    unsigned short *psrc_temp;
512
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
513
0
    int k,i;
514
0
    int num_des_comps;
515
0
    int code;
516
0
    cmm_dev_profile_t *dev_profile;
517
518
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
519
0
    if (code < 0)
520
0
        return code;
521
0
    num_des_comps = gsicc_get_device_profile_comps(dev_profile);
522
0
    rendering_params.black_point_comp = pgs->blackptcomp;
523
0
    rendering_params.graphics_type_tag = dev->graphics_type_tag;
524
0
    rendering_params.override_icc = false;
525
0
    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
526
0
    rendering_params.rendering_intent = pgs->renderingintent;
527
0
    rendering_params.cmm = gsCMM_DEFAULT;
528
    /* Need to clear out psrc_cm in case we have separation bands that are
529
       not color managed */
530
0
    memset(psrc_cm, 0, sizeof(unsigned short)*GS_CLIENT_COLOR_MAX_COMPONENTS);
531
532
0
    for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++)
533
0
        psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
534
535
    /* Get a link from the cache, or create if it is not there. Need to get 16 bit profile */
536
0
    icc_link = gsicc_get_link(pgs, dev, pcs, NULL, &rendering_params, pgs->memory);
537
0
    if (icc_link == NULL) {
538
#ifdef DEBUG
539
        gs_warn("Could not create ICC link:  Check profiles");
540
#endif
541
0
        return_error(gs_error_unknownerror);
542
0
    }
543
0
    if (icc_link->is_identity) {
544
0
        psrc_temp = &(psrc[0]);
545
0
    } else {
546
        /* Transform the color */
547
0
        psrc_temp = &(psrc_cm[0]);
548
0
        (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
549
0
    }
550
    /* Release the link */
551
0
    gsicc_release_link(icc_link);
552
    /* Now do the remap for ICC which amounts to the alpha application
553
       the transfer function and potentially the halftoning */
554
    /* Right now we need to go from unsigned short to frac.  I really
555
       would like to avoid this sort of stuff.  That will come. */
556
0
    for (k = 0; k < num_des_comps; k++){
557
0
        conc[k] = ushort2frac(psrc_temp[k]);
558
0
    }
559
    /* We have to worry about extra colorants in the device. */
560
0
    for (k = num_des_comps; k < dev->color_info.num_components; k++) {
561
0
        conc[k] = 0;
562
0
    }
563
0
    gx_remap_concrete_ICC(pcs, conc, pdc, pgs, dev, select, dev_profile);
564
565
    /* Save original color space and color info into dev color */
566
0
    i = pcs->cmm_icc_profile_data->num_comps;
567
0
    for (i--; i >= 0; i--)
568
0
        pdc->ccolor.paint.values[i] = pcc->paint.values[i];
569
0
    pdc->ccolor_valid = true;
570
0
    return 0;
571
0
}
572
573
/* Convert an ICCBased color space to a concrete color space. */
574
575
static int
576
gx_concretize_ICC(
577
    const gs_client_color * pcc,
578
    const gs_color_space *  pcs,
579
    frac *                  pconc,
580
    const gs_gstate * pgs,
581
    gx_device *dev)
582
49.7M
    {
583
584
49.7M
    gsicc_link_t *icc_link;
585
49.7M
    gsicc_rendering_param_t rendering_params;
586
49.7M
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS];
587
49.7M
    int k;
588
49.7M
    unsigned short *psrc_temp;
589
49.7M
    int num_des_comps;
590
49.7M
    int code;
591
49.7M
    cmm_dev_profile_t *dev_profile;
592
593
49.7M
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
594
49.7M
    if (code < 0)
595
0
        return code;
596
49.7M
    num_des_comps = gsicc_get_device_profile_comps(dev_profile);
597
    /* Define the rendering intents.  */
598
49.7M
    rendering_params.black_point_comp = pgs->blackptcomp;
599
49.7M
    rendering_params.graphics_type_tag = dev->graphics_type_tag;
600
49.7M
    rendering_params.override_icc = false;
601
49.7M
    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
602
49.7M
    rendering_params.rendering_intent = pgs->renderingintent;
603
49.7M
    rendering_params.cmm = gsCMM_DEFAULT;
604
199M
    for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++) {
605
149M
        psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0);
606
149M
    }
607
    /* Get a link from the cache, or create if it is not there. Get 16 bit profile */
608
49.7M
    icc_link = gsicc_get_link(pgs, dev, pcs, NULL, &rendering_params, pgs->memory);
609
49.7M
    if (icc_link == NULL) {
610
#ifdef DEBUG
611
        gs_warn("Could not create ICC link:  Check profiles");
612
#endif
613
9.47k
        return_error(gs_error_unknownerror);
614
9.47k
    }
615
    /* Transform the color */
616
49.7M
    if (icc_link->is_identity) {
617
6.37M
        psrc_temp = &(psrc[0]);
618
43.4M
    } else {
619
        /* Transform the color */
620
43.4M
        psrc_temp = &(psrc_cm[0]);
621
43.4M
        (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2);
622
43.4M
    }
623
    /* This needs to be optimized */
624
195M
    for (k = 0; k < num_des_comps; k++) {
625
145M
        pconc[k] = float2frac(((float) psrc_temp[k])/65535.0);
626
145M
    }
627
    /* We have to worry about extra colorants in the device. */
628
49.7M
    for (k = num_des_comps; k < dev->color_info.num_components; k++) {
629
1.25k
        pconc[k] = 0;
630
1.25k
    }
631
632
    /* Release the link */
633
49.7M
    gsicc_release_link(icc_link);
634
49.7M
    return 0;
635
49.7M
}
636
637
        /*
638
 * Finalize the contents of an ICC color space. Now that color space
639
 * objects have straightforward reference counting discipline, there's
640
 * nothing special about it. In the previous state of affairs, the
641
 * argument in favor of correct reference counting spoke of "an
642
 * unintuitive but otherwise legitimate state of affairs".
643
         */
644
static void
645
gx_final_ICC(gs_color_space * pcs)
646
22.7M
{
647
22.7M
    if (pcs->cmm_icc_profile_data != NULL) {
648
22.7M
        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "gx_final_ICC");
649
22.7M
        pcs->cmm_icc_profile_data = NULL;
650
22.7M
    }
651
22.7M
}
652
653
/*
654
 * Install an ICCBased color space.
655
 *
656
 * Note that an ICCBased color space must be installed before it is known if
657
 * the ICC profile or the alternate color space is to be used.
658
 */
659
static int
660
gx_install_ICC(gs_color_space * pcs, gs_gstate * pgs)
661
2.98M
{
662
    /* update the stub information used by the joint caches */
663
2.98M
    return 0;
664
2.98M
}
665
666
/*
667
 * Constructor for ICCBased color space. As with the other color space
668
 * constructors, this provides only minimal initialization.
669
 */
670
int
671
gs_cspace_build_ICC(
672
    gs_color_space **   ppcspace,
673
    void *              client_data,
674
    gs_memory_t *       pmem )
675
2.26M
{
676
2.26M
    gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC);
677
2.26M
    if (!pcspace) {
678
0
        return_error(gs_error_VMerror);
679
0
    }
680
2.26M
    *ppcspace = pcspace;
681
682
2.26M
    return 0;
683
2.26M
}
684
685
/* ---------------- Serialization. -------------------------------- */
686
687
static int
688
gx_serialize_ICC(const gs_color_space * pcs, stream * s)
689
97.6k
{
690
97.6k
    gsicc_serialized_profile_t *profile__serial;
691
97.6k
    uint n;
692
97.6k
    int code = gx_serialize_cspace_type(pcs, s);
693
694
97.6k
    if (code < 0)
695
0
        return code;
696
97.6k
    profile__serial = (gsicc_serialized_profile_t*) pcs->cmm_icc_profile_data;
697
97.6k
    code = sputs(s, (byte *)profile__serial, GSICC_SERIALIZED_SIZE, &n);
698
97.6k
    return(code);
699
97.6k
}
700
701
/* Overprint.  Here we may have either spot colors or CMYK colors. */
702
static int
703
gx_set_overprint_ICC(const gs_color_space * pcs, gs_gstate * pgs)
704
877k
{
705
877k
    gx_device *dev = pgs->device;
706
877k
    gx_device_color_info *pcinfo = (dev == 0 ? 0 : &dev->color_info);
707
877k
    bool cs_ok;
708
877k
    cmm_dev_profile_t *dev_profile;
709
877k
    bool gray_to_k;
710
877k
    bool op = pgs->is_fill_color ? pgs->overprint : pgs->stroke_overprint;
711
712
877k
    if (dev == 0 || pcinfo == NULL || !op ||
713
857k
        gx_get_opmsupported(dev) == GX_CINFO_OPMSUPPORTED_NOT)
714
869k
        return gx_set_no_overprint(pgs);
715
716
8.32k
    dev_proc(dev, get_profile)(dev, &dev_profile);
717
8.32k
    gray_to_k = dev_profile->devicegraytok;
718
719
    /* Possibly do CMYK based overprinting if profile is CMYK based or if we
720
       are gray source based and doing gray to k mapping
721
       (Ghent GWG 3.0 Gray Overprint Patch (030_Gray_K_black_OP_x1a.pdf) */
722
8.32k
    if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
723
0
        cs_ok = (pcs->cmm_icc_profile_data->data_cs == gsRGB);
724
8.32k
    else
725
8.32k
        cs_ok = ((pcs->cmm_icc_profile_data->data_cs == gsCMYK) ||
726
6.59k
            (pcs->cmm_icc_profile_data->data_cs == gsGRAY && gray_to_k));
727
728
8.32k
    if_debug4m(gs_debug_flag_overprint, pgs->memory,
729
8.32k
        "[overprint] gx_set_overprint_ICC. cs_ok = %d is_fill_color = %d overprint = %d stroke_overprint = %d \n",
730
8.32k
        cs_ok, pgs->is_fill_color, pgs->overprint, pgs->stroke_overprint);
731
732
8.32k
    if (cs_ok)
733
2.00k
    {
734
2.00k
        if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
735
0
            return gx_set_overprint_rgb(pcs, pgs);
736
2.00k
        else
737
2.00k
            return gx_set_overprint_cmyk(pcs, pgs);
738
2.00k
    }
739
740
    /* In this case, we still need to maintain any spot
741
       colorant channels.  Per Table 7.14. */
742
6.31k
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0))
743
6.30k
        return gx_set_spot_only_overprint(pgs);
744
745
9
    return gx_set_no_overprint(pgs);
746
6.31k
}
747
748
int
749
gx_default_get_profile(const gx_device *dev, cmm_dev_profile_t **profile)
750
3.99G
{
751
3.99G
    *profile = dev->icc_struct;
752
3.99G
    return 0;
753
3.99G
}
754
755
/* Adjust the color model of the device to match that of the profile. Used by
756
   vector based devices and the tiff scaled devices. Only valid for bit depths
757
   of 8n/component. Note the caller likely will need to update its procs */
758
int
759
gx_change_color_model(gx_device *dev, int num_comps, int bit_depth)
760
0
{
761
0
    int k;
762
763
0
    if (!((num_comps == 1) || (num_comps == 3) || (num_comps == 4)))
764
0
        return_error(gs_error_unknownerror);
765
766
0
    dev->color_info.max_components = num_comps;
767
0
    dev->color_info.num_components = num_comps;
768
0
    dev->color_info.depth = num_comps * bit_depth;
769
770
0
    if (num_comps == 4) {
771
0
        dev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
772
0
    } else {
773
0
        dev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
774
0
    }
775
776
0
    for (k = 0; k < num_comps; k++) {
777
0
        dev->color_info.comp_shift[k] = bit_depth * (3 - k);
778
0
        dev->color_info.comp_bits[k] = bit_depth;
779
0
        dev->color_info.comp_mask[k] =
780
0
            ((gx_color_index)255) << dev->color_info.comp_shift[k];
781
0
    }
782
783
0
    return 0;
784
0
}