1 /* Copyright (C) 2001-2012 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.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* CIE color space management */
18 #include "math_.h"
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsstruct.h"
22 #include "gsmatrix.h"		/* for gscolor2.h */
23 #include "gxcspace.h"
24 #include "gscolor2.h"		/* for gs_set/currentcolorrendering */
25 #include "gxcie.h"
26 #include "gxarith.h"
27 #include "gxdevice.h"		/* for gxcmap.h */
28 #include "gxcmap.h"
29 #include "gzstate.h"
30 #include "stream.h"
31 
32 /* ---------------- Color space definition ---------------- */
33 
34 /* GC descriptors */
35 public_st_cie_common();
36 public_st_cie_common_elements();
37 private_st_cie_a();
38 private_st_cie_abc();
39 private_st_cie_def();
40 private_st_cie_defg();
41 
42 /* Define the CIE color space types. */
43 
44 /* CIEBasedDEFG */
45 gs_private_st_ptrs1(st_color_space_CIEDEFG, gs_color_space,
46      "gs_color_space(CIEDEFG)", cs_CIEDEFG_enum_ptrs, cs_CIEDEFG_reloc_ptrs,
47                     params.defg);
48 static cs_proc_final(gx_final_CIEDEFG);
49 static cs_proc_serialize(gx_serialize_CIEDEFG);
50 const gs_color_space_type gs_color_space_type_CIEDEFG = {
51     gs_color_space_index_CIEDEFG, true, true,
52     &st_color_space_CIEDEFG, gx_num_components_4,
53     gx_init_CIE, gx_restrict_CIEDEFG,
54     gx_concrete_space_CIE,
55     gx_concretize_CIEDEFG, NULL,
56     gx_remap_CIEDEFG,
57     gx_install_CIE,
58     gx_spot_colors_set_overprint,
59     gx_final_CIEDEFG, gx_no_adjust_color_count,
60     gx_serialize_CIEDEFG,
61     gx_cspace_is_linear_default
62 };
63 
64 /* CIEBasedDEF */
65 gs_private_st_ptrs1(st_color_space_CIEDEF, gs_color_space,
66         "gs_color_space(CIEDEF)", cs_CIEDEF_enum_ptrs, cs_CIEDEF_reloc_ptrs,
67                     params.def);
68 static cs_proc_final(gx_final_CIEDEF);
69 static cs_proc_serialize(gx_serialize_CIEDEF);
70 const gs_color_space_type gs_color_space_type_CIEDEF = {
71     gs_color_space_index_CIEDEF, true, true,
72     &st_color_space_CIEDEF, gx_num_components_3,
73     gx_init_CIE, gx_restrict_CIEDEF,
74     gx_concrete_space_CIE,
75     gx_concretize_CIEDEF, NULL,
76     gx_remap_CIEDEF,
77     gx_install_CIE,
78     gx_spot_colors_set_overprint,
79     gx_final_CIEDEF, gx_no_adjust_color_count,
80     gx_serialize_CIEDEF,
81     gx_cspace_is_linear_default
82 };
83 
84 /* CIEBasedABC */
85 gs_private_st_ptrs1(st_color_space_CIEABC, gs_color_space,
86         "gs_color_space(CIEABC)", cs_CIEABC_enum_ptrs, cs_CIEABC_reloc_ptrs,
87                     params.abc);
88 static cs_proc_final(gx_final_CIEABC);
89 static cs_proc_serialize(gx_serialize_CIEABC);
90 const gs_color_space_type gs_color_space_type_CIEABC = {
91     gs_color_space_index_CIEABC, true, true,
92     &st_color_space_CIEABC, gx_num_components_3,
93     gx_init_CIE, gx_restrict_CIEABC,
94     gx_concrete_space_CIE,
95     gx_concretize_CIEABC, NULL,
96     gx_remap_CIEABC, gx_install_CIE,
97     gx_spot_colors_set_overprint,
98     gx_final_CIEABC, gx_no_adjust_color_count,
99     gx_serialize_CIEABC,
100     gx_cspace_is_linear_default
101 };
102 
103 /* CIEBasedA */
104 gs_private_st_ptrs1(st_color_space_CIEA, gs_color_space,
105               "gs_color_space(CIEA)", cs_CIEA_enum_ptrs, cs_CIEA_reloc_ptrs,
106                     params.a);
107 static cs_proc_final(gx_final_CIEA);
108 static cs_proc_serialize(gx_serialize_CIEA);
109 const gs_color_space_type gs_color_space_type_CIEA = {
110     gs_color_space_index_CIEA, true, true,
111     &st_color_space_CIEA, gx_num_components_1,
112     gx_init_CIE, gx_restrict_CIEA,
113     gx_concrete_space_CIE,
114     gx_concretize_CIEA, NULL,
115     gx_remap_CIEA,
116     gx_install_CIE,
117     gx_spot_colors_set_overprint,
118     gx_final_CIEA, gx_no_adjust_color_count,
119     gx_serialize_CIEA,
120     gx_cspace_is_linear_default
121 };
122 
123 /* Determine the concrete space underlying a CIEBased space. */
124 const gs_color_space *
gx_concrete_space_CIE(const gs_color_space * pcs,const gs_imager_state * pis)125 gx_concrete_space_CIE(const gs_color_space * pcs, const gs_imager_state * pis)
126 {
127     const gs_cie_render *pcie = pis->cie_render;
128 
129     if (pcie == 0 || pcie->RenderTable.lookup.table == 0 ||
130         pcie->RenderTable.lookup.m == 3
131         ) {
132         return pis->devicergb_cs;
133     } else {			/* pcie->RenderTable.lookup.m == 4 */
134         return pis->devicecmyk_cs;
135     }
136 }
137 
138 /* Install a CIE space in the graphics state. */
139 /* We go through an extra level of procedure so that */
140 /* interpreters can substitute their own installer. */
141 /* This procedure is exported for the benefit of gsicc.c */
142 int
gx_install_CIE(gs_color_space * pcs,gs_state * pgs)143 gx_install_CIE(gs_color_space * pcs, gs_state * pgs)
144 {
145     return (*pcs->params.a->common.install_cspace) (pcs, pgs);
146 }
147 
148 /* Free params for a CIE color space */
149 static void
gx_final_CIEDEFG(const gs_color_space * pcs)150 gx_final_CIEDEFG(const gs_color_space * pcs)
151 {
152     gs_color_space *pcs_noconst = (gs_color_space *)pcs;
153 
154     if (pcs->icc_equivalent != NULL) {
155         rc_decrement(pcs_noconst->icc_equivalent, "gx_final_CIEDEFG");
156     }
157     if (pcs->cmm_icc_profile_data != NULL) {
158         rc_decrement(pcs_noconst->cmm_icc_profile_data, "gx_final_CIEDEFG");
159     }
160     rc_decrement(pcs_noconst->params.defg, "gx_final_CIEDEFG");
161 }
162 
163 static void
gx_final_CIEDEF(const gs_color_space * pcs)164 gx_final_CIEDEF(const gs_color_space * pcs)
165 {
166     gs_color_space *pcs_noconst = (gs_color_space *)pcs;
167 
168     if (pcs->icc_equivalent != NULL) {
169         rc_decrement(pcs_noconst->icc_equivalent,"gx_final_CIEDEF");
170     }
171     if (pcs->cmm_icc_profile_data != NULL) {
172         rc_decrement(pcs_noconst->cmm_icc_profile_data, "gx_final_CIEDEF");
173     }
174     rc_decrement(pcs_noconst->params.def, "gx_final_CIEDEF");
175 }
176 
177 static void
gx_final_CIEABC(const gs_color_space * pcs)178 gx_final_CIEABC(const gs_color_space * pcs)
179 {
180     gs_color_space *pcs_noconst = (gs_color_space *)pcs;
181 
182     if (pcs->icc_equivalent != NULL) {
183         rc_decrement(pcs_noconst->icc_equivalent,"gx_final_CIEABC");
184     }
185     if (pcs->cmm_icc_profile_data != NULL) {
186         rc_decrement(pcs_noconst->cmm_icc_profile_data, "gx_final_CIEABC");
187     }
188     rc_decrement(pcs_noconst->params.abc, "gx_final_CIEABC");
189 }
190 
191 static void
gx_final_CIEA(const gs_color_space * pcs)192 gx_final_CIEA(const gs_color_space * pcs)
193 {
194     gs_color_space *pcs_noconst = (gs_color_space *)pcs;
195 
196     if (pcs->icc_equivalent != NULL) {
197         rc_decrement(pcs_noconst->icc_equivalent,"gx_final_CIEA");
198     }
199     if (pcs->cmm_icc_profile_data != NULL) {
200         rc_decrement(pcs_noconst->cmm_icc_profile_data, "gx_final_CIEA");
201     }
202     rc_decrement(pcs_noconst->params.a, "gx_adjust_cspace_CIEA");
203 }
204 
205 /* ---------------- Procedures ---------------- */
206 
207 /* ------ Internal initializers ------ */
208 
209 /*
210  * Set up the default values for the CIE parameters that are common to
211  * all CIE color spaces.
212  *
213  * There is no default for the white point, so it is set equal to the
214  * black point. If anyone actually uses the color space in that form,
215  * the results are likely to be unsatisfactory.
216  *
217  * This procedure is exported for the benefit of gsicc.c.
218  */
219 void
gx_set_common_cie_defaults(gs_cie_common * pcommon,void * client_data)220 gx_set_common_cie_defaults(gs_cie_common * pcommon, void *client_data)
221 {
222     pcommon->RangeLMN = Range3_default;
223     pcommon->DecodeLMN = DecodeLMN_default;
224     pcommon->MatrixLMN = Matrix3_default;
225     pcommon->points.WhitePoint = BlackPoint_default;
226     pcommon->points.BlackPoint = BlackPoint_default;
227     pcommon->client_data = client_data;
228 }
229 
230 /*
231  * Set defaults for a CIEBasedABC color space.  This is also used for
232  * CIEBasedDEF and CIEBasedDEFG color spaces.
233  */
234 static void
set_cie_abc_defaults(gs_cie_abc * pabc,void * client_data)235 set_cie_abc_defaults(gs_cie_abc * pabc, void *client_data)
236 {
237     gx_set_common_cie_defaults(&pabc->common, client_data);
238     pabc->RangeABC = Range3_default;
239     pabc->DecodeABC = DecodeABC_default;
240     pabc->MatrixABC = Matrix3_default;
241 }
242 
243 /*
244  * Set up a default color lookup table for a CIEBasedDEF[G] space. There is
245  * no specified default for this structure, so the values used here (aside
246  * from the input and output component numbers) are intended only to make
247  * the system fail in a predictable manner.
248  */
249 static void
set_ctbl_defaults(gx_color_lookup_table * plktblp,int num_comps)250 set_ctbl_defaults(gx_color_lookup_table * plktblp, int num_comps)
251 {
252     int i;
253 
254     plktblp->n = num_comps;
255     plktblp->m = 3;		/* always output CIE ABC */
256     for (i = 0; i < countof(plktblp->dims); i++)
257         plktblp->dims[i] = 0;
258     plktblp->table = 0;
259 }
260 
261 /*
262  * Allocate a color space and its parameter structure.
263  * Return 0 if VMerror, otherwise the parameter structure.
264  *
265  * This is exported for the benefit of gsicc.c
266  */
267 void *
gx_build_cie_space(gs_color_space ** ppcspace,const gs_color_space_type * pcstype,gs_memory_type_ptr_t stype,gs_memory_t * pmem)268 gx_build_cie_space(gs_color_space ** ppcspace,
269                 const gs_color_space_type * pcstype,
270                 gs_memory_type_ptr_t stype, gs_memory_t * pmem)
271 {
272     gs_color_space *pcspace = gs_cspace_alloc(pmem, pcstype);
273     gs_cie_common_elements_t *pdata;
274 
275     if (pcspace == NULL)
276         return NULL;
277     rc_alloc_struct_1(pdata, gs_cie_common_elements_t, stype, pmem,
278                       {
279                       gs_free_object(pmem, pcspace, "gx_build_cie_space");
280                       return 0;
281                       }
282                       ,
283                       "gx_build_cie_space(data)");
284     *ppcspace = pcspace;
285     return (void *)pdata;
286 }
287 
288 /* ------ Constructors ------ */
289 
290 int
gs_cspace_build_CIEA(gs_color_space ** ppcspace,void * client_data,gs_memory_t * pmem)291 gs_cspace_build_CIEA(gs_color_space ** ppcspace, void *client_data,
292                      gs_memory_t * pmem)
293 {
294     gs_cie_a *pciea =
295     gx_build_cie_space(ppcspace, &gs_color_space_type_CIEA, &st_cie_a, pmem);
296 
297     if (pciea == 0)
298         return_error(gs_error_VMerror);
299 
300     gx_set_common_cie_defaults(&pciea->common, client_data);
301     pciea->common.install_cspace = gx_install_CIEA;
302     pciea->RangeA = RangeA_default;
303     pciea->DecodeA = DecodeA_default;
304     pciea->MatrixA = MatrixA_default;
305 
306     (*ppcspace)->params.a = pciea;
307     return 0;
308 }
309 
310 int
gs_cspace_build_CIEABC(gs_color_space ** ppcspace,void * client_data,gs_memory_t * pmem)311 gs_cspace_build_CIEABC(gs_color_space ** ppcspace, void *client_data,
312                        gs_memory_t * pmem)
313 {
314     gs_cie_abc *pabc =
315     gx_build_cie_space(ppcspace, &gs_color_space_type_CIEABC, &st_cie_abc,
316                        pmem);
317 
318     if (pabc == 0)
319         return_error(gs_error_VMerror);
320 
321     set_cie_abc_defaults(pabc, client_data);
322     pabc->common.install_cspace = gx_install_CIEABC;
323 
324     (*ppcspace)->params.abc = pabc;
325     return 0;
326 }
327 
328 int
gs_cspace_build_CIEDEF(gs_color_space ** ppcspace,void * client_data,gs_memory_t * pmem)329 gs_cspace_build_CIEDEF(gs_color_space ** ppcspace, void *client_data,
330                        gs_memory_t * pmem)
331 {
332     gs_cie_def *pdef =
333     gx_build_cie_space(ppcspace, &gs_color_space_type_CIEDEF, &st_cie_def,
334                        pmem);
335 
336     if (pdef == 0)
337         return_error(gs_error_VMerror);
338 
339     set_cie_abc_defaults((gs_cie_abc *) pdef, client_data);
340     pdef->common.install_cspace = gx_install_CIEDEF;
341     pdef->RangeDEF = Range3_default;
342     pdef->DecodeDEF = DecodeDEF_default;
343     pdef->RangeHIJ = Range3_default;
344     set_ctbl_defaults(&pdef->Table, 3);
345 
346     (*ppcspace)->params.def = pdef;
347     return 0;
348 }
349 
350 int
gs_cspace_build_CIEDEFG(gs_color_space ** ppcspace,void * client_data,gs_memory_t * pmem)351 gs_cspace_build_CIEDEFG(gs_color_space ** ppcspace, void *client_data,
352                         gs_memory_t * pmem)
353 {
354     gs_cie_defg *pdefg =
355     gx_build_cie_space(ppcspace, &gs_color_space_type_CIEDEFG, &st_cie_defg,
356                        pmem);
357 
358     if (pdefg == 0)
359         return_error(gs_error_VMerror);
360 
361     set_cie_abc_defaults((gs_cie_abc *) pdefg, client_data);
362     pdefg->common.install_cspace = gx_install_CIEDEFG;
363     pdefg->RangeDEFG = Range4_default;
364     pdefg->DecodeDEFG = DecodeDEFG_default;
365     pdefg->RangeHIJK = Range4_default;
366     set_ctbl_defaults(&pdefg->Table, 4);
367 
368     (*ppcspace)->params.defg = pdefg;
369     return 0;
370 }
371 
372 /* ------ Accessors ------ */
373 
374 int
gs_cie_defx_set_lookup_table(gs_color_space * pcspace,int * pdims,const gs_const_string * ptable)375 gs_cie_defx_set_lookup_table(gs_color_space * pcspace, int *pdims,
376                              const gs_const_string * ptable)
377 {
378     gx_color_lookup_table *plktblp;
379 
380     switch (gs_color_space_get_index(pcspace)) {
381         case gs_color_space_index_CIEDEF:
382             plktblp = &pcspace->params.def->Table;
383             break;
384         case gs_color_space_index_CIEDEFG:
385             plktblp = &pcspace->params.defg->Table;
386             plktblp->dims[3] = pdims[3];
387             break;
388         default:
389             return_error(gs_error_rangecheck);
390     }
391 
392     plktblp->dims[0] = pdims[0];
393     plktblp->dims[1] = pdims[1];
394     plktblp->dims[2] = pdims[2];
395     plktblp->table = ptable;
396     return 0;
397 }
398 
399 /* ---------------- Serialization. -------------------------------- */
400 
401 static int
gx_serialize_cie_cache(const cie_cache_floats * c,stream * s)402 gx_serialize_cie_cache(const cie_cache_floats *c, stream * s)
403 { /* p->DecodeA : */
404     const uint cache_size = count_of(c->values);
405     uint n;
406     int code;
407 
408     code = sputs(s, (const byte *)&c->params.is_identity, sizeof(c->params.is_identity), &n);
409     if (c->params.is_identity)
410         return 0;
411     code = sputs(s, (const byte *)&cache_size, sizeof(cache_size), &n);
412     if (code < 0)
413         return code;
414     return sputs(s, (const byte *)c->values, sizeof(c->values), &n);
415 }
416 
417 int
gx_serialize_cie_common_elements(const gs_color_space * pcs,stream * s)418 gx_serialize_cie_common_elements(const gs_color_space * pcs, stream * s)
419 {
420     const gs_cie_a * p = pcs->params.a;
421     uint n, k;
422     int code = gx_serialize_cspace_type(pcs, s);
423 
424     if (code < 0)
425         return code;
426     code = sputs(s, (const byte *)&p->common.RangeLMN,
427                         sizeof(p->common.RangeLMN), &n);
428     if (code < 0)
429         return code;
430     for (k = 0; k < 3 && code >= 0; k++)
431         code = gx_serialize_cie_cache(&p->common.caches.DecodeLMN[k].floats, s);
432     if (code < 0)
433         return code;
434     code = sputs(s, (const byte *)&p->common.MatrixLMN,
435                         sizeof(p->common.MatrixLMN), &n);
436     if (code < 0)
437         return code;
438     return sputs(s, (const byte *)&p->common.points,
439                         sizeof(p->common.points), &n);
440 }
441 
442 static int
gx_serialize_CIEA(const gs_color_space * pcs,stream * s)443 gx_serialize_CIEA(const gs_color_space * pcs, stream * s)
444 {
445     const gs_cie_a * p = pcs->params.a;
446     uint n;
447     int code = gx_serialize_cie_common_elements(pcs, s);
448 
449     if (code < 0)
450         return code;
451     code = sputs(s, (const byte *)&p->RangeA, sizeof(p->RangeA), &n);
452     if (code < 0)
453         return code;
454     code = gx_serialize_cie_cache(&p->caches.DecodeA.floats, s);
455     if (code < 0)
456         return code;
457     return sputs(s, (const byte *)&p->MatrixA, sizeof(p->MatrixA), &n);
458 }
459 
460 static int
gx_serialize_CIEABC(const gs_color_space * pcs,stream * s)461 gx_serialize_CIEABC(const gs_color_space * pcs, stream * s)
462 {
463     const gs_cie_abc * p = pcs->params.abc;
464     uint n, k;
465     int code = gx_serialize_cie_common_elements(pcs, s);
466 
467     if (code < 0)
468         return code;
469     code = sputs(s, (const byte *)&p->RangeABC, sizeof(p->RangeABC), &n);
470     if (code < 0)
471         return code;
472     code = sputs(s, (const byte *)&p->caches.skipABC, sizeof(p->caches.skipABC), &n);
473     if (code < 0)
474         return code;
475     if (p->caches.skipABC)
476         return 0;
477     for (k = 0; k < 3 && code >= 0; k++)
478         code = gx_serialize_cie_cache(&p->caches.DecodeABC.caches[k].floats, s);
479     if (code < 0)
480         return code;
481     return sputs(s, (const byte *)&p->MatrixABC, sizeof(p->MatrixABC), &n);
482 }
483 
484 static int
gx_serialize_lookup_table(const gx_color_lookup_table * t,stream * s)485 gx_serialize_lookup_table(const gx_color_lookup_table * t, stream * s)
486 {
487     uint n;
488     int code = sputs(s, (const byte *)&t->n, sizeof(t->n), &n);
489 
490     if (code < 0)
491         return code;
492     code = sputs(s, (const byte *)&t->dims[0], sizeof(t->dims[0]) * t->n, &n);
493     if (code < 0)
494         return code;
495     code = sputs(s, (const byte *)&t->m, sizeof(t->m), &n);
496     if (code < 0)
497         return code;
498     code = sputs(s, (const byte *)&t->table->size, sizeof(t->table->size), &n);
499     if (code < 0)
500         return code;
501     return sputs(s, (const byte *)&t->table->data, t->table->size, &n);
502 }
503 
504 static int
gx_serialize_CIEDEF(const gs_color_space * pcs,stream * s)505 gx_serialize_CIEDEF(const gs_color_space * pcs, stream * s)
506 {
507     const gs_cie_def * p = pcs->params.def;
508     uint n, k;
509     int code = gx_serialize_cie_common_elements(pcs, s);
510 
511     if (code < 0)
512         return code;
513     code = sputs(s, (const byte *)&p->RangeDEF, sizeof(p->RangeDEF), &n);
514     if (code < 0)
515         return code;
516     for (k = 0; k < 3 && code >= 0; k++)
517         code = gx_serialize_cie_cache(&p->caches_def.DecodeDEF[k].floats, s);
518     if (code < 0)
519         return code;
520     code = sputs(s, (const byte *)&p->RangeHIJ, sizeof(p->RangeHIJ), &n);
521     if (code < 0)
522         return code;
523     return gx_serialize_lookup_table(&p->Table, s);
524 }
525 
526 static int
gx_serialize_CIEDEFG(const gs_color_space * pcs,stream * s)527 gx_serialize_CIEDEFG(const gs_color_space * pcs, stream * s)
528 {
529     const gs_cie_defg * p = pcs->params.defg;
530     uint n, k;
531     int code = gx_serialize_cie_common_elements(pcs, s);
532 
533     if (code < 0)
534         return code;
535     code = sputs(s, (const byte *)&p->RangeDEFG, sizeof(p->RangeDEFG), &n);
536     if (code < 0)
537         return code;
538     for (k = 0; k < 3 && code >= 0; k++)
539         code = gx_serialize_cie_cache(&p->caches_defg.DecodeDEFG[k].floats, s);
540     if (code < 0)
541         return code;
542     code = sputs(s, (const byte *)&p->RangeHIJK, sizeof(p->RangeHIJK), &n);
543     if (code < 0)
544         return code;
545     return gx_serialize_lookup_table(&p->Table, s);
546 }
547