~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/gsicc.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2006 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, modified
 
8
   or distributed except as expressly authorized under the terms of that
 
9
   license.  Refer to licensing information at http://www.artifex.com/
 
10
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
 
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
 
12
*/
 
13
 
 
14
/* $Id: gsicc.c 8780 2008-05-27 20:12:08Z mvrhel $ */
 
15
/* Implementation of the ICCBased color space family */
 
16
 
 
17
#include "math_.h"
 
18
#include "memory_.h"
 
19
#include "gx.h"
 
20
#include "gserrors.h"
 
21
#include "gsstruct.h"
 
22
#include "stream.h"
 
23
#include "gxcspace.h"           /* for gxcie.c */
 
24
#include "gxarith.h"
 
25
#include "gxcie.h"
 
26
#include "gzstate.h"
 
27
#include "icc.h"                /* must precede icc.h */
 
28
#include "gsicc.h"
 
29
 
 
30
#define SAVEICCPROFILE 0
 
31
 
 
32
typedef struct _icmFileGs icmFileGs;
 
33
 
 
34
struct _icmFileGs {
 
35
    ICM_FILE_BASE
 
36
 
 
37
    /* Private: */
 
38
    stream *strp;
 
39
};
 
40
 
 
41
/* Garbage collection code */
 
42
 
 
43
/*
 
44
 * Discard a gs_cie_icc_s structure. This requires that we call the
 
45
 * destructor for ICC profile, lookup, and file objects (which are
 
46
 * stored in "foreign" memory).
 
47
 *
 
48
 * No special action is taken with respect to the stream pointer; that is
 
49
 * the responsibility of the client.  */
 
50
static void
 
51
cie_icc_finalize(void * pvicc_info)
 
52
{
 
53
    gs_cie_icc *    picc_info = (gs_cie_icc *)pvicc_info;
 
54
 
 
55
    if (picc_info->plu != NULL) {
 
56
        picc_info->plu->del(picc_info->plu);
 
57
        picc_info->plu = NULL;
 
58
    }
 
59
    if (picc_info->picc != NULL) {
 
60
        picc_info->picc->del(picc_info->picc);
 
61
        picc_info->picc = NULL;
 
62
    }
 
63
    if (picc_info->pfile != NULL) {
 
64
        picc_info->pfile->del(picc_info->pfile);
 
65
        picc_info->pfile = NULL;
 
66
    }
 
67
}
 
68
 
 
69
private_st_cie_icc();
 
70
 
 
71
/*
 
72
 * Because the color space structure stores alternative color space in-line,
 
73
 * we must enumerate and relocate pointers in these space explicity.
 
74
 */
 
75
gs_private_st_composite( st_color_space_CIEICC,
 
76
                         gs_color_space,
 
77
                         "gs_color_space_CIEICC",
 
78
                         cs_CIEICC_enum_ptrs,
 
79
                         cs_CIEICC_reloc_ptrs );
 
80
 
 
81
/* pointer enumeration routine */
 
82
static
 
83
ENUM_PTRS_BEGIN(cs_CIEICC_enum_ptrs) return 0;
 
84
        ENUM_PTR(0, gs_color_space, params.icc.picc_info);
 
85
ENUM_PTRS_END
 
86
 
 
87
/* pointer relocation routine */
 
88
static
 
89
RELOC_PTRS_BEGIN(cs_CIEICC_reloc_ptrs)
 
90
    RELOC_PTR(gs_color_space, params.icc.picc_info);
 
91
RELOC_PTRS_END
 
92
 
 
93
 
 
94
/*
 
95
 * Color space methods for ICCBased color spaces.
 
96
 *
 
97
 * As documented, ICCBased color spaces may be used as both base and
 
98
 * alternative color spaces. Futhermore,, they can themselves contain paint
 
99
 * color spaces as alternative color space. In this implementation we allow
 
100
 * them to be used as base and alternative color spaces, but only to contain
 
101
 * "small" base color spaces (CIEBased or smaller). This arrangement avoids
 
102
 * breaking the color space heirarchy. Providing a more correct arrangement
 
103
 * requires a major change in the color space mechanism.
 
104
 *
 
105
 * Several of the methods used by ICCBased color space apply as well to
 
106
 * DeviceN color spaces, in that they are generic to color spaces having
 
107
 * a variable number of components. We have elected not to attempt to 
 
108
 * extract and combine these operations, because this would save only a
 
109
 * small amount of code, and much more could be saved by intorducing certain
 
110
 * common elements (ranges, number of components, etc.) into the color space
 
111
 * root class.
 
112
 */
 
113
static cs_proc_num_components(gx_num_components_CIEICC);
 
114
static cs_proc_init_color(gx_init_CIEICC);
 
115
static cs_proc_restrict_color(gx_restrict_CIEICC);
 
116
static cs_proc_concrete_space(gx_concrete_space_CIEICC);
 
117
static cs_proc_concretize_color(gx_concretize_CIEICC);
 
118
#if ENABLE_CUSTOM_COLOR_CALLBACK
 
119
static cs_proc_remap_color(gx_remap_ICCBased);
 
120
#endif
 
121
static cs_proc_final(gx_final_CIEICC);
 
122
static cs_proc_serialize(gx_serialize_CIEICC);
 
123
 
 
124
static const gs_color_space_type gs_color_space_type_CIEICC = {
 
125
    gs_color_space_index_CIEICC,    /* index */
 
126
    true,                           /* can_be_base_space */
 
127
    true,                           /* can_be_alt_space */
 
128
    &st_color_space_CIEICC,         /* stype - structure descriptor */
 
129
    gx_num_components_CIEICC,       /* num_components */
 
130
    gx_init_CIEICC,                 /* init_color */
 
131
    gx_restrict_CIEICC,             /* restrict_color */
 
132
    gx_concrete_space_CIEICC,       /* concrete_space */
 
133
    gx_concretize_CIEICC,           /* concreteize_color */
 
134
    NULL,                           /* remap_concrete_color */
 
135
#if ENABLE_CUSTOM_COLOR_CALLBACK
 
136
    gx_remap_ICCBased,              /* remap_color */
 
137
#else
 
138
    gx_default_remap_color,         /* remap_color */
 
139
#endif
 
140
    gx_install_CIE,                 /* install_cpsace */
 
141
    gx_spot_colors_set_overprint,   /* set_overprint */
 
142
    gx_final_CIEICC,                /* final */
 
143
    gx_no_adjust_color_count,       /* adjust_color_count */
 
144
    gx_serialize_CIEICC,                    /* serialize */
 
145
    gx_cspace_is_linear_default
 
146
};
 
147
 
 
148
 
 
149
/*
 
150
 * Return the number of components used by a ICCBased color space - 1, 3, or 4
 
151
 */
 
152
static int
 
153
gx_num_components_CIEICC(const gs_color_space * pcs)
 
154
{
 
155
    return pcs->params.icc.picc_info->num_components;
 
156
}
 
157
 
 
158
/*
 
159
 * Set the initial client color for an ICCBased color space. The convention
 
160
 * suggested by the ICC specification is to set all components to 0.
 
161
 */
 
162
static void
 
163
gx_init_CIEICC(gs_client_color * pcc, const gs_color_space * pcs)
 
164
{
 
165
    int     i, ncomps = pcs->params.icc.picc_info->num_components;
 
166
 
 
167
    for (i = 0; i < ncomps; ++i)
 
168
        pcc->paint.values[i] = 0.0;
 
169
 
 
170
    /* make sure that [ 0, ... 0] is in range */
 
171
    gx_restrict_CIEICC(pcc, pcs);
 
172
}
 
173
 
 
174
/*
 
175
 * Restrict an color to the range specified for an ICCBased color space.
 
176
 */
 
177
static void
 
178
gx_restrict_CIEICC(gs_client_color * pcc, const gs_color_space * pcs)
 
179
{
 
180
    int                 i, ncomps = pcs->params.icc.picc_info->num_components;
 
181
    const gs_range *    ranges = pcs->params.icc.picc_info->Range.ranges;
 
182
 
 
183
    for (i = 0; i < ncomps; ++i) {
 
184
        floatp  v = pcc->paint.values[i];
 
185
        floatp  rmin = ranges[i].rmin, rmax = ranges[i].rmax;
 
186
 
 
187
        if (v < rmin)
 
188
            pcc->paint.values[i] = rmin;
 
189
        else if (v > rmax)
 
190
            pcc->paint.values[i] = rmax;
 
191
    }
 
192
}
 
193
 
 
194
/*
 
195
 * Return the conrecte space to which this color space will map. If the
 
196
 * ICCBased color space is being used in native mode, the concrete space
 
197
 * will be dependent on the current color rendering dictionary, as it is
 
198
 * for all CIE bases. If the alternate color space is being used, then
 
199
 * this question is passed on the the appropriate method of that space.
 
200
 */
 
201
static const gs_color_space *
 
202
gx_concrete_space_CIEICC(const gs_color_space * pcs, const gs_imager_state * pis)
 
203
{
 
204
    if (pcs->params.icc.picc_info->picc == NULL) {
 
205
        const gs_color_space *  pacs = pcs->base_space;
 
206
 
 
207
        return cs_concrete_space(pacs, pis);
 
208
    } else
 
209
        return gx_concrete_space_CIE(NULL, pis);
 
210
}
 
211
 
 
212
/*
 
213
 * Convert an ICCBased color space to a concrete color space.
 
214
 */
 
215
static int
 
216
gx_concretize_CIEICC(
 
217
    const gs_client_color * pcc,
 
218
    const gs_color_space *  pcs,
 
219
    frac *                  pconc,
 
220
    const gs_imager_state * pis )
 
221
{
 
222
    const gs_icc_params *   picc_params = &pcs->params.icc;
 
223
    const gs_cie_icc *      picc_info = picc_params->picc_info;
 
224
    stream *                instrp = picc_info->instrp;
 
225
    icc *                   picc = picc_info->picc;
 
226
    double                  inv[4], outv[3];
 
227
    cie_cached_vector3      vlmn;
 
228
    gs_client_color         lcc = *pcc;
 
229
    int                     i, ncomps = picc_info->num_components;
 
230
    int code;
 
231
 
 
232
    /* use the altenate space concretize if appropriate */
 
233
    if (picc == NULL)
 
234
        return pcs->base_space->type->concretize_color(
 
235
                            pcc,
 
236
                            pcs->base_space,
 
237
                            pconc,
 
238
                            pis );
 
239
 
 
240
    /* set up joint cache as required */
 
241
    code = gx_cie_check_rendering(pcs, pconc, pis);
 
242
    if (code < 0)
 
243
        return code;
 
244
    if (code == 1)
 
245
        return 0;
 
246
 
 
247
    /* verify and update the stream pointer */
 
248
    if (picc_info->file_id != (instrp->read_id | instrp->write_id))
 
249
        return_error(gs_error_ioerror);
 
250
    ((icmFileGs *)picc->fp)->strp = instrp;
 
251
 
 
252
    /* translate the input components */
 
253
    gx_restrict_CIEICC(&lcc, pcs);
 
254
    for (i = 0; i < ncomps; i++)
 
255
        inv[i] = lcc.paint.values[i];
 
256
                
 
257
        /* Since the original limits were wrong for this case, We need to adjust things a bit different */
 
258
 
 
259
    /* For input Lab color space massage the values into Lab range */
 
260
 
 
261
   /* if (picc_info->plu->e_inSpace == icSigLabData) {
 
262
 
 
263
        inv[0] *= 100;
 
264
        inv[1] = inv[1]*255 - 128;
 
265
        inv[2] = inv[2]*255 - 128; 
 
266
 
 
267
    } */
 
268
 
 
269
    /*
 
270
     * Perform the lookup operation. A return value of 1 indicates that
 
271
     * clipping occurred somewhere in the operation, but the result is
 
272
     * legitimate. Other non-zero return values indicate an error, which
 
273
     * should not occur in practice.
 
274
     */
 
275
 
 
276
    if (picc_info->plu->lookup(picc_info->plu, outv, inv) > 1)
 
277
        return_error(gs_error_unregistered);
 
278
 
 
279
    /* if the output is in the CIE L*a*b* space, convert to XYZ */
 
280
    if (picc_info->pcs_is_cielab) {
 
281
        floatp              f[3];
 
282
        const gs_vector3 *  pwhtpt = &picc_info->common.points.WhitePoint;
 
283
 
 
284
 
 
285
        f[1] = (outv[0] + 16.0) / 116.0;
 
286
        f[0] = f[1] + outv[1] / 500.0;
 
287
        f[2] = f[1] - outv[2] / 200;
 
288
 
 
289
        for (i = 0; i < 3; i++) {
 
290
            if (f[i] >= 6.0 / 29.0)
 
291
                outv[i] = f[i] * f[i] * f[i];
 
292
            else
 
293
                outv[i] = 108.0 * (f[i] - 4.0 / 29.0) / 841.0;
 
294
        }
 
295
 
 
296
        /*
 
297
         * The connection space white-point is known to be D50, but we
 
298
         * use the more general form in case of future revisions.
 
299
         */
 
300
        outv[0] *= pwhtpt->u;
 
301
        outv[1] *= pwhtpt->v;
 
302
        outv[2] *= pwhtpt->w;
 
303
    }
 
304
 
 
305
    /* translate the output */
 
306
    vlmn.u = float2cie_cached(outv[0]);
 
307
    vlmn.v = float2cie_cached(outv[1]);
 
308
    vlmn.w = float2cie_cached(outv[2]);
 
309
 
 
310
    gx_cie_remap_finish(vlmn, pconc, pis, pcs);
 
311
    return 0;
 
312
}
 
313
 
 
314
#if ENABLE_CUSTOM_COLOR_CALLBACK
 
315
/*
 
316
 * This routine is only used if ENABLE_CUSTOM_COLOR_CALLBACK is true.
 
317
 * Otherwise we use gx_default_remap_color directly for CIEBasedDEFG color
 
318
 * spaces.
 
319
 *
 
320
 * Render a CIEBasedDEFG color.
 
321
 */
 
322
int
 
323
gx_remap_ICCBased(const gs_client_color * pc, const gs_color_space * pcs,
 
324
        gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
 
325
                gs_color_select_t select)
 
326
{
 
327
    client_custom_color_params_t * pcb =
 
328
            (client_custom_color_params_t *) (pis->memory->gs_lib_ctx->custom_color_callback);
 
329
 
 
330
    if (pcb != NULL) {
 
331
        if (pcb->client_procs->remap_ICCBased(pcb, pc, pcs,
 
332
                                                pdc, pis, dev, select) == 0)
 
333
            return 0;
 
334
    }
 
335
    /* Use default routine for non custom color processing. */
 
336
    return gx_default_remap_color(pc, pcs, pdc, pis, dev, select);
 
337
}
 
338
#endif
 
339
 
 
340
/*
 
341
 * Finalize the contents of an ICC color space. Now that color space
 
342
 * objects have straightforward reference counting discipline, there's
 
343
 * nothing special about it. In the previous state of affairs, the
 
344
 * argument in favor of correct reference counting spoke of "an
 
345
 * unintuitive but otherwise legitimate state of affairs".
 
346
 */
 
347
static void
 
348
gx_final_CIEICC(const gs_color_space * pcs)
 
349
{
 
350
    rc_decrement_only(pcs->params.icc.picc_info, "gx_final_CIEICC");
 
351
}
 
352
 
 
353
static int
 
354
icmFileGs_seek(icmFile *pp, long int offset)
 
355
{
 
356
    icmFileGs *p = (icmFileGs *)pp;
 
357
 
 
358
    return spseek(p->strp, offset);
 
359
}
 
360
 
 
361
static size_t
 
362
icmFileGs_read(icmFile *pp, void *buffer, size_t size, size_t count)
 
363
{
 
364
    icmFileGs *p = (icmFileGs *)pp;
 
365
    uint    tot;
 
366
    int     status = sgets(p->strp, buffer, size * count, &tot);
 
367
 
 
368
    return (status < 0) ? status : tot;
 
369
}
 
370
 
 
371
static size_t
 
372
icmFileGs_write(icmFile *pp, void *buffer, size_t size, size_t count)
 
373
{
 
374
    icmFileGs *p = (icmFileGs *)pp;
 
375
    uint    tot;
 
376
    int     status = sputs(p->strp, buffer, size * count, &tot);
 
377
 
 
378
    return (status < 0) ? status : tot;
 
379
}
 
380
 
 
381
static int
 
382
icmFileGs_flush(icmFile *pp)
 
383
{
 
384
    icmFileGs *p = (icmFileGs *)pp;
 
385
 
 
386
    return s_std_write_flush(p->strp);
 
387
}
 
388
 
 
389
static int
 
390
icmFileGs_delete(icmFile *pp)
 
391
{
 
392
    free(pp);
 
393
    return 0;
 
394
}
 
395
 
 
396
/**
 
397
 * gx_wrap_icc_stream: Wrap a Ghostscript stream as an icclib file.
 
398
 * @strp: The Ghostscript stream.
 
399
 *
 
400
 * Creates an icmFile object that wraps @stream.
 
401
 *
 
402
 * Note: the memory for this object is allocated using malloc, and the
 
403
 * relocation of the stream pointer is done lazily, before an icclu
 
404
 * operation. It would probably be cleaner to allocate the icmFile in
 
405
 * garbage collected memory, and have the relocation happen there, but
 
406
 * I wanted to minimally modify Jan's working code.
 
407
 *
 
408
 * Return value: the stream wrapped as an icmFile object, or NULL on
 
409
 * error.
 
410
 **/
 
411
static icmFile *
 
412
gx_wrap_icc_stream(stream *strp)
 
413
{
 
414
    icmFileGs *p;
 
415
 
 
416
    if ((p = (icmFileGs *) calloc(1,sizeof(icmFileGs))) == NULL)
 
417
        return NULL;
 
418
    p->seek  = icmFileGs_seek;
 
419
    p->read  = icmFileGs_read;
 
420
    p->write = icmFileGs_write;
 
421
    p->flush = icmFileGs_flush;
 
422
    p->del   = icmFileGs_delete;
 
423
 
 
424
    p->strp = strp;
 
425
 
 
426
    return (icmFile *)p;
 
427
}
 
428
 
 
429
int
 
430
gx_load_icc_profile(gs_cie_icc *picc_info)
 
431
{
 
432
    stream *        instrp = picc_info->instrp;
 
433
    icc *           picc;
 
434
    icmLuBase * plu = NULL;
 
435
    icmFile *pfile = NULL;
 
436
 
 
437
#if   SAVEICCPROFILE
 
438
 
 
439
    unsigned int num_bytes;
 
440
    unsigned char *iccbuffer;
 
441
    FILE *fid;
 
442
 
 
443
#endif
 
444
        
 
445
    /* verify that the file is legitimate */
 
446
    if (picc_info->file_id != (instrp->read_id | instrp->write_id))
 
447
        return_error(gs_error_ioerror);
 
448
    /*
 
449
     * Load the top-level ICC profile.
 
450
     *
 
451
     * If an ICC profile fails to load, generate an error.
 
452
     * 
 
453
     * Testing demonstrates, however, Acrobat Reader silently
 
454
     * ignores the error and uses the alternate color space.
 
455
     * This behaviour is implemented by catching the error using
 
456
     * a stopped context from within the interpreter (gs_icc.ps).
 
457
     *
 
458
     * Failure to allocate the top-level profile object is considered
 
459
     * a limitcheck rather than a VMerror, as profile data structures
 
460
     * are stored in "foreign" memory.
 
461
     */
 
462
    if ((picc = new_icc()) == NULL)
 
463
        return_error(gs_error_limitcheck);
 
464
    {
 
465
        icProfileClassSignature profile_class;
 
466
        icColorSpaceSignature   cspace_type;
 
467
        gs_vector3 *            ppt;
 
468
 
 
469
        pfile = gx_wrap_icc_stream (instrp);
 
470
      
 
471
        if ((picc->read(picc, pfile, 0)) != 0)
 
472
            goto return_rangecheck;
 
473
 
 
474
#if SAVEICCPROFILE
 
475
 
 
476
        num_bytes = picc->header->size;
 
477
        iccbuffer = (unsigned char *) malloc(num_bytes);
 
478
        pfile->seek(pfile,0);
 
479
        pfile->read(pfile,iccbuffer,1,num_bytes);
 
480
        fid = fopen("DumpedICC.icm","wb");
 
481
        fwrite(iccbuffer,sizeof(unsigned char),num_bytes,fid);
 
482
        fclose(fid);
 
483
        free(iccbuffer);
 
484
 
 
485
#endif
 
486
        
 
487
            
 
488
        /* verify the profile type */
 
489
        profile_class = picc->header->deviceClass;
 
490
        if ( profile_class != icSigInputClass     &&
 
491
             profile_class != icSigDisplayClass   &&
 
492
             profile_class != icSigOutputClass    &&
 
493
             profile_class != icSigColorSpaceClass  )
 
494
            goto return_rangecheck;
 
495
 
 
496
        /* verify the profile connection space */
 
497
        cspace_type = picc->header->pcs;
 
498
        if (cspace_type == icSigLabData)
 
499
            picc_info->pcs_is_cielab = true;
 
500
        else if (cspace_type == icSigXYZData)
 
501
            picc_info->pcs_is_cielab = false;
 
502
        else
 
503
            goto return_rangecheck;
 
504
 
 
505
        /* verify the source color space */
 
506
        cspace_type = picc->header->colorSpace;
 
507
        if (cspace_type == icSigCmykData) {
 
508
            if (picc_info->num_components != 4)
 
509
                goto return_rangecheck;
 
510
        } else if ( cspace_type == icSigRgbData ||
 
511
                    cspace_type == icSigLabData   ) {
 
512
            if (picc_info->num_components != 3)
 
513
                goto return_rangecheck;
 
514
        } else if (cspace_type == icSigGrayData) {
 
515
            if (picc_info->num_components != 1)
 
516
                goto return_rangecheck;
 
517
        }
 
518
 
 
519
        /*
 
520
         * Fetch the lookup object.
 
521
         *
 
522
         * PostScript and PDF deal with rendering intent as strictly a
 
523
         * rendering dictionary facility. ICC profiles allow a rendering
 
524
         * intent to be specified for both the input (device ==> pcs) and
 
525
         * output (pcs ==> device) operations. Hence, when using ICCBased
 
526
         * color spaces with PDF, no clue is provided as to which source
 
527
         * mapping to select.
 
528
         *
 
529
         * In the absence of other information, there are two possible
 
530
         * selections. If our understanding is correct, when relative
 
531
         * colorimetry is specified, the icclib code will map source
 
532
         * color values to XYZ or L*a*b* values such that the relationship
 
533
         * of the source color, relative to the source white and black
 
534
         * points, will be the same as the output colors and the
 
535
         * profile connection space illuminant (currently always D50)
 
536
         * and pure black ([0, 0, 0]). In this case, the white and black
 
537
         * points that should be listed in the color space are the
 
538
         * profile connection space illuminant (D50) and pure black.
 
539
         *
 
540
         * If absolute colorimetry is employed, the XYZ or L*a*b* values
 
541
         * generated will be absolute in the chromatic sense (they are
 
542
         * not literally "absolute", as we still must have overall
 
543
         * intensity information inorder to determine weighted spectral
 
544
         * power levels). To achieve relative colorimetry for the output,
 
545
         * these colors must be evaluated relative to the source white
 
546
         * and black points. Hence, in this case, the appropriate white
 
547
         * and black points to list in the color space are the source
 
548
         * white and black points provided in the profile tag array.
 
549
         *
 
550
         * In this implementation, we will always request relative
 
551
         * colorimetry from the icclib, and so will use the profile
 
552
         * connection space illuminant and pure black as the white and
 
553
         * black points of the color space. This approach is somewhat
 
554
         * simpler, as it allows the color space white point to also
 
555
         * be used for L*a*b* to XYZ conversion (otherwise we would
 
556
         * need to store the profile connection space illuminant
 
557
         * separately for that purpose). The approach does reduce to
 
558
         * to some extent the range of mappings that can be achieved
 
559
         * via the color rendering dictionary, but for now we believe
 
560
         * this loss is not significant.
 
561
         *
 
562
         * For reasons that are not clear to us, the icclib code does
 
563
         * not support relative colorimetry for all color profiles. For
 
564
         * this reason, we specify icmDefaultIntent rather than
 
565
         * icRelativeColormetric.
 
566
         *
 
567
         * NB: We are not color experts; our understanding of this area
 
568
         *     may well be incorrect.
 
569
         */
 
570
        plu = picc->get_luobj( picc,
 
571
                               icmFwd,
 
572
                               icmDefaultIntent,
 
573
                               0, /* PCS override */
 
574
                               icmLuOrdNorm );
 
575
        if (plu == NULL)
 
576
            goto return_rangecheck;
 
577
 
 
578
        /* 
 
579
         * Get the appropriate white and black points. See the note on
 
580
         * rendering intent above for a discussion of why we are using
 
581
         * the profile space illuminant and pure black. (Pure black need
 
582
         * not be set explicitly, as it is the default.)
 
583
         */
 
584
        ppt = &picc_info->common.points.WhitePoint;
 
585
        ppt->u = picc->header->illuminant.X;
 
586
        ppt->v = picc->header->illuminant.Y;
 
587
        ppt->w = picc->header->illuminant.Z;
 
588
 
 
589
        picc_info->picc = picc;
 
590
        picc_info->plu = plu;
 
591
        picc_info->pfile = pfile;
 
592
    }
 
593
 
 
594
    return 0;
 
595
 
 
596
 return_rangecheck:
 
597
    if (plu != NULL)
 
598
        plu->del(plu);
 
599
    if (picc != NULL)
 
600
        picc->del(picc);
 
601
    if (pfile != NULL)
 
602
        pfile->del(pfile);
 
603
    return_error(gs_error_rangecheck);
 
604
}
 
605
 
 
606
/*
 
607
 * Install an ICCBased color space.
 
608
 *
 
609
 * Note that an ICCBased color space must be installed before it is known if
 
610
 * the ICC profile or the alternate color space is to be used.
 
611
 */
 
612
static int
 
613
gx_install_CIEICC(gs_color_space * pcs, gs_state * pgs)
 
614
{
 
615
    const gs_icc_params * picc_params = (const gs_icc_params *)&pcs->params.icc;
 
616
    gs_cie_icc *    picc_info = picc_params->picc_info;
 
617
 
 
618
#if ENABLE_CUSTOM_COLOR_CALLBACK
 
619
    {
 
620
        /*
 
621
         * Check if we want to use the callback color processing for this
 
622
         * color space.
 
623
         */
 
624
        client_custom_color_params_t * pcb =
 
625
            (client_custom_color_params_t *) pgs->memory->gs_lib_ctx->custom_color_callback;
 
626
 
 
627
        if (pcb != NULL) {
 
628
            if (pcb->client_procs->install_ICCBased(pcb, pcs, pgs))
 
629
                /* Exit if the client will handle the colorspace completely */
 
630
                return 0;
 
631
        }
 
632
    }
 
633
#endif
 
634
    /* update the stub information used by the joint caches */
 
635
    gx_cie_load_common_cache(&picc_info->common, pgs);
 
636
    gx_cie_common_complete(&picc_info->common);
 
637
    return gs_cie_cs_complete(pgs, true);
 
638
}
 
639
 
 
640
 
 
641
/*
 
642
 * Constructor for ICCBased color space. As with the other color space
 
643
 * constructors, this provides only minimal initialization.
 
644
 */
 
645
int
 
646
gs_cspace_build_CIEICC(
 
647
    gs_color_space **   ppcspace,
 
648
    void *              client_data,
 
649
    gs_memory_t *       pmem )
 
650
{
 
651
    gs_cie_icc *        picc_info;
 
652
    gs_color_space *    pcs;
 
653
 
 
654
    /*
 
655
     * The gs_cie_icc_s structure is the only CIE-based color space structure
 
656
     * which accesses additional memory for which it is responsible. We make
 
657
     * use of the finalization procedure to handle this task, so we can use
 
658
     * the generic CIE space build routine (otherwise we would need a
 
659
     * separate build routine that provided its own reference count freeing
 
660
     * procedure).
 
661
     */
 
662
    picc_info = gx_build_cie_space( ppcspace,
 
663
                                    &gs_color_space_type_CIEICC,
 
664
                                    &st_cie_icc,
 
665
                                    pmem );
 
666
 
 
667
    if (picc_info == NULL)
 
668
        return_error(gs_error_VMerror);
 
669
 
 
670
    gx_set_common_cie_defaults(&picc_info->common, client_data);
 
671
    /*
 
672
     * Now set the D50 WhitePoint. The above function does not set any
 
673
     * valid WhitepPoint since PostScript always requires this, but ICC
 
674
     * assumes a D50 WhitePoint as a default
 
675
     */
 
676
    picc_info->common.points.WhitePoint.u = (float)0.9642;              /* Profile illuminant - D50 */
 
677
    picc_info->common.points.WhitePoint.v = 1.0000;
 
678
    picc_info->common.points.WhitePoint.w = (float)0.8249;
 
679
    picc_info->common.install_cspace = gx_install_CIEICC;
 
680
    picc_info->num_components = 0;
 
681
    picc_info->Range = Range4_default;
 
682
    picc_info->instrp = NULL;
 
683
    picc_info->pcs_is_cielab = false;
 
684
    picc_info->picc = NULL;
 
685
    picc_info->plu = NULL;
 
686
    picc_info->pfile = NULL;
 
687
 
 
688
    pcs = *ppcspace;
 
689
    pcs->params.icc.picc_info = picc_info;
 
690
    return 0;
 
691
}
 
692
 
 
693
/* ---------------- Serialization. -------------------------------- */
 
694
 
 
695
static int 
 
696
gx_serialize_CIEICC(const gs_color_space * pcs, stream * s)
 
697
{
 
698
    const gs_icc_params * p = &pcs->params.icc;
 
699
    gs_cie_icc *picc = p->picc_info;
 
700
    uint n;
 
701
    int code = gx_serialize_cspace_type(pcs, s);
 
702
    long avail, pos, count;
 
703
    byte buf[100];
 
704
 
 
705
    if (code < 0)
 
706
        return code;
 
707
    code = gx_serialize_cie_common_elements(pcs, s);
 
708
    if (code < 0)
 
709
        return code;
 
710
    code = sputs(s, (byte *)&picc->num_components, sizeof(picc->num_components), &n);
 
711
    if (code < 0)
 
712
        return code;
 
713
    code = sputs(s, (byte *)&picc->Range, sizeof(picc->Range), &n);
 
714
    if (code < 0)
 
715
        return code;
 
716
    if (sseek(picc->instrp, 0) < 0)
 
717
        return_error(gs_error_unregistered); /* Unimplemented. */
 
718
    if (savailable(picc->instrp, &avail) != 0)
 
719
        return_error(gs_error_unregistered); /* Unimplemented. */
 
720
    code = sputs(s, (byte *)&avail, sizeof(avail), &n);
 
721
    if (code < 0)
 
722
        return code;
 
723
    for (pos = 0; pos < avail; pos += count) {
 
724
        count = min(sizeof(buf), avail - pos);
 
725
        code = sgets(picc->instrp, buf, count, &n);
 
726
        if (code < 0)
 
727
            return code;
 
728
        code = sputs(s, buf, count, &n);
 
729
        if (code < 0)
 
730
            return code;
 
731
    }
 
732
    return sputs(s, (byte *)&picc->pcs_is_cielab, sizeof(picc->pcs_is_cielab), &n);
 
733
}