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