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 /*$Id: gdevdevn.c 10394 2009-11-27 19:07:02Z ray $ */
14 /* Example DeviceN process color model devices. */
15
16 #include "math_.h"
17 #include "string_.h"
18 #include "gdevprn.h"
19 #include "gsparam.h"
20 #include "gscrd.h"
21 #include "gscrdp.h"
22 #include "gxlum.h"
23 #include "gdevdcrd.h"
24 #include "gstypes.h"
25 #include "gxdcconv.h"
26 #include "gdevdevn.h"
27 #include "gsequivc.h"
28 #include "gxblend.h"
29 #include "gdevp14.h"
30
31 /*
32 * Utility routines for common DeviceN related parameters:
33 * SeparationColorNames, SeparationOrder, and MaxSeparations
34 */
35
36 /* Convert a gray color space to DeviceN colorants. */
37 void
gray_cs_to_devn_cm(gx_device * dev,int * map,frac gray,frac out[])38 gray_cs_to_devn_cm(gx_device * dev, int * map, frac gray, frac out[])
39 {
40 int i = dev->color_info.num_components - 1;
41
42 for(; i >= 0; i--) /* Clear colors */
43 out[i] = frac_0;
44 if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
45 out[i] = frac_1 - gray;
46 }
47
48 /* Convert an RGB color space to DeviceN colorants. */
49 void
rgb_cs_to_devn_cm(gx_device * dev,int * map,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])50 rgb_cs_to_devn_cm(gx_device * dev, int * map,
51 const gs_imager_state *pis, frac r, frac g, frac b, frac out[])
52 {
53 int i = dev->color_info.num_components - 1;
54 frac cmyk[4];
55
56 for(; i >= 0; i--) /* Clear colors */
57 out[i] = frac_0;
58 color_rgb_to_cmyk(r, g, b, pis, cmyk);
59 if ((i = map[0]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
60 out[i] = cmyk[0];
61 if ((i = map[1]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
62 out[i] = cmyk[1];
63 if ((i = map[2]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
64 out[i] = cmyk[2];
65 if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
66 out[i] = cmyk[3];
67 }
68
69 /* Convert a CMYK color space to DeviceN colorants. */
70 void
cmyk_cs_to_devn_cm(gx_device * dev,int * map,frac c,frac m,frac y,frac k,frac out[])71 cmyk_cs_to_devn_cm(gx_device * dev, int * map,
72 frac c, frac m, frac y, frac k, frac out[])
73 {
74 int i = dev->color_info.num_components - 1;
75
76 for(; i >= 0; i--) /* Clear colors */
77 out[i] = frac_0;
78 if ((i = map[0]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
79 out[i] = c;
80 if ((i = map[1]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
81 out[i] = m;
82 if ((i = map[2]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
83 out[i] = y;
84 if ((i = map[3]) != GX_DEVICE_COLOR_MAX_COMPONENTS)
85 out[i] = k;
86 }
87
88 /*
89 * This utility routine calculates the number of bits required to store
90 * color information. In general the values are rounded up to an even
91 * byte boundary except those cases in which mulitple pixels can evenly
92 * into a single byte.
93 *
94 * The parameter are:
95 * ncomp - The number of components (colorants) for the device. Valid
96 * values are 1 to GX_DEVICE_COLOR_MAX_COMPONENTS
97 * bpc - The number of bits per component. Valid values are 1, 2, 4, 5,
98 * and 8.
99 * Input values are not tested for validity.
100 */
101 int
bpc_to_depth(int ncomp,int bpc)102 bpc_to_depth(int ncomp, int bpc)
103 {
104 static const byte depths[4][8] = {
105 {1, 2, 0, 4, 8, 0, 0, 8},
106 {2, 4, 0, 8, 16, 0, 0, 16},
107 {4, 8, 0, 16, 16, 0, 0, 24},
108 {4, 8, 0, 16, 32, 0, 0, 32}
109 };
110
111 if (ncomp <=4 && bpc <= 8)
112 return depths[ncomp -1][bpc-1];
113 else
114 return (ncomp * bpc + 7) & 0xf8;
115 }
116
117 #define compare_color_names(name, name_size, str, str_size) \
118 (name_size == str_size && \
119 (strncmp((const char *)name, (const char *)str, name_size) == 0))
120
121 /*
122 * This routine will check if a name matches any item in a list of process
123 * color model colorant names.
124 */
125 static bool
check_process_color_names(fixed_colorant_names_list plist,const gs_param_string * pstring)126 check_process_color_names(fixed_colorant_names_list plist,
127 const gs_param_string * pstring)
128 {
129 if (plist) {
130 uint size = pstring->size;
131
132 while( *plist) {
133 if (compare_color_names(*plist, strlen(*plist), pstring->data, size)) {
134 return true;
135 }
136 plist++;
137 }
138 }
139 return false;
140 }
141
142 /*
143 * This routine will check to see if the color component name match those
144 * of either the process color model colorants or the names on the
145 * SeparationColorNames list.
146 *
147 * Parameters:
148 * dev - pointer to device data structure.
149 * pname - pointer to name (zero termination not required)
150 * nlength - length of the name
151 *
152 * This routine returns a positive value (0 to n) which is the device colorant
153 * number if the name is found. It returns a negative value if not found.
154 */
155 int
check_pcm_and_separation_names(const gx_device * dev,const gs_devn_params * pparams,const char * pname,int name_size,int component_type)156 check_pcm_and_separation_names(const gx_device * dev,
157 const gs_devn_params * pparams, const char * pname,
158 int name_size, int component_type)
159 {
160 fixed_colorant_name * pcolor = pparams->std_colorant_names;
161 int color_component_number = 0;
162 int i;
163
164 /* Check if the component is in the process color model list. */
165 if (pcolor) {
166 while( *pcolor) {
167 if (compare_color_names(pname, name_size, *pcolor, strlen(*pcolor)))
168 return color_component_number;
169 pcolor++;
170 color_component_number++;
171 }
172 }
173
174 /* Check if the component is in the separation names list. */
175 {
176 const gs_separations * separations = &pparams->separations;
177 int num_spot = separations->num_separations;
178
179 for (i=0; i<num_spot; i++) {
180 if (compare_color_names((const char *)separations->names[i].data,
181 separations->names[i].size, pname, name_size)) {
182 return color_component_number;
183 }
184 color_component_number++;
185 }
186 }
187
188 return -1;
189 }
190
191 /*
192 * This routine will check to see if the color component name match those
193 * that are available amoung the current device's color components.
194 *
195 * Parameters:
196 * dev - pointer to device data structure.
197 * pname - pointer to name (zero termination not required)
198 * nlength - length of the name
199 * component_type - separation name or not
200 * pdevn_params - pointer to device's DeviceN paramters
201 * pequiv_colors - pointer to equivalent color structure (may be NULL)
202 *
203 * This routine returns a positive value (0 to n) which is the device colorant
204 * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
205 * the color component is found but is not being used due to the
206 * SeparationOrder device parameter. It returns a negative value if not found.
207 *
208 * This routine will also add separations to the device if space is
209 * available.
210 */
211 int
devn_get_color_comp_index(gx_device * dev,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors,const char * pname,int name_size,int component_type,int auto_spot_colors)212 devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params,
213 equivalent_cmyk_color_params * pequiv_colors,
214 const char * pname, int name_size, int component_type,
215 int auto_spot_colors)
216 {
217 int num_order = pdevn_params->num_separation_order_names;
218 int color_component_number = 0;
219 int max_spot_colors = GX_DEVICE_MAX_SEPARATIONS - MAX_DEVICE_PROCESS_COLORS;
220
221 /*
222 * Check if the component is in either the process color model list
223 * or in the SeparationNames list.
224 */
225 color_component_number = check_pcm_and_separation_names(dev, pdevn_params,
226 pname, name_size, component_type);
227
228 /* If we have a valid component */
229 if (color_component_number >= 0) {
230 /* Check if the component is in the separation order map. */
231 if (num_order)
232 color_component_number =
233 pdevn_params->separation_order_map[color_component_number];
234 else
235 /*
236 * We can have more spot colors than we can image. We simply
237 * ignore the component (i.e. treat it the same as we would
238 * treat a component that is not in the separation order map).
239 * Note: Most device do not allow more spot colors than we can
240 * image. (See the options for auto_spot_color in gdevdevn.h.)
241 */
242 if (color_component_number >= dev->color_info.num_components)
243 color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
244
245 return color_component_number;
246 }
247 /*
248 * The given name does not match any of our current components or
249 * separations. Check if we should add the spot color to our list.
250 * If the SeparationOrder parameter has been specified then we should
251 * already have our complete list of desired spot colorants.
252 */
253 if (component_type != SEPARATION_NAME ||
254 auto_spot_colors == NO_AUTO_SPOT_COLORS ||
255 pdevn_params->num_separation_order_names != 0)
256 return -1; /* Do not add --> indicate colorant unknown. */
257 /*
258 * Check if we have room for another spot colorant.
259 */
260 if (auto_spot_colors == ENABLE_AUTO_SPOT_COLORS)
261 max_spot_colors = dev->color_info.num_components -
262 pdevn_params->num_std_colorant_names;
263 if (pdevn_params->separations.num_separations < max_spot_colors) {
264 byte * sep_name;
265 gs_separations * separations = &pdevn_params->separations;
266 int sep_num = separations->num_separations++;
267
268 /* We have a new spot colorant - put in stable memory to avoid "restore" */
269 sep_name = gs_alloc_bytes(dev->memory->stable_memory,
270 name_size, "devn_get_color_comp_index");
271 memcpy(sep_name, pname, name_size);
272 separations->names[sep_num].size = name_size;
273 separations->names[sep_num].data = sep_name;
274 color_component_number = sep_num + pdevn_params->num_std_colorant_names;
275 if (color_component_number >= dev->color_info.num_components)
276 color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
277 else
278 pdevn_params->separation_order_map[color_component_number] =
279 color_component_number;
280
281 if (pequiv_colors != NULL) {
282 /* Indicate that we need to find equivalent CMYK color. */
283 pequiv_colors->color[sep_num].color_info_valid = false;
284 pequiv_colors->all_color_info_valid = false;
285 }
286 }
287
288 return color_component_number;
289 }
290
291 #define set_param_array(a, d, s)\
292 (a.data = d, a.size = s, a.persistent = false);
293
294 /* Get parameters. We provide a default CRD. */
295 int
devn_get_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)296 devn_get_params(gx_device * pdev, gs_param_list * plist,
297 gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
298 {
299 int code;
300 bool seprs = false;
301 gs_param_string_array scna;
302 gs_param_string_array sona;
303
304 set_param_array(scna, NULL, 0);
305 set_param_array(sona, NULL, 0);
306
307 if ( (code = sample_device_crd_get_params(pdev, plist, "CRDDefault")) < 0 ||
308 (code =
309 param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
310 (code = param_write_name_array(plist, "SeparationOrder", &sona)) < 0 ||
311 (code = param_write_bool(plist, "Separations", &seprs)) < 0)
312 return code;
313
314 return 0;
315 }
316 #undef set_param_array
317
318 #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
319 BEGIN\
320 switch (code = pread(plist, (param_name = pname), &(pa))) {\
321 case 0:\
322 if ((pa).size != psize) {\
323 ecode = gs_note_error(gs_error_rangecheck);\
324 (pa).data = 0; /* mark as not filled */\
325 } else
326 #define END_ARRAY_PARAM(pa, e)\
327 goto e;\
328 default:\
329 ecode = code;\
330 e: param_signal_error(plist, param_name, ecode);\
331 case 1:\
332 (pa).data = 0; /* mark as not filled */\
333 }\
334 END
335
336 /*
337 * Utility routine for handling DeviceN related parameters. This routine
338 * may modify the color_info, devn_params, and the equiv_cmyk_colors fields.
339 *
340 * Note: This routine does not restore values in case of a problem. This
341 * is left to the caller.
342 */
343 int
devn_put_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)344 devn_put_params(gx_device * pdev, gs_param_list * plist,
345 gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
346 {
347 int code = 0, ecode;
348 gs_param_name param_name;
349 int npcmcolors = pdevn_params->num_std_colorant_names;
350 int num_spot = pdevn_params->separations.num_separations;
351 bool num_spot_changed = false;
352 int num_order = pdevn_params->num_separation_order_names;
353 int max_sep = pdevn_params->max_separations;
354 int page_spot_colors = pdevn_params->page_spot_colors;
355 gs_param_string_array scna; /* SeparationColorNames array */
356 gs_param_string_array sona; /* SeparationOrder names array */
357
358 /* Get the SeparationOrder names */
359 BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationOrder",
360 sona, sona.size, sone)
361 {
362 break;
363 } END_ARRAY_PARAM(sona, sone);
364 if (sona.data != 0 && sona.size > GX_DEVICE_COLOR_MAX_COMPONENTS)
365 return_error(gs_error_rangecheck);
366
367 /* Get the SeparationColorNames */
368 BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames",
369 scna, scna.size, scne)
370 {
371 break;
372 } END_ARRAY_PARAM(scna, scne);
373 if (scna.data != 0 && scna.size > GX_DEVICE_MAX_SEPARATIONS)
374 return_error(gs_error_rangecheck);
375
376 /* Separations are only valid with a subrtractive color model */
377 if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
378 /*
379 * Process the SeparationColorNames. Remove any names that already
380 * match the process color model colorant names for the device.
381 */
382 if (scna.data != 0) {
383 int i;
384 int num_names = scna.size;
385 fixed_colorant_names_list pcomp_names =
386 pdevn_params->std_colorant_names;
387
388 for (i = num_spot = 0; i < num_names; i++) {
389 /* Verify that the name is not one of our process colorants */
390 if (!check_process_color_names(pcomp_names, &scna.data[i])) {
391 byte * sep_name;
392 int name_size = scna.data[i].size;
393
394 /* We have a new separation */
395 sep_name = (byte *)gs_alloc_bytes(pdev->memory,
396 name_size, "devicen_put_params_no_sep_order");
397 memcpy(sep_name, scna.data[i].data, name_size);
398 pdevn_params->separations.names[num_spot].size = name_size;
399 pdevn_params->separations.names[num_spot].data = sep_name;
400 if (pequiv_colors != NULL) {
401 /* Indicate that we need to find equivalent CMYK color. */
402 pequiv_colors->color[num_spot].color_info_valid = false;
403 pequiv_colors->all_color_info_valid = false;
404 }
405 num_spot++;
406 }
407 }
408 pdevn_params->separations.num_separations = num_spot;
409 num_spot_changed = true;
410 for (i = 0; i < num_spot + npcmcolors; i++)
411 pdevn_params->separation_order_map[i] = i;
412 }
413 /*
414 * Process the SeparationOrder names.
415 */
416 if (sona.data != 0) {
417 int i, comp_num;
418
419 num_order = sona.size;
420 for (i = 0; i < num_spot + npcmcolors; i++)
421 pdevn_params->separation_order_map[i] =
422 GX_DEVICE_COLOR_MAX_COMPONENTS;
423 for (i = 0; i < num_order; i++) {
424 /*
425 * Check if names match either the process color model or
426 * SeparationColorNames. If not then error.
427 */
428 if ((comp_num = check_pcm_and_separation_names(pdev, pdevn_params,
429 (const char *)sona.data[i].data, sona.data[i].size, 0)) < 0) {
430 return_error(gs_error_rangecheck);
431 }
432 pdevn_params->separation_order_map[comp_num] = i;
433 }
434 }
435 /*
436 * Adobe says that MaxSeparations is supposed to be 'read only'
437 * however we use this to allow the specification of the maximum
438 * number of separations. Memory is allocated for the specified
439 * number of separations. This allows us to then accept separation
440 * colors in color spaces even if they we not specified at the start
441 * of the image file.
442 */
443 code = param_read_int(plist, param_name = "MaxSeparations", &max_sep);
444 switch (code) {
445 default:
446 param_signal_error(plist, param_name, code);
447 case 1:
448 break;
449 case 0:
450 if (max_sep < 1 || max_sep > GX_DEVICE_COLOR_MAX_COMPONENTS)
451 return_error(gs_error_rangecheck);
452 }
453 /*
454 * The PDF interpreter scans the resources for pages to try to
455 * determine the number of spot colors. (Unfortuneately there is
456 * no way to determine the number of spot colors for a PS page
457 * except to interpret the entire page.) The spot color count for
458 * a PDF page may be high since there may be spot colors in a PDF
459 * page's resources that are not used. However this does give us
460 * an upper limit on the number of spot colors. A value of -1
461 * indicates that the number of spot colors in unknown (a PS file).
462 */
463 code = param_read_int(plist, param_name = "PageSpotColors",
464 &page_spot_colors);
465 switch (code) {
466 default:
467 param_signal_error(plist, param_name, code);
468 case 1:
469 break;
470 case 0:
471 if (page_spot_colors < -1)
472 return_error(gs_error_rangecheck);
473 if (page_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS)
474 page_spot_colors = GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS;
475 /* Need to leave room for the process colors in GX_DEVICE_COLOR_MAX_COMPONENTS */
476 }
477 /*
478 * The DeviceN device can have zero components if nothing has been
479 * specified. This causes some problems so force at least one
480 * component until something is specified.
481 */
482 if (!pdev->color_info.num_components)
483 pdev->color_info.num_components = 1;
484 /*
485 * Update the number of device components if we have changes in
486 * SeparationColorNames, SeparationOrder, or MaxSeparations.
487 */
488 if (num_spot_changed || pdevn_params->max_separations != max_sep ||
489 pdevn_params->num_separation_order_names != num_order ||
490 pdevn_params->page_spot_colors != page_spot_colors) {
491 pdevn_params->separations.num_separations = num_spot;
492 pdevn_params->num_separation_order_names = num_order;
493 pdevn_params->max_separations = max_sep;
494 pdevn_params->page_spot_colors = page_spot_colors;
495 if (max_sep != 0)
496 pdev->color_info.max_components = max_sep;
497 /*
498 * If we have SeparationOrder specified then the number of
499 * components is given by the number of names in the list.
500 * Otherwise check if the MaxSeparations parameter has specified
501 * a value. If so then use that value, otherwise use the number
502 * of ProcessColorModel components plus the number of
503 * SeparationColorNames is used.
504 */
505 pdev->color_info.num_components = (num_order)
506 ? num_order
507 : (pdevn_params->max_separations)
508 ? pdevn_params->max_separations
509 : (page_spot_colors >= 0)
510 ? npcmcolors + num_spot + page_spot_colors
511 : pdev->color_info.max_components;
512 if (pdev->color_info.num_components >
513 pdev->color_info.max_components)
514 pdev->color_info.num_components =
515 pdev->color_info.max_components;
516 #if !USE_COMPRESSED_ENCODING
517 /*
518 * See earlier comment about the depth and non compressed
519 * pixel encoding.
520 */
521 pdev->color_info.depth = bpc_to_depth(pdev->color_info.num_components,
522 pdevn_params->bitspercomponent);
523 #endif
524 }
525 }
526 return code;
527 }
528
529 /*
530 * Utility routine for handling DeviceN related parameters in a
531 * standard raster printer type device.
532 */
533 int
devn_printer_put_params(gx_device * pdev,gs_param_list * plist,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pequiv_colors)534 devn_printer_put_params(gx_device * pdev, gs_param_list * plist,
535 gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pequiv_colors)
536 {
537 int code;
538 /* Save current data in case we have a problem */
539 gx_device_color_info save_info = pdev->color_info;
540 gs_devn_params saved_devn_params = *pdevn_params;
541 equivalent_cmyk_color_params saved_equiv_colors;
542
543 if (pequiv_colors != NULL)
544 saved_equiv_colors = *pequiv_colors;
545
546 /* Use utility routine to handle parameters */
547 code = devn_put_params(pdev, plist, pdevn_params, pequiv_colors);
548
549 /* Check for default printer parameters */
550 if (code >= 0)
551 code = gdev_prn_put_params(pdev, plist);
552
553 /* If we have an error then restore original data. */
554 if (code < 0) {
555 pdev->color_info = save_info;
556 *pdevn_params = saved_devn_params;
557 if (pequiv_colors != NULL)
558 *pequiv_colors = saved_equiv_colors;
559 return code;
560 }
561
562 /* If anything changed, then close the device, etc. */
563 if (memcmp(&pdev->color_info, &save_info, sizeof(gx_device_color_info)) ||
564 memcmp(pdevn_params, &saved_devn_params,
565 sizeof(gs_devn_params)) ||
566 (pequiv_colors != NULL &&
567 memcmp(pequiv_colors, &saved_equiv_colors,
568 sizeof(equivalent_cmyk_color_params)))) {
569 gs_closedevice(pdev);
570 /* Reset the sparable and linear shift, masks, bits. */
571 set_linear_color_bits_mask_shift(pdev);
572 }
573 /*
574 * Also check for parameters which are being passed from the PDF 1.4
575 * compositior clist write device. This device needs to pass info
576 * to the PDF 1.4 compositor clist reader device. However this device
577 * is not crated until the clist is being read. Thus we have to buffer
578 * this info in the output device. (This is only needed for devices
579 * which support spot colors.)
580 */
581 code = pdf14_put_devn_params(pdev, pdevn_params, plist);
582 return code;
583 }
584
585 /*
586 * The following routines are for compressing colorant values into a 64 bit
587 * gx_color_index value. This is needed since Ghostscript uses an integer type
588 * (usually 64 bit long long) as the representation for a pixel. This is a
589 * problem for handling output devices which support spot colors. Ideally these
590 * devices should be able to handle any number of colorants. This would require
591 * an arbitrarily large number of bits to represent a pixel.
592 *
593 * See comments before devn_encode_compressed_color for more information.
594 */
595
596 /* GC procedures */
597 static
ENUM_PTRS_WITH(compressed_color_list_enum_ptrs,compressed_color_list_t * plist)598 ENUM_PTRS_WITH(compressed_color_list_enum_ptrs, compressed_color_list_t *plist)
599 {
600 if (index < plist->num_sub_level_ptrs)
601 ENUM_RETURN(plist->u.sub_level_ptrs[index]);
602 return 0;
603 }
604 ENUM_PTRS_END
605
RELOC_PTRS_WITH(compressed_color_list_reloc_ptrs,compressed_color_list_t * plist)606 static RELOC_PTRS_WITH(compressed_color_list_reloc_ptrs, compressed_color_list_t *plist)
607 {
608 int i;
609
610 for (i = 0; i < plist->num_sub_level_ptrs; i++) {
611 RELOC_PTR(compressed_color_list_t, u.sub_level_ptrs[i]);
612 }
613 }
614 RELOC_PTRS_END
615
616 gs_private_st_composite(st_compressed_color_list, compressed_color_list_t,
617 "encode color list", compressed_color_list_enum_ptrs,
618 compressed_color_list_reloc_ptrs);
619 /*
620 * A routine for debugging the encoded color colorant list. This routine
621 * dumps the contents of the list.
622 */
623 void
print_compressed_color_list(compressed_color_list_t * pcomp_list,int num_comp)624 print_compressed_color_list(compressed_color_list_t * pcomp_list, int num_comp)
625 {
626 int i, j, comp_num, comp;
627 comp_bit_map_list_t * pcomp_bit_map;
628
629 if (pcomp_list == NULL)
630 return;
631
632 /* Indent our print out for sub levels */
633 for (i = TOP_ENCODED_LEVEL - pcomp_list->level_num_comp; i > 0; i--)
634 dlprintf(" ");
635 dlprintf1("List level = %d\n", pcomp_list->level_num_comp);
636 /*
637 * Print the colorant bit maps for this level.
638 */
639 for (i = NUM_ENCODE_LIST_ITEMS - 1; i >= pcomp_list->first_bit_map; i--) {
640 pcomp_bit_map = &(pcomp_list->u.comp_data[i]);
641 /* Indent our print out for sub levels */
642 for (j = TOP_ENCODED_LEVEL - pcomp_list->level_num_comp; j > 0; j--)
643 dlprintf(" ");
644 dlprintf4("%3d%4d%4d %d ", i, pcomp_bit_map->num_comp,
645 pcomp_bit_map->num_non_solid_comp, pcomp_bit_map->solid_not_100);
646 for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
647 comp = colorant_present(pcomp_bit_map, colorants, comp_num);
648 dlprintf1("%d", comp);
649 if ((comp_num & 7) == 0) /* Separate into groups of 8 bits */
650 dlprintf(" ");
651 }
652 dlprintf(" ");
653 for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
654 comp = colorant_present(pcomp_bit_map, solid_colorants, comp_num);
655 dlprintf1("%d", comp);
656 if ((comp_num & 7) == 0) /* Separate into groups of 8 bits */
657 dlprintf(" ");
658 }
659 dlprintf("\n");
660 }
661
662 /*
663 * Print the sub levels.
664 */
665 for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++)
666 print_compressed_color_list(pcomp_list->u.sub_level_ptrs[i], num_comp);
667
668 return;
669 }
670
671 /*
672 * Allocate an list level element for our encode color list.
673 */
674 compressed_color_list_t *
alloc_compressed_color_list_elem(gs_memory_t * mem,int num_comps)675 alloc_compressed_color_list_elem(gs_memory_t * mem, int num_comps)
676 {
677 compressed_color_list_t * plist =
678 gs_alloc_struct(mem, compressed_color_list_t, &st_compressed_color_list,
679 "alloc_compressed_color_list");
680 if (plist != NULL) {
681 /* Initialize the data in the element. */
682 memset(plist, 0, size_of(*plist));
683 plist->level_num_comp = num_comps;
684 plist->first_bit_map = NUM_ENCODE_LIST_ITEMS;
685 }
686 return plist;
687 }
688
689 /*
690 * Free the elements of a compressed color list.
691 */
692 void
free_compressed_color_list(gs_memory_t * mem,compressed_color_list_t * pcomp_list)693 free_compressed_color_list(gs_memory_t * mem,
694 compressed_color_list_t * pcomp_list)
695 {
696 int i;
697
698 if (pcomp_list == NULL)
699 return;
700
701 /* Discard the sub levels. */
702 for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++)
703 free_compressed_color_list(mem, pcomp_list->u.sub_level_ptrs[i]);
704
705 gs_free_object(mem, pcomp_list, "free_compressed_color_list");
706 return;
707 }
708
709 /*
710 * Free a set of separation names
711 */
712 void
free_separation_names(gs_memory_t * mem,gs_separations * pseparation)713 free_separation_names(gs_memory_t * mem,
714 gs_separations * pseparation)
715 {
716 int i;
717
718 /* Discard the sub levels. */
719 for (i = 0; i < pseparation->num_separations; i++)
720 gs_free_object(mem->stable_memory, pseparation->names[i].data,
721 "free_separation_names");
722 pseparation->num_separations = 0;
723 return;
724 }
725
726 /*
727 * Add a new set of bit mapped colorant lists to our list of encoded color
728 * colorants.
729 */
730 static bool
sub_level_add_compressed_color_list(gs_memory_t * mem,comp_bit_map_list_t * pnew_comp_bit_map,compressed_color_list_t * pcomp_list,gx_color_index * plist_index)731 sub_level_add_compressed_color_list(gs_memory_t * mem,
732 comp_bit_map_list_t * pnew_comp_bit_map,
733 compressed_color_list_t * pcomp_list, gx_color_index * plist_index)
734 {
735 int i, entry_num;
736 int num_non_solid_comp = pnew_comp_bit_map->num_non_solid_comp;
737 bool status;
738
739 /*
740 * Check if this is the level for the specified number of entries. If so
741 * then add the bit map to this level (if we have room).
742 */
743 if (num_non_solid_comp >= pcomp_list->level_num_comp) {
744 entry_num = pcomp_list->first_bit_map - 1;
745
746 if (entry_num > pcomp_list->num_sub_level_ptrs) {
747 memcpy(&(pcomp_list->u.comp_data[entry_num]), pnew_comp_bit_map,
748 size_of(comp_bit_map_list_t));
749 pcomp_list->first_bit_map = entry_num;
750 *plist_index =
751 ((gx_color_index) entry_num) << (NUM_GX_COLOR_INDEX_BITS - 8);
752 return true;
753 }
754 return false;
755 }
756 /*
757 * Try to insert the bit map into the sub levels.
758 */
759 for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
760 status = sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
761 pcomp_list->u.sub_level_ptrs[i], plist_index);
762 if (status) {
763 *plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
764 + (*plist_index >> 8);
765 return true;
766 }
767 }
768 /*
769 * If we did not add this bit map into a sub level then create a new sub
770 * level and insert it there.
771 */
772 entry_num = pcomp_list->num_sub_level_ptrs;
773 if (entry_num < pcomp_list->first_bit_map) {
774 pcomp_list->u.sub_level_ptrs[entry_num] =
775 alloc_compressed_color_list_elem(mem, pcomp_list->level_num_comp - 1);
776 if (pcomp_list->u.sub_level_ptrs[entry_num] != NULL) {
777 pcomp_list->num_sub_level_ptrs++;
778 status = sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
779 pcomp_list->u.sub_level_ptrs[entry_num], plist_index);
780 if (status) {
781 *plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
782 + (*plist_index >> 8);
783 return true;
784 }
785 }
786 }
787 /*
788 * If we get to here then there was no space available in this list element.
789 */
790 return false;
791 }
792
793 /*
794 * Add a new bit mapped colorant list to our list of encoded color colorants.
795 *
796 * Our simple linear search for entries gets very inefficient if we have many
797 * entries. So we are doing two things to minimize the number of entries.
798 * We need separate entries for each combination of solid colorants. if we
799 * do not have many non solid colorants, we use non solid colorants even for
800 * solid colorants. For small numbers of colorants, we add more colorants
801 * to try to create an entry that can be used for more situations. We add extra
802 * process color colorants since these are the ones most likely to be mixed
803 * with spot colors.
804 */
805 static bool
add_compressed_color_list(gs_memory_t * mem,comp_bit_map_list_t * pnew_comp_bit_map,compressed_color_list_t * pcomp_list,gx_color_index * plist_index)806 add_compressed_color_list(gs_memory_t * mem,
807 comp_bit_map_list_t * pnew_comp_bit_map,
808 compressed_color_list_t * pcomp_list, gx_color_index * plist_index)
809 {
810 int num_comp = pnew_comp_bit_map->num_comp;
811 int num_non_solid = pnew_comp_bit_map->num_non_solid_comp;
812 int num_solid = num_comp - num_non_solid;
813 int comp_num = 0;
814
815 /*
816 * If we have room for more 'non solid' colorants then convert some of
817 * the solid colorants to using the non solid encodings.
818 */
819 while (num_non_solid < MIN_ENCODED_COMPONENTS && num_solid > 0) {
820 if (colorant_present(pnew_comp_bit_map, solid_colorants, comp_num)) {
821 clear_colorant_present(pnew_comp_bit_map,
822 solid_colorants, comp_num);
823 num_solid--;
824 num_non_solid++;
825 }
826 comp_num++;
827 }
828 if (num_non_solid < MIN_ENCODED_COMPONENTS) {
829 /*
830 * For small numbers of colorants, we add more colorants to try to
831 * create an entry that can be used for more situations.
832 */
833 for (comp_num = 0; num_comp < MIN_ENCODED_COMPONENTS; comp_num++) {
834 if ((colorant_present(pnew_comp_bit_map, colorants, comp_num)) == 0) {
835 set_colorant_present(pnew_comp_bit_map, colorants, comp_num);
836 num_non_solid++;
837 num_comp++;
838 }
839 }
840 }
841 pnew_comp_bit_map->num_comp = num_comp;
842 pnew_comp_bit_map->num_non_solid_comp = num_non_solid;
843 return sub_level_add_compressed_color_list(mem, pnew_comp_bit_map,
844 pcomp_list, plist_index);
845 }
846
847 /*
848 * Initialize our encode color list. When we initialize the list, we add two
849 * initial colorant maps. The first one is good for any image that uses zeven
850 * or fewer colorants. The second is good for any image which uses seven spot
851 * colors (or less) and no process colors. These are placed at the start of
852 * the list to minimize the add and search times for these common situations.
853 */
854 static compressed_color_list_t *
init_compressed_color_list(gs_memory_t * mem)855 init_compressed_color_list(gs_memory_t *mem)
856 {
857 /*
858 * Create our first list element.
859 */
860 compressed_color_list_t * plist =
861 alloc_compressed_color_list_elem(mem, TOP_ENCODED_LEVEL);
862
863 /*
864 * Add a first colorant bit map to the list. This bit map covers the first
865 * TOP_ENCODED_LEVEL colorants. Typically this covers CMYK plus the
866 * first three spot colors. This bit map should handle many situations.
867 */
868 if (plist != NULL) {
869 int comp_num;
870 comp_bit_map_list_t comp_bit_map;
871 gx_color_index temp;
872
873 /*
874 * Add a first colorant bit map to the list. This bit map covers the
875 * first TOP_ENCODED_LEVEL colorants. Typically this covers CMYK plus
876 * the first three spot colors. This bit map should handle many
877 * situations.
878 */
879 memset(&comp_bit_map, 0, size_of(comp_bit_map));
880 for (comp_num = 0; comp_num < TOP_ENCODED_LEVEL; comp_num++)
881 set_colorant_present(&comp_bit_map, colorants, comp_num);
882 comp_bit_map.num_comp =
883 comp_bit_map.num_non_solid_comp = TOP_ENCODED_LEVEL;
884 add_compressed_color_list(mem, &comp_bit_map, plist, &temp);
885 /*
886 * Add a second colorant bit map to the list. This bit map covers the
887 * first TOP_ENCODED_LEVEL colorants after the first four colorants.
888 * Typically this covers the first seven spot colors. This bit map is
889 * being placed to cover images that use only spot colors.
890 */
891 memset(&comp_bit_map, 0, size_of(comp_bit_map));
892 for (comp_num = 4; comp_num < TOP_ENCODED_LEVEL + 4; comp_num++)
893 set_colorant_present(&comp_bit_map, colorants, comp_num);
894 comp_bit_map.num_comp =
895 comp_bit_map.num_non_solid_comp = TOP_ENCODED_LEVEL;
896 add_compressed_color_list(mem, &comp_bit_map, plist, &temp);
897 }
898 return plist;
899 }
900
901 /*
902 * For most combinations of colorants we use 8 bits for saving the colorant
903 * value. However if we get above 7 colorants (in a pixel, not total) we use
904 * fewer bits. The constraint is that the size of the index value plus the
905 * the number of colorants being used times size of the colorant value saved
906 * must fit into a gx_color_index value.
907 */
908 int num_comp_bits[MAX_ENCODED_COMPONENTS + 1] = {
909 8, /* 0 colorants - not used */
910 8, /* 1 colorants */
911 8, /* 2 colorants */
912 8, /* 3 colorants */
913 8, /* 4 colorants */
914 8, /* 5 colorants */
915 8, /* 6 colorants */
916 8, /* 7 colorants */
917 7, /* 8 colorants */
918 6, /* 9 colorants */
919 5, /* 10 colorants */
920 5, /* 11 colorants */
921 4, /* 12 colorants */
922 4, /* 13 colorants */
923 4 /* 14 colorants */
924 };
925
926 /*
927 * Values used to decompressed the colorants in our encoded values back into
928 * a gx_color value. The color value will be (comp_bits * entry) >> 8
929 * The number of bits in comp_bits are defined in the num_comp_bits table.
930 * These values are chosen to expand these bit combinations back to 16 bit values
931 * (after shifting right 8 bits).
932 */
933 #define gx_color_value_factor(num_bits) \
934 ((gx_max_color_value << 8) + 0xff) / ((1 << num_bits) - 1)
935
936 int comp_bit_factor[MAX_ENCODED_COMPONENTS + 1] = {
937 gx_color_value_factor(8), /* 0 colorants (8 bits) */
938 gx_color_value_factor(8), /* 1 colorants (8 bits) */
939 gx_color_value_factor(8), /* 2 colorants (8 bits) */
940 gx_color_value_factor(8), /* 3 colorants (8 bits) */
941 gx_color_value_factor(8), /* 4 colorants (8 bits) */
942 gx_color_value_factor(8), /* 5 colorants (8 bits) */
943 gx_color_value_factor(8), /* 6 colorants (8 bits) */
944 gx_color_value_factor(8), /* 7 colorants (8 bits) */
945 gx_color_value_factor(7), /* 8 colorants (7 bits) */
946 gx_color_value_factor(6), /* 9 colorants (6 bits) */
947 gx_color_value_factor(5), /* 10 colorants (5 bits) */
948 gx_color_value_factor(5), /* 11 colorants (5 bits) */
949 gx_color_value_factor(4), /* 12 colorants (4 bits) */
950 gx_color_value_factor(4), /* 13 colorants (4 bits) */
951 gx_color_value_factor(4) /* 14 colorants (4 bits) */
952 };
953 #undef gx_color_value_factor
954
955 /*
956 * Find a given colorant bit map is the list of encoded colorant bit map.
957 *
958 * Note: This routine is called recursively to search sub levels of the
959 * list.
960 *
961 * The parameters are:
962 * num_comp - The number of colorants for the device.
963 * pcomp_list - The current list of encoded colorants.
964 * pnew_comp_bit_map - Pointer to the bit map found to be encoded.
965 * plist_index - Pointer to 'encode bits' (return value)
966 * pcomp_bit_map - Pointer to pointer to the actual bit map found
967 * (return value).
968 * returns true if the bit map is found.
969 */
970 static bool
search_compressed_color_list(int num_comp,compressed_color_list_t * pcomp_list,comp_bit_map_list_t * pnew_comp_bit_map,gx_color_index * plist_index,comp_bit_map_list_t ** pcomp_bit_map)971 search_compressed_color_list(int num_comp, compressed_color_list_t * pcomp_list,
972 comp_bit_map_list_t * pnew_comp_bit_map, gx_color_index * plist_index,
973 comp_bit_map_list_t * * pcomp_bit_map)
974 {
975 int i;
976 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
977 int j, num_bit_map_elem;
978 #endif
979 bool found;
980
981 /*
982 * Search the colorant bit maps for this level of the map.
983 */
984 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
985 num_bit_map_elem = (num_comp + BITS_PER_COMP_BIT_MAP_ELEM - 1) /
986 BITS_PER_COMP_BIT_MAP_ELEM;
987 #endif
988 for (i = NUM_ENCODE_LIST_ITEMS - 1; i >= pcomp_list->first_bit_map; i--) {
989 *pcomp_bit_map = &(pcomp_list->u.comp_data[i]);
990 /*
991 * Do not try to match if one entry uses a 'solid' set of colorants
992 * that is not really solid (i.e. not 100%) and the other is. It is
993 * possible to work if different but it would make some of the logic
994 * more difficult.
995 */
996 if (pnew_comp_bit_map->solid_not_100 !=
997 (*pcomp_bit_map)->solid_not_100)
998 continue;
999 /*
1000 * It is a match if the new colorant bit map is a subset of the one
1001 * in the list and the solid colorants for new map is a super set of
1002 * the solid colorants for the one in the list. I.e. we can use
1003 * the non solid part of the entry for either zero or solid colorants.
1004 */
1005 #if DEVN_ENCODE_COLOR_USING_BIT_MAP_ARRAY
1006 for (j = 0; j < num_bit_map_elem; j++) {
1007 if ((pnew_comp_bit_map->colorants[j] &
1008 (*pcomp_bit_map)->colorants[j]) !=
1009 pnew_comp_bit_map->colorants[j])
1010 break; /* No match if a colorant is missing. */
1011 if ((pnew_comp_bit_map->solid_colorants[j] &
1012 (*pcomp_bit_map)->solid_colorants[j]) !=
1013 (*pcomp_bit_map)->solid_colorants[j])
1014 break; /* No match if extra solid colorants */
1015 }
1016 if (j == num_bit_map_elem) {
1017 #else
1018 if (((pnew_comp_bit_map->colorants &
1019 (*pcomp_bit_map)->colorants) ==
1020 pnew_comp_bit_map->colorants) &&
1021 ((pnew_comp_bit_map->solid_colorants &
1022 (*pcomp_bit_map)->solid_colorants) ==
1023 (*pcomp_bit_map)->solid_colorants)) {
1024 #endif
1025 /*
1026 * To prevent possible loss of accuracy, ignore matches in which the
1027 * packing will use fewer bits in the encoded colorant values than
1028 * is possible for the given number of colorants.
1029 */
1030 if (num_comp_bits[pnew_comp_bit_map->num_comp] >
1031 num_comp_bits[(*pcomp_bit_map)->num_comp])
1032 break;
1033 /*
1034 * We have a match. Put our object number into the top eight
1035 * bits of the encoded gx_color_index and exit.
1036 */
1037 *plist_index = ((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8);
1038 return true;
1039 }
1040 }
1041
1042 /*
1043 * Search the lower levels (i.e. with fewer colorants to see if we
1044 * can find a match.
1045 */
1046 if (pcomp_list->level_num_comp <= pnew_comp_bit_map->num_non_solid_comp)
1047 return false; /* Exit if not enough colorants in the sub levels */
1048
1049 for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
1050 found = search_compressed_color_list(num_comp,
1051 pcomp_list->u.sub_level_ptrs[i],
1052 pnew_comp_bit_map, plist_index, pcomp_bit_map);
1053 if (found) {
1054 /*
1055 * We have a match. Combine the encode index for the sub level
1056 * with our index for this level.
1057 */
1058 *plist_index = (((gx_color_index) i) << (NUM_GX_COLOR_INDEX_BITS - 8))
1059 + (*plist_index >> 8);
1060 return true;
1061 }
1062 }
1063 return false;
1064 }
1065
1066 /*
1067 * Encode a list of colorant values into a gx_color_index_value.
1068 *
1069 * This routine is designed to pack more than eight 8 bit colorant values into
1070 * a 64 bit gx_color_index value. It does this piece of magic by keeping a list
1071 * of which colorant combinations are actualy used (i.e. which colorants are non
1072 * zero). The non zero colorant values and and an 'index' value are packed into
1073 * the output gx_color_index value.
1074 *
1075 * The the different combinations of used colorants are saved into a table
1076 * defined by the comp_bit_map_list_t structure type. This table is kept as
1077 * a list with 256 elements. Each element can be either a pair of bit maps which
1078 * indicates the combination of colorants being used or a pointer to a sub list
1079 * for the next lower level of combinations. There are two bit maps to indicate
1080 * which colorants are specified by the 'index' value. One bit map indicates
1081 * which colorants are used. The second bit map is used to indicate a group of
1082 * colorants with the same value. Normally this second bit map is used to
1083 * indicate which colorants are 'solid' (i.e. 100% and the 'solid_not_100 flag
1084 * is set to false). However if there is a larger group of colorants with the
1085 * same value (and not solid) then the 'solid_not_100' flag is set to true and
1086 * second bit map is used to indicate the colorants in this group. In this
1087 * case, the value of the colorant group is stored in the first colorant entry
1088 * in the gx_color_index.
1089 *
1090 * The number of bits allocated to storing the 'index' and the number of bits
1091 * allocated to storing colorant values depends upon the number of colorant
1092 * being used.
1093 *
1094 * Number of non zero colorant Index bits Bits per colorant
1095 * 0 to 5 24 8
1096 * 6 16 8
1097 * 7 8 8
1098 * 8 8 7
1099 * 9 8 6
1100 * 10 8 5
1101 * 11 8 5
1102 * 12 8 4
1103 * 13 8 4
1104 * 14 8 4
1105 * More than 14 Not encodeable
1106 *
1107 * The 'index' bits can be logically divided into groups of 8 bits. The
1108 * first (upper) group of 8 bits is used to select either one of 256
1109 * combinations of 7 or more colorant or to select a pointer to a sub
1110 * level. If a sub level pointer is specified, then the next group of 8
1111 * index bits is used to select either one of 256 combinations of 6 colorants
1112 * of a sub level pointer. A sub level pointer points to one of 256
1113 * combinations of 5 colorants. If we have fewer than 5 colorants being
1114 * used, we add extra componnents to bring the total up to 5 colorants.
1115 * This is done to prevent having a bunch of 1 or two colorant combinations.
1116 */
1117 gx_color_index
1118 devn_encode_compressed_color(gx_device *pdev, const gx_color_value colors[],
1119 gs_devn_params * pdevn_params)
1120 {
1121 int num_comp = pdev->color_info.num_components;
1122 int comp_num, comp_count = 0, solid_comp_count = 0, bit_pos = 0;
1123 int bit_shift, bit_count, group = 0;
1124 int color_resolution = gx_max_color_value / STD_ENCODED_VALUE;
1125 bool found, added;
1126 comp_bit_map_list_t new_comp_bit_map = {0};
1127 comp_bit_map_list_t * pbit_map;
1128 gx_color_index color = 0, list_index;
1129
1130 /*
1131 * Determine what colorants are being used (non zero). We bit pack
1132 * this info. Note: We treat any colorant value which is less than
1133 * 256 as zero. Color values are 16 bits and we only keep the top
1134 * eight bits. Likewise for solid (100%) colors.
1135 */
1136 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1137 if (colors[comp_num] > color_resolution) {
1138 set_colorant_present(&new_comp_bit_map, colorants, comp_num);
1139 comp_count++;
1140 /* Check if the color is solid */
1141 if (colors[comp_num] > (gx_max_color_value - color_resolution)) {
1142 set_colorant_present(&new_comp_bit_map,
1143 solid_colorants, comp_num);
1144 solid_comp_count++;
1145 }
1146 }
1147 }
1148 new_comp_bit_map.num_comp = comp_count;
1149 new_comp_bit_map.num_non_solid_comp = comp_count - solid_comp_count;
1150 /*
1151 * We may get less loss of accuracy if instead of checking for zero and
1152 * 100% colorant values, we look for a group of colorants with the same
1153 * colorant value.
1154 */
1155 if (new_comp_bit_map.num_non_solid_comp > TOP_ENCODED_LEVEL &&
1156 solid_comp_count < (comp_count / 2)) {
1157 short group_size[(gx_max_color_value / STD_ENCODED_VALUE) + 1] = {0};
1158 int value, largest_group_size = 0;
1159
1160 /* Scan to determine the size of the largest group */
1161 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1162 value = colors[comp_num] / STD_ENCODED_VALUE;
1163 group_size[value]++;
1164 if (group_size[value] > largest_group_size) {
1165 largest_group_size = group_size[value];
1166 group = value;
1167 }
1168 }
1169 /*
1170 * If using this group instead of the solid colorants will improve
1171 * our situation, then switch to using this group.
1172 */
1173 if (largest_group_size > (solid_comp_count + 1) &&
1174 (comp_count - largest_group_size) < MAX_ENCODED_COMPONENTS) {
1175 /* Setup the colorant description to use this group */
1176 memset(&(new_comp_bit_map.solid_colorants), 0,
1177 size_of(comp_bit_map_t));
1178 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1179 value = colors[comp_num] / STD_ENCODED_VALUE;
1180 if (value == group) {
1181 set_colorant_present(&new_comp_bit_map,
1182 solid_colorants, comp_num);
1183 }
1184 }
1185 new_comp_bit_map.solid_not_100 = true;
1186 new_comp_bit_map.num_non_solid_comp =
1187 comp_count - largest_group_size + 1;
1188 }
1189 }
1190
1191 /* Our encoding scheme cannot handle too many non solid colorants. */
1192 if (new_comp_bit_map.num_non_solid_comp > MAX_ENCODED_COMPONENTS)
1193 return NON_ENCODEABLE_COLOR;
1194
1195 /*
1196 * We keep a list of which colorant combinations we have used. Make
1197 * sure that this list has been initialized.
1198 */
1199 if (pdevn_params->compressed_color_list == NULL) {
1200 pdevn_params->compressed_color_list =
1201 init_compressed_color_list(pdev->memory);
1202 if (pdevn_params->compressed_color_list == NULL)
1203 return NON_ENCODEABLE_COLOR; /* Unable to initialize list */
1204 }
1205
1206 /*
1207 * Check our list of colorant combinations to see if we already have a
1208 * combination that is useable. I.e. a combination that includes all of our
1209 * non zero colorants.
1210 */
1211 found = search_compressed_color_list(num_comp,
1212 pdevn_params->compressed_color_list,
1213 &new_comp_bit_map, &list_index, &pbit_map);
1214
1215 /*
1216 * If our new colorant list was not found then add it to our encode color
1217 * list.
1218 */
1219 if (!found) {
1220 added = add_compressed_color_list(pdev->memory, &new_comp_bit_map,
1221 pdevn_params->compressed_color_list, &list_index);
1222 if (!added)
1223 return NON_ENCODEABLE_COLOR;
1224 pbit_map = &new_comp_bit_map;
1225 }
1226
1227 /*
1228 * Form the encoded color gx_color_index value. This is a combination
1229 * of the bits that encode which colorants are used (non zero) and the
1230 * colorant values.
1231 */
1232 bit_count = num_comp_bits[pbit_map->num_non_solid_comp];
1233 bit_shift = sizeof(gx_color_value) * 8 - bit_count;
1234 if (pbit_map->solid_not_100) {
1235 color = group >> (8 - bit_count);
1236 bit_pos += bit_count;
1237 }
1238 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1239 if (colorant_present(pbit_map, colorants, comp_num) &&
1240 !colorant_present(pbit_map, solid_colorants, comp_num)) {
1241 color |=
1242 ((gx_color_index)(colors[comp_num] >> bit_shift)) << bit_pos;
1243 bit_pos += bit_count;
1244 }
1245 }
1246 color |= list_index;
1247 /*
1248 * Make sure that our color index does not match one of the reserved
1249 * values.
1250 */
1251 if (color == NON_ENCODEABLE_COLOR)
1252 color -= 1;
1253 else if (color == gx_no_color_index)
1254 color -= 2;
1255 return color;
1256 }
1257
1258 /*
1259 * Find the bit map for given bit map index.
1260 */
1261 comp_bit_map_list_t *
1262 find_bit_map(gx_color_index index, compressed_color_list_t * pcomp_list)
1263 {
1264 int loc = (int)(index >> (NUM_GX_COLOR_INDEX_BITS - 8));
1265
1266 /*
1267 * Search for the level which contains the bit map. If our index
1268 * for this level is less than the number of sub level pointers for
1269 * this level then we need to go down another level.
1270 */
1271 while (loc < pcomp_list->num_sub_level_ptrs) {
1272 pcomp_list = pcomp_list->u.sub_level_ptrs[loc];
1273 index <<= 8;
1274 loc = (int)(index >> (NUM_GX_COLOR_INDEX_BITS - 8));
1275 }
1276 return &(pcomp_list->u.comp_data[loc]);
1277 }
1278
1279 /*
1280 * Decode a gx_color_index value back to a list of colorant values. This
1281 * routine assumes that the gx_color_index value is 'encoded' as described
1282 * for devn_encode_compressed_color.
1283 *
1284 * See comments preceding devn_encode_compressed_color for more information
1285 * about the way that we are compressing colorant values in a gx_color_index.
1286 */
1287 int
1288 devn_decode_compressed_color(gx_device * dev, gx_color_index color,
1289 gx_color_value * out, gs_devn_params * pdevn_params)
1290 {
1291 int comp_num = 0;
1292 int factor, bit_count, bit_mask;
1293 int ncomp = dev->color_info.num_components;
1294 comp_bit_map_list_t * pbitmap;
1295 gx_color_value solid_color = gx_max_color_value;
1296
1297 /*
1298 * Set all colorants to max if we get a non encodeable color. We set the
1299 * values to a max since this will represent another non encodeable color.
1300 * Thus if we have a non decodable color, it will continue to propogate.
1301 */
1302 if (color == NON_ENCODEABLE_COLOR) {
1303 for (; comp_num < ncomp; comp_num++)
1304 out[comp_num] = gx_max_color_value;
1305 return 0;
1306 }
1307 pbitmap = find_bit_map(color, pdevn_params->compressed_color_list);
1308 bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
1309 bit_mask = (1 << bit_count) - 1;
1310 factor = comp_bit_factor[pbitmap->num_non_solid_comp];
1311 if (pbitmap->solid_not_100) {
1312 solid_color = (factor * ((int)color & bit_mask)) >> 8;
1313 color >>= bit_count;
1314 }
1315 for (; comp_num < ncomp; comp_num++) {
1316 if (colorant_present(pbitmap, colorants, comp_num)) {
1317 if (colorant_present(pbitmap, solid_colorants, comp_num))
1318 out[comp_num] = solid_color;
1319 else {
1320 out[comp_num] = (factor * ((int)color & bit_mask)) >> 8;
1321 color >>= bit_count;
1322 }
1323 }
1324 else
1325 out[comp_num] = 0;
1326 }
1327 return 0;
1328 }
1329
1330
1331 /*
1332 * Unpack a row of 'compressed color' values. These values are encoded as
1333 * described for the devn_encode_compressed_color routine.
1334 *
1335 * The routine takes a raster line of data and expands each pixel into a buffer
1336 * of 8 bit values for each colorant.
1337 *
1338 * See comments preceding devn_encode_compressed_color for more information
1339 * about the way that we are encoding colorant values in a gx_color_index.
1340 *
1341 * Note: For simplicity of coding the calling routines, this routine will also
1342 * handle 'uncompressed' bit maps.
1343 */
1344 int
1345 devn_unpack_row(gx_device * dev, int num_comp, gs_devn_params * pdevn_params,
1346 int width, byte * in, byte * out)
1347 {
1348 int i, comp_num, pixel_num;
1349
1350 if (pdevn_params->compressed_color_list == NULL) {
1351 int bytes_pp = dev->color_info.depth >> 3;
1352
1353 /*
1354 * For 'uncompressed' data, the number of bytes per pixel in the input
1355 * raster line is defined by the device depth. This may be more than
1356 * the number of actual device components.
1357 */
1358 for (pixel_num = 0; pixel_num < width; pixel_num++) {
1359 for (i = 0; i < num_comp; i++)
1360 *out++ = *in++;
1361 in += bytes_pp - num_comp;
1362 }
1363 return 0;
1364 }
1365 else {
1366 int non_encodeable_count = 0;
1367 int factor, bit_count, bit_mask;
1368 comp_bit_map_list_t * pbitmap;
1369 gx_color_index color;
1370 gx_color_value solid_color = gx_max_color_value;
1371
1372 for (pixel_num = 0; pixel_num < width; pixel_num++) {
1373 /*
1374 * Get the encoded color value.
1375 */
1376 color = ((gx_color_index)(*in++)) << (NUM_GX_COLOR_INDEX_BITS - 8);
1377 for (i = NUM_GX_COLOR_INDEX_BITS - 16; i >= 0; i -= 8)
1378 color |= ((gx_color_index)(*in++)) << i;
1379 /*
1380 * Set all colorants to zero if we get a non encodeable color.
1381 */
1382 if (color == NON_ENCODEABLE_COLOR) {
1383 for (comp_num = 0; comp_num < num_comp; comp_num++)
1384 *out++ = 0;
1385 non_encodeable_count++;
1386 }
1387 else {
1388 pbitmap = find_bit_map(color,
1389 pdevn_params->compressed_color_list);
1390 bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
1391 bit_mask = (1 << bit_count) - 1;
1392 factor = comp_bit_factor[pbitmap->num_non_solid_comp];
1393 if (pbitmap->solid_not_100) {
1394 solid_color = (factor * ((int)color & bit_mask)) >> 8;
1395 color >>= bit_count;
1396 }
1397 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1398 if (colorant_present(pbitmap, colorants, comp_num)) {
1399 if (colorant_present(pbitmap,
1400 solid_colorants, comp_num))
1401 *out++ = solid_color >> 8;
1402 else {
1403 *out++ = (factor * ((int)color & bit_mask)) >> 16;
1404 color >>= bit_count;
1405 }
1406 }
1407 else
1408 *out++ = 0;
1409 }
1410 }
1411 }
1412 return non_encodeable_count;
1413 }
1414 }
1415
1416
1417 /* ***************** The spotcmyk and devicen devices ***************** */
1418
1419 /* Define the device parameters. */
1420 #ifndef X_DPI
1421 # define X_DPI 72
1422 #endif
1423 #ifndef Y_DPI
1424 # define Y_DPI 72
1425 #endif
1426
1427 /* The device descriptor */
1428 static dev_proc_open_device(spotcmyk_prn_open);
1429 static dev_proc_get_params(spotcmyk_get_params);
1430 static dev_proc_put_params(spotcmyk_put_params);
1431 static dev_proc_print_page(spotcmyk_print_page);
1432 static dev_proc_get_color_mapping_procs(get_spotcmyk_color_mapping_procs);
1433 static dev_proc_get_color_mapping_procs(get_devicen_color_mapping_procs);
1434 static dev_proc_get_color_comp_index(spotcmyk_get_color_comp_index);
1435 static dev_proc_encode_color(spotcmyk_encode_color);
1436 static dev_proc_decode_color(spotcmyk_decode_color);
1437
1438 /*
1439 * A structure definition for a DeviceN type device
1440 */
1441 typedef struct spotcmyk_device_s {
1442 gx_device_common;
1443 gx_prn_device_common;
1444 gs_devn_params devn_params;
1445 } spotcmyk_device;
1446
1447 /* GC procedures */
1448
1449 static
1450 ENUM_PTRS_WITH(spotcmyk_device_enum_ptrs, spotcmyk_device *pdev)
1451 {
1452 if (index < pdev->devn_params.separations.num_separations)
1453 ENUM_RETURN(pdev->devn_params.separations.names[index].data);
1454 ENUM_PREFIX(st_device_printer,
1455 pdev->devn_params.separations.num_separations);
1456 }
1457
1458 ENUM_PTRS_END
1459 static RELOC_PTRS_WITH(spotcmyk_device_reloc_ptrs, spotcmyk_device *pdev)
1460 {
1461 RELOC_PREFIX(st_device_printer);
1462 {
1463 int i;
1464
1465 for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
1466 RELOC_PTR(spotcmyk_device, devn_params.separations.names[i].data);
1467 }
1468 }
1469 }
1470 RELOC_PTRS_END
1471
1472 /* Even though spotcmyk_device_finalize is the same as gx_device_finalize, */
1473 /* we need to implement it separately because st_composite_final */
1474 /* declares all 3 procedures as private. */
1475 static void
1476 spotcmyk_device_finalize(void *vpdev)
1477 {
1478 gx_device_finalize(vpdev);
1479 }
1480
1481 gs_private_st_composite_final(st_spotcmyk_device, spotcmyk_device,
1482 "spotcmyk_device", spotcmyk_device_enum_ptrs, spotcmyk_device_reloc_ptrs,
1483 spotcmyk_device_finalize);
1484
1485 /*
1486 * Macro definition for DeviceN procedures
1487 */
1488 #define device_procs(get_color_mapping_procs)\
1489 { spotcmyk_prn_open,\
1490 gx_default_get_initial_matrix,\
1491 NULL, /* sync_output */\
1492 gdev_prn_output_page, /* output_page */\
1493 gdev_prn_close, /* close */\
1494 NULL, /* map_rgb_color - not used */\
1495 NULL, /* map_color_rgb - not used */\
1496 NULL, /* fill_rectangle */\
1497 NULL, /* tile_rectangle */\
1498 NULL, /* copy_mono */\
1499 NULL, /* copy_color */\
1500 NULL, /* draw_line */\
1501 NULL, /* get_bits */\
1502 spotcmyk_get_params, /* get_params */\
1503 spotcmyk_put_params, /* put_params */\
1504 NULL, /* map_cmyk_color - not used */\
1505 NULL, /* get_xfont_procs */\
1506 NULL, /* get_xfont_device */\
1507 NULL, /* map_rgb_alpha_color */\
1508 gx_page_device_get_page_device, /* get_page_device */\
1509 NULL, /* get_alpha_bits */\
1510 NULL, /* copy_alpha */\
1511 NULL, /* get_band */\
1512 NULL, /* copy_rop */\
1513 NULL, /* fill_path */\
1514 NULL, /* stroke_path */\
1515 NULL, /* fill_mask */\
1516 NULL, /* fill_trapezoid */\
1517 NULL, /* fill_parallelogram */\
1518 NULL, /* fill_triangle */\
1519 NULL, /* draw_thin_line */\
1520 NULL, /* begin_image */\
1521 NULL, /* image_data */\
1522 NULL, /* end_image */\
1523 NULL, /* strip_tile_rectangle */\
1524 NULL, /* strip_copy_rop */\
1525 NULL, /* get_clipping_box */\
1526 NULL, /* begin_typed_image */\
1527 NULL, /* get_bits_rectangle */\
1528 NULL, /* map_color_rgb_alpha */\
1529 NULL, /* create_compositor */\
1530 NULL, /* get_hardware_params */\
1531 NULL, /* text_begin */\
1532 NULL, /* finish_copydevice */\
1533 NULL, /* begin_transparency_group */\
1534 NULL, /* end_transparency_group */\
1535 NULL, /* begin_transparency_mask */\
1536 NULL, /* end_transparency_mask */\
1537 NULL, /* discard_transparency_layer */\
1538 get_color_mapping_procs, /* get_color_mapping_procs */\
1539 spotcmyk_get_color_comp_index, /* get_color_comp_index */\
1540 spotcmyk_encode_color, /* encode_color */\
1541 spotcmyk_decode_color, /* decode_color */\
1542 NULL, /* pattern_manage */\
1543 NULL /* fill_rectangle_hl_color */\
1544 }
1545
1546 fixed_colorant_name DeviceCMYKComponents[] = {
1547 "Cyan",
1548 "Magenta",
1549 "Yellow",
1550 "Black",
1551 0 /* List terminator */
1552 };
1553
1554
1555 #define spotcmyk_device_body(procs, dname, ncomp, pol, depth, mg, mc, cn)\
1556 std_device_full_body_type_extended(spotcmyk_device, &procs, dname,\
1557 &st_spotcmyk_device,\
1558 (int)((long)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10),\
1559 (int)((long)(DEFAULT_HEIGHT_10THS) * (Y_DPI) / 10),\
1560 X_DPI, Y_DPI,\
1561 GX_DEVICE_COLOR_MAX_COMPONENTS, /* MaxComponents */\
1562 ncomp, /* NumComp */\
1563 pol, /* Polarity */\
1564 depth, 0, /* Depth, GrayIndex */\
1565 mg, mc, /* MaxGray, MaxColor */\
1566 mg + 1, mc + 1, /* DitherGray, DitherColor */\
1567 GX_CINFO_SEP_LIN, /* Linear & Separable */\
1568 cn, /* Process color model name */\
1569 0, 0, /* offsets */\
1570 0, 0, 0, 0 /* margins */\
1571 ),\
1572 prn_device_body_rest_(spotcmyk_print_page)
1573
1574 /*
1575 * Example device with CMYK and spot color support
1576 */
1577 static const gx_device_procs spot_cmyk_procs = device_procs(get_spotcmyk_color_mapping_procs);
1578
1579 const spotcmyk_device gs_spotcmyk_device =
1580 {
1581 spotcmyk_device_body(spot_cmyk_procs, "spotcmyk", 4, GX_CINFO_POLARITY_SUBTRACTIVE, 4, 1, 1, "DeviceCMYK"),
1582 /* DeviceN device specific parameters */
1583 { 1, /* Bits per color - must match ncomp, depth, etc. above */
1584 DeviceCMYKComponents, /* Names of color model colorants */
1585 4, /* Number colorants for CMYK */
1586 0, /* MaxSeparations has not been specified */
1587 -1, /* PageSpotColors has not been specified */
1588 {0}, /* SeparationNames */
1589 0, /* SeparationOrder names */
1590 {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
1591 }
1592 };
1593
1594 /*
1595 * Example DeviceN color device
1596 */
1597 static const gx_device_procs devicen_procs = device_procs(get_devicen_color_mapping_procs);
1598
1599 const spotcmyk_device gs_devicen_device =
1600 {
1601 spotcmyk_device_body(devicen_procs, "devicen", 4, GX_CINFO_POLARITY_SUBTRACTIVE, 32, 255, 255, "DeviceCMYK"),
1602 /* DeviceN device specific parameters */
1603 { 8, /* Bits per color - must match ncomp, depth, etc. above */
1604 NULL, /* No names for standard DeviceN color model */
1605 0, /* No standard colorants for DeviceN */
1606 0, /* MaxSeparations has not been specified */
1607 -1, /* PageSpotColors has not been specified */
1608 {0}, /* SeparationNames */
1609 0, /* SeparationOrder names */
1610 {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
1611 }
1612 };
1613
1614 /* Open the psd devices */
1615 int
1616 spotcmyk_prn_open(gx_device * pdev)
1617 {
1618 int code = gdev_prn_open(pdev);
1619
1620 set_linear_color_bits_mask_shift(pdev);
1621 pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1622 return code;
1623 }
1624
1625 /* Color mapping routines for the spotcmyk device */
1626
1627 static void
1628 gray_cs_to_spotcmyk_cm(gx_device * dev, frac gray, frac out[])
1629 {
1630 int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1631
1632 gray_cs_to_devn_cm(dev, map, gray, out);
1633 }
1634
1635 static void
1636 rgb_cs_to_spotcmyk_cm(gx_device * dev, const gs_imager_state *pis,
1637 frac r, frac g, frac b, frac out[])
1638 {
1639 int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1640
1641 rgb_cs_to_devn_cm(dev, map, pis, r, g, b, out);
1642 }
1643
1644 static void
1645 cmyk_cs_to_spotcmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
1646 {
1647 int * map = ((spotcmyk_device *) dev)->devn_params.separation_order_map;
1648
1649 cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
1650 }
1651
1652 static const gx_cm_color_map_procs spotCMYK_procs = {
1653 gray_cs_to_spotcmyk_cm, rgb_cs_to_spotcmyk_cm, cmyk_cs_to_spotcmyk_cm
1654 };
1655
1656 static const gx_cm_color_map_procs *
1657 get_spotcmyk_color_mapping_procs(const gx_device * dev)
1658 {
1659 return &spotCMYK_procs;
1660 }
1661
1662 /* Also use the spotcmyk procs for the devicen device. */
1663
1664 static const gx_cm_color_map_procs *
1665 get_devicen_color_mapping_procs(const gx_device * dev)
1666 {
1667 return &spotCMYK_procs;
1668 }
1669
1670
1671 /*
1672 * Encode a list of colorant values into a gx_color_index_value.
1673 */
1674 static gx_color_index
1675 spotcmyk_encode_color(gx_device *dev, const gx_color_value colors[])
1676 {
1677 int bpc = ((spotcmyk_device *)dev)->devn_params.bitspercomponent;
1678 int drop = sizeof(gx_color_value) * 8 - bpc;
1679 gx_color_index color = 0;
1680 int i = 0;
1681 int ncomp = dev->color_info.num_components;
1682
1683 for (; i<ncomp; i++) {
1684 color <<= bpc;
1685 color |= (colors[i] >> drop);
1686 }
1687 return (color == gx_no_color_index ? color ^ 1 : color);
1688 }
1689
1690 /*
1691 * Decode a gx_color_index value back to a list of colorant values.
1692 */
1693 static int
1694 spotcmyk_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
1695 {
1696 int bpc = ((spotcmyk_device *)dev)->devn_params.bitspercomponent;
1697 int drop = sizeof(gx_color_value) * 8 - bpc;
1698 int mask = (1 << bpc) - 1;
1699 int i = 0;
1700 int ncomp = dev->color_info.num_components;
1701
1702 for (; i<ncomp; i++) {
1703 out[ncomp - i - 1] = (gx_color_value)((color & mask) << drop);
1704 color >>= bpc;
1705 }
1706 return 0;
1707 }
1708
1709 /* Get parameters. */
1710 static int
1711 spotcmyk_get_params(gx_device * pdev, gs_param_list * plist)
1712 {
1713 int code = gdev_prn_get_params(pdev, plist);
1714
1715 if (code < 0)
1716 return code;
1717 return devn_get_params(pdev, plist,
1718 &(((spotcmyk_device *)pdev)->devn_params), NULL);
1719 }
1720
1721 /* Set parameters. */
1722 static int
1723 spotcmyk_put_params(gx_device * pdev, gs_param_list * plist)
1724 {
1725 return devn_printer_put_params(pdev, plist,
1726 &(((spotcmyk_device *)pdev)->devn_params), NULL);
1727 }
1728
1729 /*
1730 * This routine will check to see if the color component name match those
1731 * that are available amoung the current device's color components.
1732 *
1733 * Parameters:
1734 * dev - pointer to device data structure.
1735 * pname - pointer to name (zero termination not required)
1736 * nlength - length of the name
1737 *
1738 * This routine returns a positive value (0 to n) which is the device colorant
1739 * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
1740 * the colorant is not being used due to a SeparationOrder device parameter.
1741 * It returns a negative value if not found.
1742 */
1743 static int
1744 spotcmyk_get_color_comp_index(gx_device * dev, const char * pname,
1745 int name_size, int component_type)
1746 {
1747 return devn_get_color_comp_index(dev,
1748 &(((spotcmyk_device *)dev)->devn_params), NULL,
1749 pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS);
1750 }
1751
1752
1753 /*
1754 * This routine will extract a specified set of bits from a buffer and pack
1755 * them into a given buffer.
1756 *
1757 * Parameters:
1758 * source - The source of the data
1759 * dest - The destination for the data
1760 * depth - The size of the bits per pixel - must be a multiple of 8
1761 * first_bit - The location of the first data bit (LSB).
1762 * bit_width - The number of bits to be extracted.
1763 * npixel - The number of pixels.
1764 *
1765 * Returns:
1766 * Length of the output line (in bytes)
1767 * Data in dest.
1768 */
1769 int
1770 repack_data(byte * source, byte * dest, int depth, int first_bit,
1771 int bit_width, int npixel)
1772 {
1773 int in_nbyte = depth >> 3; /* Number of bytes per input pixel */
1774 int out_nbyte = bit_width >> 3; /* Number of bytes per output pixel */
1775 gx_color_index mask = 1;
1776 gx_color_index data;
1777 int i, j, length = 0;
1778 byte temp;
1779 byte * out = dest;
1780 int in_bit_start = 8 - depth;
1781 int out_bit_start = 8 - bit_width;
1782 int in_byte_loc = in_bit_start, out_byte_loc = out_bit_start;
1783
1784 mask = (mask << bit_width) - 1;
1785 for (i=0; i<npixel; i++) {
1786 /* Get the pixel data */
1787 if (!in_nbyte) { /* Multiple pixels per byte */
1788 data = *source;
1789 data >>= in_byte_loc;
1790 in_byte_loc -= depth;
1791 if (in_byte_loc < 0) { /* If finished with byte */
1792 in_byte_loc = in_bit_start;
1793 source++;
1794 }
1795 }
1796 else { /* One or more bytes per pixel */
1797 data = *source++;
1798 for (j=1; j<in_nbyte; j++)
1799 data = (data << 8) + *source++;
1800 }
1801 data >>= first_bit;
1802 data &= mask;
1803
1804 /* Put the output data */
1805 if (!out_nbyte) { /* Multiple pixels per byte */
1806 temp = (byte)(*out & ~(mask << out_byte_loc));
1807 *out = (byte)(temp | (data << out_byte_loc));
1808 out_byte_loc -= bit_width;
1809 if (out_byte_loc < 0) { /* If finished with byte */
1810 out_byte_loc = out_bit_start;
1811 out++;
1812 }
1813 }
1814 else { /* One or more bytes per pixel */
1815 *out++ = (byte)(data >> ((out_nbyte - 1) * 8));
1816 for (j=1; j<out_nbyte; j++) {
1817 *out++ = (byte)(data >> ((out_nbyte - 1 - j) * 8));
1818 }
1819 }
1820 }
1821 /* Return the number of bytes in the destination buffer. */
1822 if (out_byte_loc != out_bit_start) { /* If partially filled last byte */
1823 *out = *out & ((~0) << out_byte_loc); /* Mask unused part of last byte */
1824 out++;
1825 }
1826 length = out - dest;
1827 return length;
1828 }
1829
1830 static int devn_write_pcx_file(gx_device_printer * pdev, char * filename, int ncomp,
1831 int bpc, int pcmlinelength);
1832 /*
1833 * This is an example print page routine for a DeviceN device. This routine
1834 * will handle a DeviceN, a CMYK with spot colors, or an RGB process color model.
1835 *
1836 * This routine creates several output files. If the process color model is
1837 * RGB or CMYK then a bit image file is created which contains the data for the
1838 * process color model data. This data is put into the given file stream.
1839 * I.e. into the output file specified by the user. This file is not created
1840 * for the DeviceN process color model. A separate bit image file is created
1841 * is created for the data for each of the given spot colors. The names for
1842 * these files are created by taking the given output file name and appending
1843 * "sn" (where n is the spot color number 0 to ...) to the output file name.
1844 * The results are unknown if the output file is stdout etc.
1845 *
1846 * After the bit image files are created, then a set of PCX format files are
1847 * created from the bit image files. This files have a ".pcx" appended to the
1848 * end of the files. Thus a CMYK process color model with two spot colors
1849 * would end up with a total of six files being created. (xxx, xxxs0, xxxs1,
1850 * xxx.pcx, xxxs0.pcx, and xxxs1.pcx).
1851 *
1852 * I do not assume that any users will actually want to create all of these
1853 * different files. However I wanted to show an example of how each of the
1854 * spot * colorants could be unpacked from the process color model colorants.
1855 * The bit images files are an easy way to show this without the complication
1856 * of trying to put the data into a specific format. However I do not have a
1857 * tool which will display the bit image data directly so I needed to convert
1858 * it to a form which I can view. Thus the PCX format files are being created.
1859 * Note: The PCX implementation is not complete. There are many (most)
1860 * combinations of bits per pixel and number of colorants that are not supported.
1861 */
1862 static int
1863 spotcmyk_print_page(gx_device_printer * pdev, FILE * prn_stream)
1864 {
1865 int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
1866 byte *in = gs_alloc_bytes(pdev->memory, line_size, "spotcmyk_print_page(in)");
1867 byte *buf = gs_alloc_bytes(pdev->memory, line_size + 3, "spotcmyk_print_page(buf)");
1868 const spotcmyk_device * pdevn = (spotcmyk_device *) pdev;
1869 int npcmcolors = pdevn->devn_params.num_std_colorant_names;
1870 int ncomp = pdevn->color_info.num_components;
1871 int depth = pdevn->color_info.depth;
1872 int nspot = pdevn->devn_params.separations.num_separations;
1873 int bpc = pdevn->devn_params.bitspercomponent;
1874 int lnum = 0, bottom = pdev->height;
1875 int width = pdev->width;
1876 FILE * spot_file[GX_DEVICE_COLOR_MAX_COMPONENTS] = {0};
1877 int i, code = 0;
1878 int first_bit;
1879 int pcmlinelength = 0; /* Initialize against indeterminizm in case of pdev->height == 0. */
1880 int linelength[GX_DEVICE_COLOR_MAX_COMPONENTS];
1881 byte *data;
1882 char spotname[gp_file_name_sizeof];
1883
1884 if (in == NULL || buf == NULL) {
1885 code = gs_error_VMerror;
1886 goto prn_done;
1887 }
1888 /*
1889 * Check if the SeparationOrder list has changed the order of the process
1890 * color model colorants. If so then we will treat all colorants as if they
1891 * are spot colors.
1892 */
1893 for (i = 0; i < npcmcolors; i++)
1894 if (pdevn->devn_params.separation_order_map[i] != i)
1895 break;
1896 if (i < npcmcolors || ncomp < npcmcolors) {
1897 nspot = ncomp;
1898 npcmcolors = 0;
1899 }
1900
1901 /* Open the output files for the spot colors */
1902 for(i = 0; i < nspot; i++) {
1903 sprintf(spotname, "%ss%d", pdevn->fname, i);
1904 spot_file[i] = fopen(spotname, "wb");
1905 if (spot_file[i] == NULL) {
1906 code = gs_error_VMerror;
1907 goto prn_done;
1908 }
1909 }
1910
1911
1912 /* Now create the output bit image files */
1913 for (; lnum < bottom; ++lnum) {
1914 gdev_prn_get_bits(pdev, lnum, in, &data);
1915 /* Now put the pcm data into the output file */
1916 if (npcmcolors) {
1917 first_bit = bpc * (ncomp - npcmcolors);
1918 pcmlinelength = repack_data(data, buf, depth, first_bit, bpc * npcmcolors, width);
1919 fwrite(buf, 1, pcmlinelength, prn_stream);
1920 }
1921 /* Put spot color data into the output files */
1922 for (i = 0; i < nspot; i++) {
1923 first_bit = bpc * (nspot - 1 - i);
1924 linelength[i] = repack_data(data, buf, depth, first_bit, bpc, width);
1925 fwrite(buf, 1, linelength[i], spot_file[i]);
1926 }
1927 }
1928
1929 /* Close the bit image files */
1930 for(i = 0; i < nspot; i++) {
1931 fclose(spot_file[i]);
1932 spot_file[i] = NULL;
1933 }
1934
1935 /* Now convert the bit image files into PCX files */
1936 if (npcmcolors) {
1937 code = devn_write_pcx_file(pdev, (char *) &pdevn->fname,
1938 npcmcolors, bpc, pcmlinelength);
1939 if (code < 0)
1940 return code;
1941 }
1942 for(i = 0; i < nspot; i++) {
1943 sprintf(spotname, "%ss%d", pdevn->fname, i);
1944 code = devn_write_pcx_file(pdev, spotname, 1, bpc, linelength[i]);
1945 if (code < 0)
1946 return code;
1947 }
1948
1949
1950 /* Clean up and exit */
1951 prn_done:
1952 for(i = 0; i < nspot; i++) {
1953 if (spot_file[i] != NULL)
1954 fclose(spot_file[i]);
1955 }
1956 if (in != NULL)
1957 gs_free_object(pdev->memory, in, "spotcmyk_print_page(in)");
1958 if (buf != NULL)
1959 gs_free_object(pdev->memory, buf, "spotcmyk_print_page(buf)");
1960 return code;
1961 }
1962
1963 /*
1964 * We are using the PCX output format. This is done for simplicity.
1965 * Much of the following code was copied from gdevpcx.c.
1966 */
1967
1968 /* ------ Private definitions ------ */
1969
1970 /* All two-byte quantities are stored LSB-first! */
1971 #if arch_is_big_endian
1972 # define assign_ushort(a,v) a = ((v) >> 8) + ((v) << 8)
1973 #else
1974 # define assign_ushort(a,v) a = (v)
1975 #endif
1976
1977 typedef struct pcx_header_s {
1978 byte manuf; /* always 0x0a */
1979 byte version;
1980 #define version_2_5 0
1981 #define version_2_8_with_palette 2
1982 #define version_2_8_without_palette 3
1983 #define version_3_0 /* with palette */ 5
1984 byte encoding; /* 1=RLE */
1985 byte bpp; /* bits per pixel per plane */
1986 ushort x1; /* X of upper left corner */
1987 ushort y1; /* Y of upper left corner */
1988 ushort x2; /* x1 + width - 1 */
1989 ushort y2; /* y1 + height - 1 */
1990 ushort hres; /* horz. resolution (dots per inch) */
1991 ushort vres; /* vert. resolution (dots per inch) */
1992 byte palette[16 * 3]; /* color palette */
1993 byte reserved;
1994 byte nplanes; /* number of color planes */
1995 ushort bpl; /* number of bytes per line (uncompressed) */
1996 ushort palinfo;
1997 #define palinfo_color 1
1998 #define palinfo_gray 2
1999 byte xtra[58]; /* fill out header to 128 bytes */
2000 } pcx_header;
2001
2002 /* Define the prototype header. */
2003 static const pcx_header pcx_header_prototype =
2004 {
2005 10, /* manuf */
2006 0, /* version (variable) */
2007 1, /* encoding */
2008 0, /* bpp (variable) */
2009 00, 00, /* x1, y1 */
2010 00, 00, /* x2, y2 (variable) */
2011 00, 00, /* hres, vres (variable) */
2012 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* palette (variable) */
2013 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2014 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2015 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
2016 0, /* reserved */
2017 0, /* nplanes (variable) */
2018 00, /* bpl (variable) */
2019 00, /* palinfo (variable) */
2020 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* xtra */
2021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2022 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2023 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2024 };
2025
2026
2027 /* Forward declarations */
2028 static void devn_pcx_write_rle(const byte *, const byte *, int, FILE *);
2029 static int devn_pcx_write_page(gx_device_printer * pdev, FILE * infile,
2030 int linesize, FILE * outfile, pcx_header * phdr, bool planar, int depth);
2031
2032 static const byte pcx_cmyk_palette[16 * 3] =
2033 {
2034 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00,
2035 0xff, 0x00, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0x00, 0x00,
2036 0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x00,
2037 0x00, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f,
2038 };
2039
2040 static const byte pcx_ega_palette[16 * 3] =
2041 {
2042 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x00, 0xaa, 0xaa,
2043 0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0xaa, 0xaa, 0xaa,
2044 0x55, 0x55, 0x55, 0x55, 0x55, 0xff, 0x55, 0xff, 0x55, 0x55, 0xff, 0xff,
2045 0xff, 0x55, 0x55, 0xff, 0x55, 0xff, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff
2046 };
2047
2048
2049 /*
2050 * This routine will set up the revision and palatte for the output
2051 * file.
2052 *
2053 * Please note that this routine does not currently handle all possible
2054 * combinations of bits and planes.
2055 *
2056 * Input parameters:
2057 * pdev - Pointer to device data structure
2058 * file - output file
2059 * header - The header structure to hold the data.
2060 * bits_per_plane - The number of bits per plane.
2061 * num_planes - The number of planes.
2062 */
2063 static bool
2064 devn_setup_pcx_header(gx_device_printer * pdev, pcx_header * phdr, int num_planes, int bits_per_plane)
2065 {
2066 bool planar = true; /* Invalid cases could cause an indeterminizm. */
2067
2068 *phdr = pcx_header_prototype;
2069 phdr->bpp = bits_per_plane;
2070 phdr->nplanes = num_planes;
2071
2072 switch (num_planes) {
2073 case 1:
2074 switch (bits_per_plane) {
2075 case 1:
2076 phdr->version = version_2_8_with_palette;
2077 assign_ushort(phdr->palinfo, palinfo_gray);
2078 memcpy((byte *) phdr->palette, "\000\000\000\377\377\377", 6);
2079 planar = false;
2080 break;
2081 case 2: /* Not defined */
2082 break;
2083 case 4:
2084 phdr->version = version_2_8_with_palette;
2085 memcpy((byte *) phdr->palette, pcx_ega_palette, sizeof(pcx_ega_palette));
2086 planar = true;
2087 break;
2088 case 5: /* Not defined */
2089 break;
2090 case 8:
2091 phdr->version = version_3_0;
2092 assign_ushort(phdr->palinfo, palinfo_gray);
2093 planar = false;
2094 break;
2095 case 16: /* Not defined */
2096 break;
2097 }
2098 break;
2099 case 2:
2100 switch (bits_per_plane) {
2101 case 1: /* Not defined */
2102 break;
2103 case 2: /* Not defined */
2104 break;
2105 case 4: /* Not defined */
2106 break;
2107 case 5: /* Not defined */
2108 break;
2109 case 8: /* Not defined */
2110 break;
2111 case 16: /* Not defined */
2112 break;
2113 }
2114 break;
2115 case 3:
2116 switch (bits_per_plane) {
2117 case 1: /* Not defined */
2118 break;
2119 case 2: /* Not defined */
2120 break;
2121 case 4: /* Not defined */
2122 break;
2123 case 5: /* Not defined */
2124 break;
2125 case 8:
2126 phdr->version = version_3_0;
2127 assign_ushort(phdr->palinfo, palinfo_color);
2128 planar = true;
2129 break;
2130 case 16: /* Not defined */
2131 break;
2132 }
2133 break;
2134 case 4:
2135 switch (bits_per_plane) {
2136 case 1:
2137 phdr->version = 2;
2138 memcpy((byte *) phdr->palette, pcx_cmyk_palette,
2139 sizeof(pcx_cmyk_palette));
2140 planar = false;
2141 phdr->bpp = 4;
2142 phdr->nplanes = 1;
2143 break;
2144 case 2: /* Not defined */
2145 break;
2146 case 4: /* Not defined */
2147 break;
2148 case 5: /* Not defined */
2149 break;
2150 case 8: /* Not defined */
2151 break;
2152 case 16: /* Not defined */
2153 break;
2154 }
2155 break;
2156 }
2157 return planar;
2158 }
2159
2160 /* Write a palette on a file. */
2161 static int
2162 pc_write_mono_palette(gx_device * dev, uint max_index, FILE * file)
2163 {
2164 uint i, c;
2165 gx_color_value rgb[3];
2166
2167 for (i = 0; i < max_index; i++) {
2168 rgb[0] = rgb[1] = rgb[2] = i << 8;
2169 for (c = 0; c < 3; c++) {
2170 byte b = gx_color_value_to_byte(rgb[c]);
2171
2172 fputc(b, file);
2173 }
2174 }
2175 return 0;
2176 }
2177 /*
2178 * This routine will send any output data required at the end of a file
2179 * for a particular combination of planes and bits per plane.
2180 *
2181 * Please note that most combinations do not require anything at the end
2182 * of a data file.
2183 *
2184 * Input parameters:
2185 * pdev - Pointer to device data structure
2186 * file - output file
2187 * header - The header structure to hold the data.
2188 * bits_per_plane - The number of bits per plane.
2189 * num_planes - The number of planes.
2190 */
2191 static int
2192 devn_finish_pcx_file(gx_device_printer * pdev, FILE * file, pcx_header * header, int num_planes, int bits_per_plane)
2193 {
2194 switch (num_planes) {
2195 case 1:
2196 switch (bits_per_plane) {
2197 case 1: /* Do nothing */
2198 break;
2199 case 2: /* Not defined */
2200 break;
2201 case 4: /* Do nothing */
2202 break;
2203 case 5: /* Not defined */
2204 break;
2205 case 8:
2206 fputc(0x0c, file);
2207 return pc_write_mono_palette((gx_device *) pdev, 256, file);
2208 case 16: /* Not defined */
2209 break;
2210 }
2211 break;
2212 case 2:
2213 switch (bits_per_plane) {
2214 case 1: /* Not defined */
2215 break;
2216 case 2: /* Not defined */
2217 break;
2218 case 4: /* Not defined */
2219 break;
2220 case 5: /* Not defined */
2221 break;
2222 case 8: /* Not defined */
2223 break;
2224 case 16: /* Not defined */
2225 break;
2226 }
2227 break;
2228 case 3:
2229 switch (bits_per_plane) {
2230 case 1: /* Not defined */
2231 break;
2232 case 2: /* Not defined */
2233 break;
2234 case 4: /* Not defined */
2235 break;
2236 case 5: /* Not defined */
2237 break;
2238 case 8: /* Do nothing */
2239 break;
2240 case 16: /* Not defined */
2241 break;
2242 }
2243 break;
2244 case 4:
2245 switch (bits_per_plane) {
2246 case 1: /* Do nothing */
2247 break;
2248 case 2: /* Not defined */
2249 break;
2250 case 4: /* Not defined */
2251 break;
2252 case 5: /* Not defined */
2253 break;
2254 case 8: /* Not defined */
2255 break;
2256 case 16: /* Not defined */
2257 break;
2258 }
2259 break;
2260 }
2261 return 0;
2262 }
2263
2264 /* Send the page to the printer. */
2265 static int
2266 devn_write_pcx_file(gx_device_printer * pdev, char * filename, int ncomp,
2267 int bpc, int linesize)
2268 {
2269 pcx_header header;
2270 int code;
2271 bool planar;
2272 char outname[gp_file_name_sizeof];
2273 FILE * in;
2274 FILE * out;
2275 int depth = bpc_to_depth(ncomp, bpc);
2276
2277 in = fopen(filename, "rb");
2278 if (!in)
2279 return_error(gs_error_invalidfileaccess);
2280 sprintf(outname, "%s.pcx", filename);
2281 out = fopen(outname, "wb");
2282 if (!out) {
2283 fclose(in);
2284 return_error(gs_error_invalidfileaccess);
2285 }
2286
2287 planar = devn_setup_pcx_header(pdev, &header, ncomp, bpc);
2288 code = devn_pcx_write_page(pdev, in, linesize, out, &header, planar, depth);
2289 if (code >= 0)
2290 code = devn_finish_pcx_file(pdev, out, &header, ncomp, bpc);
2291
2292 fclose(in);
2293 fclose(out);
2294 return code;
2295 }
2296
2297 /* Write out a page in PCX format. */
2298 /* This routine is used for all formats. */
2299 /* The caller has set header->bpp, nplanes, and palette. */
2300 static int
2301 devn_pcx_write_page(gx_device_printer * pdev, FILE * infile, int linesize, FILE * outfile,
2302 pcx_header * phdr, bool planar, int depth)
2303 {
2304 int raster = linesize;
2305 uint rsize = ROUND_UP((pdev->width * phdr->bpp + 7) >> 3, 2); /* PCX format requires even */
2306 int height = pdev->height;
2307 uint lsize = raster + rsize;
2308 byte *line = gs_alloc_bytes(pdev->memory, lsize, "pcx file buffer");
2309 byte *plane = line + raster;
2310 int y;
2311 int code = 0; /* return code */
2312
2313 if (line == 0) /* can't allocate line buffer */
2314 return_error(gs_error_VMerror);
2315
2316 /* Fill in the other variable entries in the header struct. */
2317
2318 assign_ushort(phdr->x2, pdev->width - 1);
2319 assign_ushort(phdr->y2, height - 1);
2320 assign_ushort(phdr->hres, (int)pdev->x_pixels_per_inch);
2321 assign_ushort(phdr->vres, (int)pdev->y_pixels_per_inch);
2322 assign_ushort(phdr->bpl, (planar || depth == 1 ? rsize :
2323 raster + (raster & 1)));
2324
2325 /* Write the header. */
2326
2327 if (fwrite((const char *)phdr, 1, 128, outfile) < 128) {
2328 code = gs_error_ioerror;
2329 goto pcx_done;
2330 }
2331 /* Write the contents of the image. */
2332 for (y = 0; y < height; y++) {
2333 byte *row = line;
2334 byte *end;
2335
2336 code = fread(line, sizeof(byte), linesize, infile);
2337 if (code < 0)
2338 break;
2339 end = row + raster;
2340 if (!planar) { /* Just write the bits. */
2341 if (raster & 1) { /* Round to even, with predictable padding. */
2342 *end = end[-1];
2343 ++end;
2344 }
2345 devn_pcx_write_rle(row, end, 1, outfile);
2346 } else
2347 switch (depth) {
2348
2349 case 4:
2350 {
2351 byte *pend = plane + rsize;
2352 int shift;
2353
2354 for (shift = 0; shift < 4; shift++) {
2355 register byte *from, *to;
2356 register int bright = 1 << shift;
2357 register int bleft = bright << 4;
2358
2359 for (from = row, to = plane;
2360 from < end; from += 4
2361 ) {
2362 *to++ =
2363 (from[0] & bleft ? 0x80 : 0) |
2364 (from[0] & bright ? 0x40 : 0) |
2365 (from[1] & bleft ? 0x20 : 0) |
2366 (from[1] & bright ? 0x10 : 0) |
2367 (from[2] & bleft ? 0x08 : 0) |
2368 (from[2] & bright ? 0x04 : 0) |
2369 (from[3] & bleft ? 0x02 : 0) |
2370 (from[3] & bright ? 0x01 : 0);
2371 }
2372 /* We might be one byte short of rsize. */
2373 if (to < pend)
2374 *to = to[-1];
2375 devn_pcx_write_rle(plane, pend, 1, outfile);
2376 }
2377 }
2378 break;
2379
2380 case 24:
2381 {
2382 int pnum;
2383
2384 for (pnum = 0; pnum < 3; ++pnum) {
2385 devn_pcx_write_rle(row + pnum, row + raster, 3, outfile);
2386 if (pdev->width & 1)
2387 fputc(0, outfile); /* pad to even */
2388 }
2389 }
2390 break;
2391
2392 default:
2393 code = gs_note_error(gs_error_rangecheck);
2394 goto pcx_done;
2395
2396 }
2397 code = 0;
2398 }
2399
2400 pcx_done:
2401 gs_free_object(pdev->memory, line, "pcx file buffer");
2402
2403 return code;
2404 }
2405
2406 /* ------ Internal routines ------ */
2407
2408 /* Write one line in PCX run-length-encoded format. */
2409 static void
2410 devn_pcx_write_rle(const byte * from, const byte * end, int step, FILE * file)
2411 { /*
2412 * The PCX format theoretically allows encoding runs of 63
2413 * identical bytes, but some readers can't handle repetition
2414 * counts greater than 15.
2415 */
2416 #define MAX_RUN_COUNT 15
2417 int max_run = step * MAX_RUN_COUNT;
2418
2419 while (from < end) {
2420 byte data = *from;
2421
2422 from += step;
2423 if (data != *from || from == end) {
2424 if (data >= 0xc0)
2425 putc(0xc1, file);
2426 } else {
2427 const byte *start = from;
2428
2429 while ((from < end) && (*from == data))
2430 from += step;
2431 /* Now (from - start) / step + 1 is the run length. */
2432 while (from - start >= max_run) {
2433 putc(0xc0 + MAX_RUN_COUNT, file);
2434 putc(data, file);
2435 start += max_run;
2436 }
2437 if (from > start || data >= 0xc0)
2438 putc((from - start) / step + 0xc1, file);
2439 }
2440 putc(data, file);
2441 }
2442 #undef MAX_RUN_COUNT
2443 }
2444