/src/ghostpdl/pcl/pcl/pcindxed.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 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 | | /* pcindexed.c - PCL indexed color space implementation */ |
18 | | #include "math_.h" |
19 | | #include "string_.h" |
20 | | #include "gx.h" |
21 | | #include "pcmtx3.h" |
22 | | #include "pccid.h" |
23 | | #include "pccsbase.h" |
24 | | #include "pcpalet.h" |
25 | | |
26 | | /* default GL/2 pen width, in plotter units (1016 plotter units per inch) */ |
27 | | static const float dflt_pen_width = 14.0; |
28 | | |
29 | | /* the image data configuration for the default color space */ |
30 | | static const pcl_cid_hdr_t dflt_cid_hdr = { |
31 | | pcl_cspace_RGB, /* color space type */ |
32 | | pcl_penc_indexed_by_plane, /* pixel encoding type */ |
33 | | 1, /* bits per index */ |
34 | | {1, 1, 1} /* bits per primary (3 components) */ |
35 | | }; |
36 | | |
37 | | gs_private_st_simple(st_cs_indexed_t, pcl_cs_indexed_t, |
38 | | "pcl indexed color space"); |
39 | | |
40 | | /* |
41 | | * Find the smallest non-negative integral exponent of 2 larger than |
42 | | * or equal to the given number; 8 => 2^3 12 => 2^4 |
43 | | * Note: in/out should be unsigned. |
44 | | */ |
45 | | static int |
46 | | get_pow_2(int num) |
47 | 20.9k | { |
48 | 20.9k | int i; |
49 | 20.9k | unsigned power_2 = 1; |
50 | | |
51 | 51.5k | for (i = 0; (unsigned)num > power_2; ++i) |
52 | 30.5k | power_2 <<= 1; |
53 | 20.9k | return i; |
54 | 20.9k | } |
55 | | |
56 | | /* |
57 | | * Free a PCL indexed color space structure. |
58 | | */ |
59 | | static void |
60 | | free_indexed_cspace(gs_memory_t * pmem, void *pvindexed, client_name_t cname) |
61 | 24.8k | { |
62 | 24.8k | pcl_cs_indexed_t *pindexed = (pcl_cs_indexed_t *) pvindexed; |
63 | | |
64 | 24.8k | pcl_cs_base_release(pindexed->pbase); |
65 | 24.8k | rc_decrement(pindexed->pcspace, "free_indexed_cspace"); |
66 | 24.8k | gs_free_object(pmem, pvindexed, cname); |
67 | 24.8k | } |
68 | | |
69 | | /* |
70 | | * Allocate a PCL indexed color space. |
71 | | * |
72 | | * Because a PCL indexed color space and the associated graphic library |
73 | | * indexed color space must be kept in a one-to-one relationship, the latter |
74 | | * color space is allocated here as well. This requires that the base color |
75 | | * space be an operand. |
76 | | * |
77 | | * Returns 0 on success, < 0 in the event of an error. |
78 | | */ |
79 | | static int |
80 | | alloc_indexed_cspace(pcl_cs_indexed_t ** ppindexed, |
81 | | pcl_cs_base_t * pbase, |
82 | | uint num_entries, gs_memory_t * pmem) |
83 | 24.9k | { |
84 | 24.9k | pcl_cs_indexed_t *pindexed = 0; |
85 | 24.9k | int code = 0; |
86 | 24.9k | byte *bp = 0; |
87 | 24.9k | uint palette_size = 3 * num_entries; |
88 | 24.9k | int i; |
89 | | |
90 | 24.9k | if_debug1m('c', pmem, "[c]alloc_indexed_cspace entries:%d\n", |
91 | 24.9k | num_entries); |
92 | | |
93 | 24.9k | rc_alloc_struct_1(pindexed, |
94 | 24.9k | pcl_cs_indexed_t, |
95 | 24.9k | &st_cs_indexed_t, |
96 | 24.9k | pmem, |
97 | 24.9k | return e_Memory, "allocate pcl indexed color space"); |
98 | | |
99 | 24.9k | pindexed->rc.free = free_indexed_cspace; |
100 | 24.9k | pindexed->pfixed = false; |
101 | 24.9k | pindexed->is_GL = false; |
102 | 24.9k | pcl_cs_base_init_from(pindexed->pbase, pbase); |
103 | 24.9k | pindexed->pcspace = 0; |
104 | 24.9k | pindexed->num_entries = 0; |
105 | 24.9k | pindexed->palette.data = 0; |
106 | 24.9k | pindexed->palette.size = 0; |
107 | | |
108 | 24.9k | bp = gs_alloc_string(pmem, |
109 | 24.9k | palette_size, "allocate pcl indexed color space"); |
110 | 24.9k | if (bp == 0) { |
111 | 0 | free_indexed_cspace(pmem, pindexed, |
112 | 0 | "allocate pcl indexed color space"); |
113 | 0 | return e_Memory; |
114 | 0 | } |
115 | 24.9k | pindexed->palette.data = bp; |
116 | 24.9k | pindexed->palette.size = palette_size; |
117 | 104k | for (i = 0; i < num_entries; i++) |
118 | 79.2k | pindexed->pen_widths[i] = dflt_pen_width; |
119 | | |
120 | 24.9k | code = gs_cspace_build_Indexed(&(pindexed->pcspace), |
121 | 24.9k | pbase->pcspace, |
122 | 24.9k | num_entries, |
123 | 24.9k | (gs_const_string *) & (pindexed->palette), |
124 | 24.9k | pmem); |
125 | 24.9k | if (code < 0) { |
126 | 0 | free_indexed_cspace(pmem, pindexed, |
127 | 0 | "allocate pcl indexed color space"); |
128 | 0 | gs_free_object(pmem, bp, "allocate pcl indexed color space"); |
129 | 0 | return code; |
130 | 0 | } |
131 | | |
132 | 24.9k | *ppindexed = pindexed; |
133 | 24.9k | return 0; |
134 | 24.9k | } |
135 | | |
136 | | /* Resize the palette of an indexed color space */ |
137 | | static int |
138 | | resize_indexed_cspace(pcl_cs_indexed_t * pindexed, uint num_entries) |
139 | 20.9k | { |
140 | 20.9k | byte *pdata; |
141 | 20.9k | gs_memory_t *pmem = pindexed->rc.memory; |
142 | 20.9k | uint new_size = num_entries * 3; |
143 | 20.9k | int i; |
144 | 20.9k | uint num_old_entries; |
145 | | |
146 | 20.9k | if_debug2m('c', pmem, "[c]resizing_indexed_cspace new:%d old:%d\n", |
147 | 20.9k | num_entries, pindexed->num_entries); |
148 | | |
149 | 20.9k | pdata = |
150 | 20.9k | gs_resize_string(pmem, pindexed->palette.data, pindexed->palette.size, |
151 | 20.9k | new_size, "resize pcl indexed color space"); |
152 | 20.9k | if (pdata == NULL) |
153 | 0 | return gs_error_VMerror; |
154 | 20.9k | num_old_entries = pindexed->num_entries; |
155 | 20.9k | pindexed->num_entries = num_entries; |
156 | 20.9k | pindexed->palette.data = pdata; |
157 | | /* NB duplicate data storage */ |
158 | 20.9k | pindexed->palette.size = |
159 | 20.9k | pindexed->pcspace->params.indexed.lookup.table.size = new_size; |
160 | 20.9k | pindexed->pcspace->params.indexed.lookup.table.data = (const byte *)pdata; |
161 | 20.9k | pindexed->palette.data = pdata; |
162 | 20.9k | pindexed->pcspace->params.indexed.hival = num_entries - 1; |
163 | | /* if the palette has grown we have to fill in the default line |
164 | | width values */ |
165 | 91.7k | for (i = num_old_entries; i < num_entries; i++) |
166 | 70.8k | pindexed->pen_widths[i] = dflt_pen_width; |
167 | 20.9k | return 0; |
168 | 20.9k | } |
169 | | |
170 | | /* |
171 | | * Make a PCL indexed color space unique. |
172 | | * |
173 | | * Note that neither the palette nor the graphic state indexed color space can |
174 | | * be shared between two PCL indexed color spaces. The two would need to be |
175 | | * shared in tandem, which would require common reference counting between the |
176 | | * pair, which would require yet another PCL object, and so on. |
177 | | * |
178 | | * Returns 0 on success, < 0 in the event of an error. |
179 | | */ |
180 | | static int |
181 | | unshare_indexed_cspace(pcl_cs_indexed_t ** ppindexed) |
182 | 54.0k | { |
183 | 54.0k | pcl_cs_indexed_t *pindexed = *ppindexed; |
184 | 54.0k | pcl_cs_indexed_t *pnew = 0; |
185 | 54.0k | int code = 0; |
186 | 54.0k | int num_entries = pindexed->num_entries; |
187 | | |
188 | | /* check if there is anything to do */ |
189 | 54.0k | if (pindexed->rc.ref_count == 1) |
190 | 53.2k | return 0; |
191 | 792 | rc_decrement(pindexed, "unshare PCL indexed color space"); |
192 | | |
193 | | /* allocate a new indexed color space */ |
194 | 792 | code = alloc_indexed_cspace(ppindexed, |
195 | 792 | pindexed->pbase, |
196 | 792 | pindexed->num_entries, pindexed->rc.memory); |
197 | 792 | if (code < 0) |
198 | 0 | return code; |
199 | 792 | pnew = *ppindexed; |
200 | | |
201 | | /* copy fields various and sundry */ |
202 | 792 | pnew->pfixed = pindexed->pfixed; |
203 | 792 | pnew->cid = pindexed->cid; |
204 | 792 | pnew->original_cspace = pindexed->original_cspace; |
205 | 792 | pnew->num_entries = pindexed->num_entries; |
206 | 792 | pnew->palette.size = pindexed->palette.size; |
207 | 792 | memcpy(pnew->palette.data, pindexed->palette.data, |
208 | 792 | pindexed->palette.size); |
209 | 792 | memcpy(pnew->pen_widths, pindexed->pen_widths, |
210 | 792 | num_entries * sizeof(float)); |
211 | | |
212 | | /* Coverity thinks next memcpy() might need to be memmove(), so we |
213 | | explicitly check for the buffers being equal. */ |
214 | 792 | if (pnew->norm != pindexed->norm) { |
215 | 792 | memcpy(pnew->norm, pindexed->norm, 3 * sizeof(pindexed->norm[0])); |
216 | 792 | } |
217 | | |
218 | | /* Coverity thinks next memcpy() might need to be memmove(), so we |
219 | | explicitly check for the buffers being equal. */ |
220 | 792 | if (pnew->Decode != pindexed->Decode) { |
221 | 792 | memcpy(pnew->Decode, pindexed->Decode, 6 * sizeof(float)); |
222 | 792 | } |
223 | | |
224 | 792 | return 0; |
225 | 792 | } |
226 | | |
227 | | /* |
228 | | * Fill in the default entries in a color palette. This is handled separately |
229 | | * for each color space type. |
230 | | * |
231 | | * The manner in which the default color palette is specified by HP is, |
232 | | * unfortunately, completely dependent on their particular implementation. |
233 | | * HP maintains palettes in device space, and initializes palettes with |
234 | | * device space colors. Hence, these palettes are affected by gamma correction |
235 | | * and the lookup tables for the device color space, but not by any lookup |
236 | | * tables for device independent color spaces (even if the base color space is |
237 | | * device independent), nor by range specifications in the color space |
238 | | * parameters. |
239 | | * |
240 | | * Because this implementation of PCL 5c works strictly in source color space, |
241 | | * it is not possible to achieve the same result. Instead, this implementation |
242 | | * will give accurate default color space values only for the RGB and CMY |
243 | | * color space values, and will give approximate results for the other color |
244 | | * spaces. The default colors will be modified by all applicable color lookup |
245 | | * tables, though some compensation is provided for component ranges. |
246 | | * |
247 | | * For applications, this should not matter: presumably an application does |
248 | | * not select a device independent color space in order to achieve a device- |
249 | | * specific color. For tests such as the PCL 5c FTS, it is more likely that |
250 | | * a discrepancy will be visible, because these tests illustrate the default |
251 | | * palette for each color space. |
252 | | */ |
253 | | |
254 | | /* |
255 | | * Convert a device-independent color intensity value to the range [0, 255]. |
256 | | */ |
257 | | static int |
258 | | convert_comp_val(double val, double min_val, double range) |
259 | 0 | { |
260 | 0 | val = 255.0 * (val - min_val) / range; |
261 | 0 | return (val < 0.0 ? 0 : (val > 255.0 ? 255 : (int)floor(val + 0.5))); |
262 | 0 | } |
263 | | |
264 | | /* |
265 | | * Set the default palette for device specific color spaces. |
266 | | */ |
267 | | static void |
268 | | set_dev_specific_default_palette(pcl_cs_base_t * pbase, /* ignored in this case */ |
269 | | byte * palette, |
270 | | const byte * porder, int start, int num) |
271 | 20.9k | { |
272 | 20.9k | int i; |
273 | 20.9k | static const byte cmy_default[(8 * 3) + 1] = { |
274 | 20.9k | 255, 255, 255, /* white */ |
275 | 20.9k | 0, 255, 255, /* cyan */ |
276 | 20.9k | 255, 0, 255, /* magenta */ |
277 | 20.9k | 0, 0, 255, /* blue */ |
278 | 20.9k | 255, 255, 0, /* yellow */ |
279 | 20.9k | 0, 255, 0, /* green */ |
280 | 20.9k | 255, 0, 0, /* red */ |
281 | 20.9k | 0, 0, 0, /* black */ |
282 | 20.9k | 0 /* Sacrificial, for porder[i] = 7 and 'num' > 8 */ |
283 | 20.9k | }; |
284 | | |
285 | | /* fill in the num_entries - 1 values from the RGB default */ |
286 | 91.7k | for (i = start; i < num + start; i++) { |
287 | 70.8k | palette[3 * i] = cmy_default[3 * porder[i]]; |
288 | 70.8k | palette[3 * i + 1] = cmy_default[3 * porder[i] + 1]; |
289 | 70.8k | palette[3 * i + 2] = cmy_default[3 * porder[i] + 2]; |
290 | 70.8k | if (num > 8) |
291 | 0 | palette[3 * i + 3] = cmy_default[3 * porder[i] + 3]; |
292 | 70.8k | } |
293 | 20.9k | } |
294 | | |
295 | | /* |
296 | | * Set the default palette for a colorimetric RGB space. |
297 | | * |
298 | | * The assumption used in this case is that if the user specified primaries, |
299 | | * presumably they want those primaries. Further, it is assumed that the red |
300 | | * primary is associated with red, the green with green, and so on. Should |
301 | | * the user specify a "blue" color as the red primary, then the default |
302 | | * palette will have blue where red is normally expected. |
303 | | * |
304 | | * An adjustment is made for the specified ranges. |
305 | | */ |
306 | | static void |
307 | | set_colmet_default_palette(pcl_cs_base_t * pbase, |
308 | | byte * palette, |
309 | | const byte * porder, int start, int num) |
310 | 0 | { |
311 | 0 | float *pmin = pbase->client_data.min_val; |
312 | 0 | float *prange = pbase->client_data.range; |
313 | 0 | int i; |
314 | |
|
315 | 0 | static const float colmet_default[8 * 3] = { |
316 | 0 | 1.0, 1.0, 1.0, /* white */ |
317 | 0 | 0.0, 1.0, 1.0, /* cyan */ |
318 | 0 | 1.0, 0.0, 1.0, /* magenta */ |
319 | 0 | 0.0, 0.0, 1.0, /* blue */ |
320 | 0 | 1.0, 1.0, 0.0, /* yellow */ |
321 | 0 | 0.0, 1.0, 0.0, /* green */ |
322 | 0 | 1.0, 0.0, 0.0, /* red */ |
323 | 0 | 0.0, 0.0, 0.0 /* black */ |
324 | 0 | }; |
325 | | |
326 | | /* fill in the num_entries - 1 values from the colorimetric default */ |
327 | 0 | for (i = start; i < start + num; i++) { |
328 | 0 | int j; |
329 | 0 | byte *pb = palette + 3 * i; |
330 | 0 | const float *pdef = colmet_default + 3 * porder[i]; |
331 | |
|
332 | 0 | for (j = 0; j < 3; j++) |
333 | 0 | pb[j] = convert_comp_val(pdef[j], pmin[j], prange[j]); |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | | /* |
338 | | * Set the default palette for a CIE L*a*b* color space. |
339 | | * |
340 | | * The values provided will, for a sufficiently capable device, generate the |
341 | | * SMPTE-C primaries (assuming that ranges and/or color lookup tables don't |
342 | | * get in the way). Most printing devices cannot generate these colors, so |
343 | | * a somewhat different output is produced, but this is as close as we can |
344 | | * come to a "device independent" set of default entries. |
345 | | * |
346 | | * The code provides some compensation for range: if the desired value is |
347 | | * within the permitted range, the palette entry intensity (always in the range |
348 | | * [0, 1]) will be adjusted so as to achieve it; otherwise the intensity will |
349 | | * be set to the appropriate bound. Obviously, none of this works if a |
350 | | * color lookup table is subsequently installed, but it is as much as can be |
351 | | * achieved under the current arrangement. |
352 | | */ |
353 | | static void |
354 | | set_CIELab_default_palette(pcl_cs_base_t * pbase, |
355 | | byte * palette, |
356 | | const byte * porder, int start, int num) |
357 | 0 | { |
358 | 0 | float *pmin = pbase->client_data.min_val; |
359 | 0 | float *prange = pbase->client_data.range; |
360 | 0 | int i; |
361 | |
|
362 | 0 | static const float lab_default[8 * 3] = { |
363 | 0 | 100.0f, 0.0f, 0.0f, /* white */ |
364 | 0 | 91.1f, -43.4f, -14.1f, /* cyan */ |
365 | 0 | 61.6f, 91.0f, -59.2f, /* magenta */ |
366 | 0 | 35.3f, 72.0f, -100.0f, /* blue */ |
367 | 0 | 96.6f, -21.3f, 95.4f, /* yellow */ |
368 | 0 | 87.0f, -80.7f, 84.0f, /* green */ |
369 | 0 | 53.2f, 74.4f, 67.7f, /* red */ |
370 | 0 | 0.0f, 0.0f, 0.0f /* black */ |
371 | 0 | }; |
372 | |
|
373 | 0 | for (i = start; i < start + num; i++) { |
374 | 0 | int j; |
375 | 0 | byte *pb = palette + 3 * i; |
376 | 0 | const float *pdef = lab_default + 3 * porder[i]; |
377 | |
|
378 | 0 | for (j = 0; j < 3; j++) |
379 | 0 | pb[j] = convert_comp_val(pdef[j], pmin[j], prange[j]); |
380 | 0 | } |
381 | 0 | } |
382 | | |
383 | | /* |
384 | | * Set the default palette for a luminance-chrominance color space. |
385 | | * |
386 | | * The arrangement used for this color space is based on the one used for |
387 | | * the colorimetric color space. The user specifies a set of primaries |
388 | | * for the color space underlying the luminance-chrominance color space, |
389 | | * and we provide those primaries in the default palette. Since the |
390 | | * palette entries themselves are in the luminance-chrominance color space, |
391 | | * the default values must be converted to that color space. |
392 | | * |
393 | | * An adjustment is made for the specified ranges. |
394 | | */ |
395 | | static void |
396 | | set_lumchrom_default_palette(pcl_cs_base_t * pbase, |
397 | | byte * palette, |
398 | | const byte * porder, int start, int num) |
399 | 0 | { |
400 | 0 | gs_matrix3 *pxfm = gs_cie_abc_MatrixABC(pbase->pcspace); |
401 | 0 | float *pmin = pbase->client_data.min_val; |
402 | 0 | float *prange = pbase->client_data.range; |
403 | 0 | pcl_mtx3_t tmp_mtx; |
404 | 0 | int i; |
405 | |
|
406 | 0 | static const pcl_vec3_t lumchrom_default[8] = { |
407 | 0 | {{1.0, 1.0, 1.0}}, /* white */ |
408 | 0 | {{0.0, 1.0, 1.0}}, /* cyan */ |
409 | 0 | {{1.0, 0.0, 1.0}}, /* magenta */ |
410 | 0 | {{0.0, 0.0, 1.0}}, /* blue */ |
411 | 0 | {{1.0, 1.0, 0.0}}, /* yellow */ |
412 | 0 | {{0.0, 1.0, 0.0}}, /* green */ |
413 | 0 | {{1.0, 0.0, 0.0}}, /* red */ |
414 | 0 | {{0.0, 0.0, 0.0}} /* black */ |
415 | 0 | }; |
416 | | |
417 | | /* form the primaries to component values matrix */ |
418 | 0 | pcl_mtx3_convert_from_gs(&tmp_mtx, pxfm); |
419 | 0 | pcl_mtx3_invert(&tmp_mtx, &tmp_mtx); |
420 | |
|
421 | 0 | for (i = start; i < start + num; i++) { |
422 | 0 | pcl_vec3_t compvec; |
423 | 0 | byte *pb = palette + 3 * i; |
424 | 0 | int j; |
425 | |
|
426 | 0 | pcl_vec3_xform(&(lumchrom_default[porder[i]]), &compvec, &tmp_mtx); |
427 | 0 | for (j = 0; j < 3; j++) |
428 | 0 | pb[j] = convert_comp_val(compvec.va[j], pmin[j], prange[j]); |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | /* |
433 | | * Set the default values for a specific range of an indexed PCL color space. |
434 | | * The starting point is indicated by start; the number of subsequent entires |
435 | | * to be set by num (for PCL, start is always 0 and num is always the number of |
436 | | * entires in the palette, but that may not be the case for GL/2). |
437 | | * |
438 | | * If gl2 is true, this call is being made from GL/2, hence the GL/2 default |
439 | | * palettes should be used. |
440 | | * |
441 | | * Returns 0 if successful, < 0 in case of an error. |
442 | | */ |
443 | | static int |
444 | | set_default_entries(pcl_cs_indexed_t * pindexed, int start, int num, bool gl2) |
445 | 20.9k | { |
446 | | /* array of procedures to set the default palette entries */ |
447 | 20.9k | static void (*const |
448 | 20.9k | set_default_palette[(int)pcl_cspace_num]) (pcl_cs_base_t * |
449 | 20.9k | pbase, |
450 | 20.9k | byte * palette, |
451 | 20.9k | const byte * |
452 | 20.9k | porder, int start, |
453 | 20.9k | int num) = { |
454 | 20.9k | set_dev_specific_default_palette, /* RGB */ |
455 | 20.9k | set_dev_specific_default_palette, /* CMY */ |
456 | 20.9k | set_colmet_default_palette, /* colorimetric RGB */ |
457 | 20.9k | set_CIELab_default_palette, /* CIE L*a*b* */ |
458 | 20.9k | set_lumchrom_default_palette, /* luminance- |
459 | | * chrominance */ |
460 | 20.9k | set_dev_specific_default_palette /* KCMY */ |
461 | 20.9k | }; |
462 | | |
463 | | /* |
464 | | * For each color space, 8 or 16 palette entries are stored in the canonical |
465 | | * CMY order; any palette entries beyond the first 8 or 16 always default to |
466 | | * black. These arrays are incorporated into procedures that handle the |
467 | | * generation of colors for each color space type. For the bits per index |
468 | | * settings of 1, 2, 3, or >= 4, an order array is provided, to indicate the |
469 | | * order in which the default palette entries should be entered into the |
470 | | * palette. Separate arrays are provided for the RGB and CMY color spaces, |
471 | | * and for GL/2 default colors. |
472 | | */ |
473 | 20.9k | static const byte order_1[] = { 0, 7 }; |
474 | 20.9k | static const byte cmy_order_2[] = { 0, 1, 2, 7 }; |
475 | 20.9k | static const byte cmy_order_3[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; |
476 | 20.9k | static const byte cmy_order_4[] = { 0, 7, 1, 7, 2, 7, 3, 7, 4, 7, 5, 7, 6, 7, 7, 7 }; |
477 | 20.9k | static const byte rgb_order_2[] = { 7, 6, 5, 0 }; |
478 | 20.9k | static const byte rgb_order_3[] = { 7, 6, 5, 4, 3, 2, 1, 0 }; |
479 | 20.9k | static const byte gl2_order_2[] = { 0, 7, 6, 5 }; |
480 | 20.9k | static const byte gl2_order_3[] = { 0, 7, 6, 5, 4, 3, 2, 1 }; |
481 | 20.9k | static const byte *cmy_order[4] = { order_1, cmy_order_2, cmy_order_3, cmy_order_4 }; |
482 | 20.9k | static const byte *rgb_order[3] = { order_1, rgb_order_2, rgb_order_3 }; |
483 | 20.9k | static const byte *gl2_order[3] = { order_1, gl2_order_2, gl2_order_3 }; |
484 | 20.9k | int type = pindexed->cid.cspace; |
485 | 20.9k | int orig_type = pindexed->original_cspace; |
486 | 20.9k | int bits = pindexed->cid.bits_per_index - 1; |
487 | 20.9k | const byte *porder; |
488 | 20.9k | int cnt = (num + start > 8 ? 8 - start : num); |
489 | 20.9k | int i; |
490 | | |
491 | 20.9k | if (bits > 2) |
492 | 0 | bits = 2; |
493 | 20.9k | if (gl2) |
494 | 4.82k | porder = gl2_order[bits]; |
495 | | /* check for a rgb or colorimetric. If the colorimetric is being |
496 | | substituted for device CMY use the cmy order */ |
497 | 16.1k | else if (((type == pcl_cspace_RGB) || (type == pcl_cspace_Colorimetric)) |
498 | 16.1k | && (orig_type != pcl_cspace_CMY)) |
499 | 16.1k | porder = rgb_order[bits]; |
500 | 0 | else |
501 | 0 | porder = cmy_order[bits]; |
502 | | |
503 | | /* If 4-plane simple color KCMY graphics, set cnt for larger palette. */ |
504 | 20.9k | if (type == pcl_cspace_KCMY) { |
505 | | /* This seems to be plain wrong, the size of the palette data is set from the number of bits, without |
506 | | * regard to the colour space. I can't see any reason to set the number of entries to 15, and it |
507 | | * overruns the palette if we do. So I'm commenting it out. |
508 | | cnt = 15; |
509 | | */ |
510 | 0 | porder = cmy_order_4; |
511 | 0 | } |
512 | | /* set the default colors for up to the first 16 entries */ |
513 | 20.9k | set_default_palette[(int)type] (pindexed->pbase, |
514 | 20.9k | pindexed->palette.data, |
515 | 20.9k | porder, start, cnt); |
516 | | |
517 | | /* set the remaining entries to black */ |
518 | 20.9k | { |
519 | 20.9k | int s = start + cnt; |
520 | 20.9k | int e = start + num; |
521 | | |
522 | 20.9k | for (i = s; i < e; i++) { |
523 | 0 | byte *bp = pindexed->palette.data + i * 3; |
524 | |
|
525 | 0 | bp[0] = bp[1] = bp[2] = 0; |
526 | 0 | } |
527 | 20.9k | } |
528 | 20.9k | return 0; |
529 | 20.9k | } |
530 | | |
531 | | /* |
532 | | * Generate the normalization and, if appropriate, Decode arrays that correspond |
533 | | * to a pcl_cid_data structure. |
534 | | * |
535 | | * Normalization in PCL and GL/2 involves a modification of a component color |
536 | | * setting prior to its being stored in the palette. This is set in PCL via |
537 | | * the black and white reference points for device specific color spaces, and |
538 | | * in GL/2 via the CR command. The latter provides the much more general |
539 | | * interface, which in turn drives the implementation. |
540 | | * |
541 | | * In PCL, white and black reference points may be set only for the device- |
542 | | * dependent color spaces, and may only be set once when a palette is created |
543 | | * (via the configure image data command; the min/max ranges for the device |
544 | | * independent color spaces have a different interpretation). The CR command, |
545 | | * on the other hand, applies to all color spaces, and can used to modfiy the |
546 | | * range without otherwise changing the current color palette. |
547 | | * |
548 | | * All color spaces in this implementation are set up so that, in the palette, |
549 | | * 0 represents the minimum intensity, and 1 the maximum intensity. For a |
550 | | * component that has black and white reference points of blk and wht, |
551 | | * respectively, the normalization applied is: |
552 | | * |
553 | | * tmp_val = ((i_val - blk) / (wht - blk) |
554 | | * |
555 | | * o_val = (tmp_val < 0 ? 0 : (tmp_val > 1 ? 1 : tmp_val)) |
556 | | * |
557 | | * Because palette entries are stored as integers in the range [0, 255], the |
558 | | * actual form in which the normalization data are stored (and the modified |
559 | | * normalization calculation) are: |
560 | | * |
561 | | * blkref = blk |
562 | | * |
563 | | * inv_range = 255.0 / (wht - blk) |
564 | | * |
565 | | * tmp_val = (i_val - blkref) * inv_range + 0.5; |
566 | | * |
567 | | * o_val = (tmp_val < 0 ? 0 : (tmp_val > 255 ? 255 : floor(tmp_val + 0.5))) |
568 | | * |
569 | | * For a primary that uses an n-bit representation, the default values for |
570 | | * blk and wht are 0 and 2^n - 1, respectively. (For HP's implementation this |
571 | | * only applies to device-dependent color spaces; wht for device-independent |
572 | | * color spaces is always 255. There seems to be no reason for such a |
573 | | * restriction, hence it is not used here. This is unlikely to cause difficulty |
574 | | * in practice, as it is unlikely a device-independent color space will ever |
575 | | * be used with anything other than 8-bits per primary.) |
576 | | * |
577 | | * Note that for the CMY color space, the white and black points are reversed. |
578 | | * This is the only distinction between the RGB and CMY color spaces. |
579 | | * |
580 | | * The Decode array is used for images, and thus has different forms |
581 | | * depending on the pixel encoding mode. For the "direct by" cases |
582 | | * it incorporates normalization information; for the "indexed by" |
583 | | * cases its contents are dictated by the size of the palette. |
584 | | */ |
585 | | int |
586 | | pcl_cs_indexed_set_norm_and_Decode(pcl_cs_indexed_t ** ppindexed, |
587 | | double wht0, |
588 | | double wht1, |
589 | | double wht2, |
590 | | double blk0, double blk1, double blk2) |
591 | 24.1k | { |
592 | 24.1k | pcl_cs_indexed_t *pindexed = *ppindexed; |
593 | 24.1k | pcl_encoding_type_t enc = (pcl_encoding_type_t) pindexed->cid.encoding; |
594 | 24.1k | pcl_cs_indexed_norm_t *pnorm; |
595 | 24.1k | int code = 0; |
596 | | |
597 | | /* ignore request if palette is fixed */ |
598 | 24.1k | if (pindexed->pfixed) |
599 | 0 | return 0; |
600 | | |
601 | | /* get a unique copy of the color space */ |
602 | 24.1k | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
603 | 0 | return code; |
604 | 24.1k | pindexed = *ppindexed; |
605 | 24.1k | pnorm = pindexed->norm; |
606 | | |
607 | | /* set up for the additive space */ |
608 | 24.1k | pnorm[0].blkref = blk0; |
609 | 24.1k | pnorm[0].inv_range = (wht0 == blk0 ? 0.0 : 255.0 / (wht0 - blk0)); |
610 | 24.1k | pnorm[1].blkref = blk1; |
611 | 24.1k | pnorm[1].inv_range = (wht1 == blk1 ? 0.0 : 255.0 / (wht1 - blk1)); |
612 | 24.1k | pnorm[2].blkref = blk2; |
613 | 24.1k | pnorm[2].inv_range = (wht2 == blk2 ? 0.0 : 255.0 / (wht2 - blk2)); |
614 | | |
615 | | /* |
616 | | * Build the Decode array to be used with images. |
617 | | * |
618 | | * If an "indexed by" pixel encoding scheme is being used, the color |
619 | | * space for images is the same color space used for the foreground, and |
620 | | * the Decode array is the canonical array for Indexed color spaces. |
621 | | * |
622 | | * If a "direct by" pixel encoding is being used, the Decode array must |
623 | | * yield the same color component values as would be produced by use of |
624 | | * the "color component" commands. Thus, for any color component intensity |
625 | | * a, we must have |
626 | | * |
627 | | * (a - blkref) / range = Dmin + a * (Dmax - Dmin) / (2^n - 1) |
628 | | * |
629 | | * where blkref and range are the black reference point and range value for |
630 | | * this component (computed above), Dmin and Dmax are the first and second |
631 | | * elements of the Decode array for this component, and n is the number of |
632 | | * bits per pixel. Setting a = 0, this yields: |
633 | | * |
634 | | * -blkref / range = Dmin |
635 | | * |
636 | | * Substituting this into the original equation yields: |
637 | | * |
638 | | * (a - blkref) / range = a * (Dmax + blkref/range) / (2^n - 1) |
639 | | * - blkref / range; |
640 | | * |
641 | | * Adding blkref / range to both sides, and multiplying both sides by |
642 | | * range * (2^n - 1) / a yields: |
643 | | * |
644 | | * 2^n - 1 = range * Dmax + blkref |
645 | | * |
646 | | * or |
647 | | * |
648 | | * (2^n - 1 - blkref) / range = Dmax |
649 | | * |
650 | | * Note that this arrangement requires the image/color space code to |
651 | | * properly handle out of range values. |
652 | | */ |
653 | 24.1k | if (enc >= pcl_penc_direct_by_plane) { |
654 | 0 | int i; |
655 | 0 | float *pdecode = pindexed->Decode; |
656 | |
|
657 | 0 | for (i = 0; i < 3; i++) { |
658 | 0 | int nbits = pindexed->cid.bits_per_primary[i]; |
659 | 0 | double inv_range = pnorm[i].inv_range; |
660 | |
|
661 | 0 | if (inv_range == 0.0) |
662 | 0 | inv_range = 254; |
663 | 0 | pdecode[2 * i] = -pnorm[i].blkref * inv_range / 255.0; |
664 | 0 | pdecode[2 * i + 1] = |
665 | 0 | ((float)((1L << nbits) - 1) - pnorm[i].blkref) |
666 | 0 | * inv_range / 255.0; |
667 | 0 | } |
668 | 24.1k | } else { |
669 | 24.1k | pindexed->Decode[0] = 0.0; |
670 | 24.1k | pindexed->Decode[1] = 0.0; /* modified subsequently */ |
671 | 24.1k | } |
672 | 24.1k | return 0; |
673 | 24.1k | } |
674 | | |
675 | | /* |
676 | | * Change the number of entries in an PCL indexed color space palette. For |
677 | | * PCL itself, this occurs only when a palette is created, and is determined |
678 | | * by the number of bits per index. The NP command in GL/2, on the other hand, |
679 | | * can override the palette size for an existing palette. |
680 | | * |
681 | | * The gl2 boolean indicates if this call is being made from GL/2 (either the |
682 | | * IN or NP command). The routine needs to know this so as to set the |
683 | | * appropriate default colors. |
684 | | * |
685 | | * Returns 0 on success, < 0 in the event of an error. |
686 | | */ |
687 | | int |
688 | | pcl_cs_indexed_set_num_entries(pcl_cs_indexed_t ** ppindexed, |
689 | | int new_num, bool gl2) |
690 | 20.9k | { |
691 | 20.9k | pcl_cs_indexed_t *pindexed = *ppindexed; |
692 | 20.9k | int bits = get_pow_2(new_num); |
693 | 20.9k | int old_num = pindexed->num_entries; |
694 | 20.9k | int code = 0; |
695 | | |
696 | | /* ignore request if palette is fixed */ |
697 | 20.9k | if (pindexed->pfixed) |
698 | 0 | return 0; |
699 | | |
700 | 20.9k | pindexed->is_GL = gl2; |
701 | | |
702 | 20.9k | if_debug3m('c', pindexed->rc.memory, |
703 | 20.9k | "pcl_cs_indexed_set_num_entries, is gl2:%d, entries old:%d, new:%d\n", |
704 | 20.9k | gl2, old_num, new_num); |
705 | | |
706 | | /* |
707 | | * Set new_num to the smallest larger power of 2 less than |
708 | | * pcl_cs_indexed_palette_size. |
709 | | */ |
710 | 20.9k | bits = (bits > pcl_cs_indexed_palette_size_log |
711 | 20.9k | ? pcl_cs_indexed_palette_size_log : bits); |
712 | 20.9k | new_num = 1L << bits; |
713 | | |
714 | | /* make sure the palette is unique */ |
715 | 20.9k | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
716 | 0 | return code; |
717 | 20.9k | pindexed = *ppindexed; |
718 | 20.9k | pindexed->cid.bits_per_index = bits; |
719 | | |
720 | | /* check if the Decode array must be updated */ |
721 | 20.9k | if (pindexed->cid.encoding < pcl_penc_direct_by_plane) |
722 | 20.9k | pindexed->Decode[1] = (float)(new_num - 1); |
723 | | |
724 | | |
725 | | /* resize the palette if necessary */ |
726 | 20.9k | if (old_num != new_num) |
727 | 20.9k | resize_indexed_cspace(pindexed, new_num); |
728 | | |
729 | | /* update the number of entries in the palette */ |
730 | 20.9k | pindexed->num_entries = new_num; |
731 | | |
732 | | /* if the palette grew, write in default colors and widths */ |
733 | 20.9k | if (new_num > old_num) |
734 | 20.9k | set_default_entries(pindexed, old_num, new_num - old_num, gl2); |
735 | | |
736 | 20.9k | return 0; |
737 | 20.9k | } |
738 | | |
739 | | /* |
740 | | * Update the lookup table information for an indexed color space. |
741 | | * |
742 | | * Because lookup tables can modify base color spaces, this operation is |
743 | | * rather ugly. If the base color space is changed, it is necessary to release |
744 | | * and re-build the graphic library indexed color space as well, as this will |
745 | | * now have references to obsolete parts of the graphic library base color |
746 | | * space. |
747 | | * |
748 | | * Fortunately, this operation does not happen very often. |
749 | | * |
750 | | * Returns 0 if successful, < 0 in the event of an error. |
751 | | */ |
752 | | int |
753 | | pcl_cs_indexed_update_lookup_tbl(pcl_cs_indexed_t ** ppindexed, |
754 | | pcl_lookup_tbl_t * plktbl) |
755 | 0 | { |
756 | 0 | pcl_cs_indexed_t *pindexed = *ppindexed; |
757 | 0 | pcl_cspace_type_t cstype = (pcl_cspace_type_t) pindexed->cid.cspace; |
758 | 0 | pcl_cspace_type_t lktype; |
759 | 0 | int code = 0; |
760 | | |
761 | | /* make some simple checks for not-interesting color spaces */ |
762 | 0 | if (plktbl != 0) |
763 | 0 | lktype = pcl_lookup_tbl_get_cspace(plktbl); |
764 | 0 | if ((plktbl != 0) && |
765 | 0 | ((cstype < lktype) || (lktype < pcl_cspace_Colorimetric))) |
766 | 0 | return 0; |
767 | | |
768 | | /* make a unique copy of the indexed color space */ |
769 | 0 | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
770 | 0 | return code; |
771 | 0 | pindexed = *ppindexed; |
772 | | |
773 | | /* update the base color space, if appropriate */ |
774 | 0 | code = pcl_cs_base_update_lookup_tbl(&(pindexed->pbase), plktbl); |
775 | 0 | if (code <= 0) |
776 | 0 | return code; |
777 | | |
778 | | /* a positive return code indicates we have to rebuild the |
779 | | palette. First copy the paletted data, it will be freed when |
780 | | the color space is released. */ |
781 | 0 | { |
782 | 0 | uint size = 3 * pcl_cs_indexed_palette_size; |
783 | 0 | byte *bp = gs_alloc_string(pindexed->rc.memory, size, |
784 | 0 | "pcl_cs_indexed_update_lookup_tbl"); |
785 | |
|
786 | 0 | if (bp == NULL) |
787 | 0 | return e_Memory; |
788 | 0 | memcpy(bp, pindexed->palette.data, 3 * pcl_cs_indexed_palette_size); |
789 | 0 | rc_decrement(pindexed->pcspace, "pcl_cs_indexed_update_lookup_tbl"); |
790 | 0 | pindexed->palette.data = bp; |
791 | 0 | } |
792 | | |
793 | | /* now rebuild it */ |
794 | 0 | return gs_cspace_build_Indexed(&(pindexed->pcspace), |
795 | 0 | pindexed->pbase->pcspace, |
796 | 0 | pcl_cs_indexed_palette_size, |
797 | 0 | (gs_const_string *) & (pindexed->palette), |
798 | 0 | pindexed->rc.memory); |
799 | |
|
800 | 0 | } |
801 | | |
802 | | /* |
803 | | * Update an entry in the palette of a PCL indexed color space. |
804 | | * |
805 | | * Returns 0 on success, < 0 in the event of an error. |
806 | | */ |
807 | | int |
808 | | pcl_cs_indexed_set_palette_entry(pcl_cs_indexed_t ** ppindexed, |
809 | | int indx, const float comps[3] |
810 | | ) |
811 | 0 | { |
812 | 0 | pcl_cs_indexed_t *pindexed = *ppindexed; |
813 | 0 | int code; |
814 | 0 | int i; |
815 | | |
816 | | /* ignore request if palette is fixed */ |
817 | 0 | if (pindexed->pfixed) |
818 | 0 | return 0; |
819 | | |
820 | | /* |
821 | | * Verify that the index is in range. This code obeys HP's documentation, |
822 | | * and the implementation in the CLJ 5/5M. The DJ 1600C/CM behaves |
823 | | * differently; it sets indx = indx % num_entries, but only if indx is |
824 | | * non-negative. |
825 | | */ |
826 | 0 | if ((indx < 0) || (indx >= pindexed->num_entries)) |
827 | 0 | return e_Range; |
828 | | |
829 | | /* get a unique copy of the indexed color space */ |
830 | 0 | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
831 | 0 | return code; |
832 | 0 | pindexed = *ppindexed; |
833 | | |
834 | | /* normalize and store the entry */ |
835 | 0 | indx *= 3; |
836 | 0 | for (i = 0; i < 3; i++) { |
837 | 0 | pcl_cs_indexed_norm_t *pn = &(pindexed->norm[i]); |
838 | 0 | double val = comps[i]; |
839 | |
|
840 | 0 | if (pn->inv_range == 0) |
841 | 0 | val = (val >= pn->blkref ? 255.0 : 0.0); |
842 | 0 | else { |
843 | 0 | val = (val - pn->blkref) * pn->inv_range; |
844 | 0 | val = (val < 0.0 ? 0.0 : (val > 255.0 ? 255.0 : val)); |
845 | 0 | } |
846 | 0 | pindexed->palette.data[indx + i] = (byte) val; |
847 | 0 | } |
848 | 0 | return 0; |
849 | 0 | } |
850 | | |
851 | | /* |
852 | | * Default the contents of a palette entry. |
853 | | * |
854 | | * This request can only come from GL/2, hence there is no gl2 boolean. |
855 | | * |
856 | | * Returns 0 on success, < 0 in the event of an error. |
857 | | */ |
858 | | int |
859 | | pcl_cs_indexed_set_default_palette_entry(pcl_cs_indexed_t ** ppindexed, |
860 | | int indx) |
861 | 0 | { |
862 | 0 | pcl_cs_indexed_t *pindexed = *ppindexed; |
863 | 0 | int code; |
864 | | |
865 | | /* |
866 | | * Verify that the index is in range. This code obeys HP's documentation, |
867 | | * and the implementation in the CLJ 5/5M. The DJ 1600C/CM behaves |
868 | | * differently; it sets indx = indx % num_entries, but only if indx is |
869 | | * non-negative. |
870 | | */ |
871 | 0 | if ((indx < 0) || (indx >= pindexed->num_entries)) |
872 | 0 | return e_Range; |
873 | | |
874 | | /* get a unique copy of the indexed color space */ |
875 | 0 | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
876 | 0 | return code; |
877 | | |
878 | 0 | return set_default_entries(*ppindexed, indx, 1, true); |
879 | 0 | } |
880 | | |
881 | | /* |
882 | | * Set a pen width in a palette. Units used are still TBD. |
883 | | * |
884 | | * Returns 0 if successful, < 0 in case of error. |
885 | | */ |
886 | | int |
887 | | pcl_cs_indexed_set_pen_width(pcl_cs_indexed_t ** ppindexed, |
888 | | int pen, double width) |
889 | 8.99k | { |
890 | 8.99k | pcl_cs_indexed_t *pindexed = *ppindexed; |
891 | 8.99k | int code; |
892 | | |
893 | | /* check for out-of-range pen */ |
894 | 8.99k | if ((pen < 0) || (pen > pindexed->num_entries)) |
895 | 0 | return e_Range; /* probably should be a different error */ |
896 | | |
897 | 8.99k | if ((code = unshare_indexed_cspace(ppindexed)) < 0) |
898 | 0 | return code; |
899 | 8.99k | pindexed = *ppindexed; |
900 | | |
901 | 8.99k | pindexed->pen_widths[pen] = width; |
902 | 8.99k | return 0; |
903 | 8.99k | } |
904 | | |
905 | | /* |
906 | | * Build a PCL indexed color space. |
907 | | * |
908 | | * To maintain the one-to-one relationship between the PCL indexed color space |
909 | | * and the graphic library indexed color space, the latter is created at the |
910 | | * same time as the former. Hence, the base PCL color space must be created |
911 | | * first (it is required to create the graphics library indexed color space), |
912 | | * and released once it has been referenced by the (PCL) indexed color space. |
913 | | * |
914 | | * The boolean gl2 indicates if this request came from the GL/2 IN command. |
915 | | * |
916 | | * Returns 0 if successful, < 0 in case of error. |
917 | | */ |
918 | | |
919 | | int |
920 | | pcl_cs_indexed_build_cspace(pcl_state_t * pcs, |
921 | | pcl_cs_indexed_t ** ppindexed, |
922 | | const pcl_cid_data_t * pcid, |
923 | | bool pfixed, bool gl2, gs_memory_t * pmem) |
924 | 20.9k | { |
925 | 20.9k | pcl_cs_indexed_t *pindexed = *ppindexed; |
926 | 20.9k | pcl_cspace_type_t type = pcl_cid_get_cspace(pcid); |
927 | 20.9k | int bits = pcl_cid_get_bits_per_index(pcid); |
928 | 20.9k | double wht_ref[3]; |
929 | 20.9k | double blk_ref[3]; |
930 | 20.9k | pcl_cs_base_t *pbase = 0; |
931 | 20.9k | bool is_default = false; |
932 | 20.9k | int code = 0; |
933 | | |
934 | | /* |
935 | | * Check if the default color space is being requested. Since there are |
936 | | * only three fixed spaces, it is sufficient to check that palette is |
937 | | * fixed and has 1-bit per pixel. |
938 | | */ |
939 | 20.9k | if (pfixed && (pcid->u.hdr.bits_per_index == dflt_cid_hdr.bits_per_index)) { |
940 | 16.1k | is_default = true; |
941 | 16.1k | if (pcs->pdflt_cs_indexed != 0) { |
942 | 0 | if_debug0m('c', pmem, |
943 | 0 | "[c]build request for default color space\n"); |
944 | 0 | pcl_cs_indexed_copy_from(*ppindexed, pcs->pdflt_cs_indexed); |
945 | 0 | return 0; |
946 | 0 | } |
947 | 16.1k | } |
948 | | |
949 | | /* release the existing color space, if present */ |
950 | 20.9k | if (pindexed != 0) { |
951 | 4.82k | if_debug1m('c', pmem, |
952 | 4.82k | "[c]releasing index for underlying color space:%s\n", |
953 | 4.82k | pcl_cid_cspace_get_debug_name(pmem, |
954 | 4.82k | pindexed->pbase->type)); |
955 | 4.82k | rc_decrement(pindexed, "build indexed color space"); |
956 | 4.82k | } |
957 | | |
958 | | /* build the base color space */ |
959 | 20.9k | if ((code = pcl_cs_base_build_cspace(&pbase, pcid, pmem)) < 0) |
960 | 0 | return code; |
961 | | |
962 | | /* build the indexed color space */ |
963 | 20.9k | if ((code = alloc_indexed_cspace(ppindexed, pbase, 1L << bits, pmem)) < 0) { |
964 | 0 | pcl_cs_base_release(pbase); |
965 | 0 | return code; |
966 | 0 | } |
967 | 20.9k | pindexed = *ppindexed; |
968 | | |
969 | 20.9k | if_debug1m('c', pmem, "[c]built base and index for color space:%s\n", |
970 | 20.9k | pcl_cid_cspace_get_debug_name(pmem, pindexed->pbase->type)); |
971 | | |
972 | | /* release our extra reference of the base color space */ |
973 | 20.9k | pcl_cs_base_release(pbase); |
974 | 20.9k | pbase = 0; |
975 | | |
976 | | /* copy the header of the configure image data structure */ |
977 | 20.9k | pindexed->cid = pcid->u.hdr; |
978 | | |
979 | | /* copy in the original color space if there is a substitution in |
980 | | effect. There will be the no color spaces type if no use cie |
981 | | substitution is in effect */ |
982 | 20.9k | pindexed->original_cspace = pcid->original_cspace; |
983 | | |
984 | | /* set up the normalization information */ |
985 | 20.9k | if ((pcid->len > 6) && (type < pcl_cspace_Colorimetric)) { |
986 | 0 | const pcl_cid_dev_long_t *pdev = &(pcid->u.dev); |
987 | 0 | int i; |
988 | |
|
989 | 0 | for (i = 0; i < 3; i++) { |
990 | 0 | wht_ref[i] = pdev->white_ref[i]; |
991 | 0 | blk_ref[i] = pdev->black_ref[i]; |
992 | 0 | } |
993 | 20.9k | } else { |
994 | 20.9k | int i; |
995 | | |
996 | 83.7k | for (i = 0; i < 3; i++) { |
997 | 62.8k | wht_ref[i] = (1L << pcl_cid_get_bits_per_primary(pcid, i)) - 1; |
998 | 62.8k | blk_ref[i] = 0.0; |
999 | 62.8k | } |
1000 | | |
1001 | | /* reverse for the CMY color space */ |
1002 | 20.9k | if ((type == pcl_cspace_CMY) |
1003 | 20.9k | || (pcid->original_cspace == pcl_cspace_CMY)) { |
1004 | 0 | int i; |
1005 | |
|
1006 | 0 | for (i = 0; i < 3; i++) { |
1007 | 0 | double ftmp = wht_ref[i]; |
1008 | |
|
1009 | 0 | wht_ref[i] = blk_ref[i]; |
1010 | 0 | blk_ref[i] = ftmp; |
1011 | 0 | } |
1012 | 0 | } |
1013 | 20.9k | } |
1014 | 20.9k | code = pcl_cs_indexed_set_norm_and_Decode(ppindexed, |
1015 | 20.9k | wht_ref[0], wht_ref[1], wht_ref[2], |
1016 | 20.9k | blk_ref[0], blk_ref[1], blk_ref[2] |
1017 | 20.9k | ); |
1018 | 20.9k | if (code < 0) |
1019 | 0 | return code; |
1020 | | |
1021 | | /* set the palette size and the default palette entries */ |
1022 | 20.9k | code = pcl_cs_indexed_set_num_entries(ppindexed, 1L << bits, gl2); |
1023 | 20.9k | if (code < 0) |
1024 | 0 | return code; |
1025 | | |
1026 | | /* now can indicate if the palette is fixed */ |
1027 | 20.9k | pindexed->pfixed = pfixed; |
1028 | | |
1029 | | /* record if this is the default. */ |
1030 | 20.9k | if (is_default) |
1031 | 20.9k | pcl_cs_indexed_init_from(pcs->pdflt_cs_indexed, pindexed); |
1032 | | |
1033 | 20.9k | return 0; |
1034 | 20.9k | } |
1035 | | |
1036 | | /* |
1037 | | * Build the default indexed color space. This function is usually called only |
1038 | | * once, at initialization time. |
1039 | | * |
1040 | | * Returns 0 on success, < 0 |
1041 | | */ |
1042 | | int |
1043 | | pcl_cs_indexed_build_default_cspace(pcl_state_t * pcs, |
1044 | | pcl_cs_indexed_t ** ppindexed, |
1045 | | gs_memory_t * pmem) |
1046 | 16.1k | { |
1047 | 16.1k | if (pcs->pdflt_cs_indexed == 0) { |
1048 | 16.1k | pcs->dflt_cid_data.len = 6; |
1049 | 16.1k | pcs->dflt_cid_data.u.hdr = dflt_cid_hdr; |
1050 | 16.1k | pcs->dflt_cid_data.original_cspace = pcl_cspace_num; |
1051 | 16.1k | return pcl_cs_indexed_build_cspace(pcs, |
1052 | 16.1k | ppindexed, |
1053 | 16.1k | &pcs->dflt_cid_data, |
1054 | 16.1k | true, false, pmem); |
1055 | 16.1k | } else { |
1056 | 0 | pcl_cs_indexed_copy_from(*ppindexed, pcs->pdflt_cs_indexed); |
1057 | 0 | return 0; |
1058 | 0 | } |
1059 | 16.1k | } |
1060 | | |
1061 | | /* |
1062 | | * Special indexed color space constructor, for building a 2 entry indexed color |
1063 | | * space based on an existing base color space. The first color is always set |
1064 | | * to white, while the second entry takes the value indicated by pcolor1. |
1065 | | * |
1066 | | * This reoutine is used to build the two-entry indexed color spaces required |
1067 | | * for creating opaque "uncolored" patterns. |
1068 | | */ |
1069 | | int |
1070 | | pcl_cs_indexed_build_special(pcl_cs_indexed_t ** ppindexed, |
1071 | | pcl_cs_base_t * pbase, |
1072 | | const byte * pcolor1, gs_memory_t * pmem) |
1073 | 3.18k | { |
1074 | 3.18k | static const pcl_cid_hdr_t cid = { pcl_cspace_White, /* ignored */ |
1075 | 3.18k | pcl_penc_indexed_by_pixel, |
1076 | 3.18k | 1, |
1077 | 3.18k | {8, 8, 8} /* ignored */ |
1078 | 3.18k | }; |
1079 | 3.18k | static const double wht_ref[3] = { 255.0, 255.0, 255.0 }; |
1080 | 3.18k | static const double blk_ref[3] = { 0.0, 0.0, 0.0 }; |
1081 | 3.18k | pcl_cs_indexed_t *pindexed; |
1082 | 3.18k | int i, code = 0; |
1083 | | |
1084 | | /* build the indexed color space */ |
1085 | 3.18k | if ((code = alloc_indexed_cspace(ppindexed, pbase, 2, pmem)) < 0) |
1086 | 0 | return code; |
1087 | 3.18k | pindexed = *ppindexed; |
1088 | 3.18k | pindexed->pfixed = false; |
1089 | 3.18k | pindexed->cid = cid; |
1090 | 3.18k | pindexed->num_entries = 2; |
1091 | | /* set up the normalization information - not strictly necessary */ |
1092 | 3.18k | code = pcl_cs_indexed_set_norm_and_Decode(ppindexed, |
1093 | 3.18k | wht_ref[0], wht_ref[1], wht_ref[2], |
1094 | 3.18k | blk_ref[0], blk_ref[1], blk_ref[2] |
1095 | 3.18k | ); |
1096 | 3.18k | if (code < 0) |
1097 | 0 | return code; |
1098 | | |
1099 | 3.18k | pindexed->Decode[1] = 1; |
1100 | | |
1101 | 12.7k | for (i = 0; i < 3; i++) { |
1102 | 9.54k | pindexed->palette.data[i] = 255; |
1103 | 9.54k | pindexed->palette.data[i + 3] = pcolor1[i]; |
1104 | 9.54k | } |
1105 | | |
1106 | | /* the latter are not strictly necessary */ |
1107 | 3.18k | pindexed->pen_widths[0] = dflt_pen_width; |
1108 | 3.18k | pindexed->pen_widths[1] = dflt_pen_width; |
1109 | | |
1110 | 3.18k | return 0; |
1111 | 3.18k | } |
1112 | | |
1113 | | /* |
1114 | | * Install an indexed color space into the graphic state. If no indexed color |
1115 | | * space exists yet, build a default color space. |
1116 | | * |
1117 | | * Returns 0 on success, < 0 in the event of an error. |
1118 | | */ |
1119 | | int |
1120 | | pcl_cs_indexed_install(pcl_cs_indexed_t ** ppindexed, pcl_state_t * pcs) |
1121 | 205k | { |
1122 | 205k | pcl_cs_indexed_t *pindexed = *ppindexed; |
1123 | 205k | int code = 0; |
1124 | | |
1125 | 205k | if (pindexed == 0) { |
1126 | 0 | code = |
1127 | 0 | pcl_cs_indexed_build_default_cspace(pcs, ppindexed, pcs->memory); |
1128 | 0 | if (code < 0) |
1129 | 0 | return code; |
1130 | 0 | pindexed = *ppindexed; |
1131 | 0 | } |
1132 | | /* Really, to be consistent with the other interpreter's usage of the graphics library, |
1133 | | * we should call gs_setcolorspace(pindexed->pcspace->base_space), but if we do that |
1134 | | * we get a lot of differences in halftoned output. Just calling the 'install' procedure |
1135 | | * for the base space doesn't modify pgs->color[0].ccolor elements for RGB, which |
1136 | | * gs_setcolorspace() does. I think it would be worthwhile someone investigating why this is |
1137 | | * one day, some of the differences looked like progressions. |
1138 | | */ |
1139 | 205k | code = (*pindexed->pcspace->base_space->type->install_cspace) |
1140 | 205k | (pindexed->pcspace->base_space, pcs->pgs); |
1141 | 205k | if (code < 0) |
1142 | 0 | return code; |
1143 | 205k | return gs_setcolorspace(pcs->pgs, pindexed->pcspace); |
1144 | 205k | } |
1145 | | |
1146 | | /* |
1147 | | * Return true if the given entry in the color palette represents white, |
1148 | | * false otherwise. |
1149 | | * |
1150 | | * As with many other parts of this code, the determination of what is "white" |
1151 | | * is done, for practical reasons, in source color space. HP's implementations |
1152 | | * make the same determination in device color space (but prior to dithering). |
1153 | | * In the absence of color lookup tables, the two will give the same result. |
1154 | | * An inverting color lookup table will, however, cause the two approaches to |
1155 | | * vary. |
1156 | | */ |
1157 | | bool |
1158 | | pcl_cs_indexed_is_white(const pcl_cs_indexed_t * pindexed, int indx) |
1159 | 3.62M | { |
1160 | 3.62M | const byte *pb = 0; |
1161 | | |
1162 | 3.62M | if (pindexed == 0) |
1163 | 0 | return true; |
1164 | 3.62M | if ((indx < 0) || (indx >= pindexed->num_entries)) |
1165 | 0 | return false; |
1166 | 3.62M | pb = pindexed->palette.data + 3 * indx; |
1167 | 3.62M | return (pb[0] == 0xff) && (pb[1] == 0xff) && (pb[2] == 0xff); |
1168 | 3.62M | } |
1169 | | |
1170 | | /* |
1171 | | * Return true if the given entry in the color palette is black, false |
1172 | | * otherwise. |
1173 | | * |
1174 | | * The determination of "blackness" is made in source space, rather than in |
1175 | | * device space (prior to dither). The latter would be more correct, but is |
1176 | | * not as easily accomplished, and only in very unusual circumstances will the |
1177 | | * two produce different results. |
1178 | | */ |
1179 | | bool |
1180 | | pcl_cs_indexed_is_black(const pcl_cs_indexed_t * pindexed, int indx) |
1181 | 6.36k | { |
1182 | 6.36k | const byte *pb = 0; |
1183 | | |
1184 | 6.36k | if ((pindexed == 0) || (indx < 0) || (indx >= pindexed->num_entries)) |
1185 | 0 | return false; |
1186 | 6.36k | pb = pindexed->palette.data + 3 * indx; |
1187 | 6.36k | return (pb[0] == 0) && (pb[1] == 0) && (pb[2] == 0); |
1188 | 6.36k | } |
1189 | | |
1190 | | /* |
1191 | | * One time initialization. This exists only because of the possibility that |
1192 | | * BSS may not be initialized. |
1193 | | */ |
1194 | | void |
1195 | | pcl_cs_indexed_init(pcl_state_t * pcs) |
1196 | 16.1k | { |
1197 | 16.1k | pcs->pdflt_cs_indexed = 0; |
1198 | 16.1k | } |