]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/imagetoraster.c
Merge changes from CUPS 1.5svn-r8849.
[thirdparty/cups.git] / filter / imagetoraster.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: imagetoraster.c 7306 2008-02-15 00:52:38Z mike $"
ef416fc2 3 *
4 * Image file to raster filter for the Common UNIX Printing System (CUPS).
5 *
4d301e69 6 * Copyright 2007-2009 by Apple Inc.
c0e1af83 7 * Copyright 1993-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * main() - Main entry...
f301802f 20 * blank_line() - Clear a line buffer to the blank value...
ef416fc2 21 * format_CMY() - Convert image data to CMY.
22 * format_CMYK() - Convert image data to CMYK.
23 * format_K() - Convert image data to black.
24 * format_KCMY() - Convert image data to KCMY.
25 * format_KCMYcm() - Convert image data to KCMYcm.
26 * format_RGBA() - Convert image data to RGBA/RGBW.
27 * format_W() - Convert image data to luminance.
28 * format_YMC() - Convert image data to YMC.
29 * format_YMCK() - Convert image data to YMCK.
30 * make_lut() - Make a lookup table given gamma and brightness values.
a74454a7 31 * raster_cb() - Validate the page header.
ef416fc2 32 */
33
34/*
35 * Include necessary headers...
36 */
37
38#include "common.h"
39#include "image-private.h"
ef416fc2 40#include <unistd.h>
41#include <math.h>
c0e1af83 42#include <cups/i18n.h>
ef416fc2 43
44
45/*
46 * Globals...
47 */
48
49int Flip = 0, /* Flip/mirror pages */
50 XPosition = 0, /* Horizontal position on page */
51 YPosition = 0, /* Vertical position on page */
52 Collate = 0, /* Collate copies? */
53 Copies = 1; /* Number of copies */
f301802f 54int Floyd16x16[16][16] = /* Traditional Floyd ordered dither */
ef416fc2 55 {
56 { 0, 128, 32, 160, 8, 136, 40, 168,
57 2, 130, 34, 162, 10, 138, 42, 170 },
58 { 192, 64, 224, 96, 200, 72, 232, 104,
59 194, 66, 226, 98, 202, 74, 234, 106 },
60 { 48, 176, 16, 144, 56, 184, 24, 152,
61 50, 178, 18, 146, 58, 186, 26, 154 },
62 { 240, 112, 208, 80, 248, 120, 216, 88,
63 242, 114, 210, 82, 250, 122, 218, 90 },
64 { 12, 140, 44, 172, 4, 132, 36, 164,
65 14, 142, 46, 174, 6, 134, 38, 166 },
66 { 204, 76, 236, 108, 196, 68, 228, 100,
67 206, 78, 238, 110, 198, 70, 230, 102 },
68 { 60, 188, 28, 156, 52, 180, 20, 148,
69 62, 190, 30, 158, 54, 182, 22, 150 },
70 { 252, 124, 220, 92, 244, 116, 212, 84,
71 254, 126, 222, 94, 246, 118, 214, 86 },
72 { 3, 131, 35, 163, 11, 139, 43, 171,
73 1, 129, 33, 161, 9, 137, 41, 169 },
74 { 195, 67, 227, 99, 203, 75, 235, 107,
75 193, 65, 225, 97, 201, 73, 233, 105 },
76 { 51, 179, 19, 147, 59, 187, 27, 155,
77 49, 177, 17, 145, 57, 185, 25, 153 },
78 { 243, 115, 211, 83, 251, 123, 219, 91,
79 241, 113, 209, 81, 249, 121, 217, 89 },
80 { 15, 143, 47, 175, 7, 135, 39, 167,
81 13, 141, 45, 173, 5, 133, 37, 165 },
82 { 207, 79, 239, 111, 199, 71, 231, 103,
83 205, 77, 237, 109, 197, 69, 229, 101 },
84 { 63, 191, 31, 159, 55, 183, 23, 151,
85 61, 189, 29, 157, 53, 181, 21, 149 },
86 { 254, 127, 223, 95, 247, 119, 215, 87,
87 253, 125, 221, 93, 245, 117, 213, 85 }
88 };
89int Floyd8x8[8][8] =
90 {
91 { 0, 32, 8, 40, 2, 34, 10, 42 },
92 { 48, 16, 56, 24, 50, 18, 58, 26 },
93 { 12, 44, 4, 36, 14, 46, 6, 38 },
94 { 60, 28, 52, 20, 62, 30, 54, 22 },
95 { 3, 35, 11, 43, 1, 33, 9, 41 },
96 { 51, 19, 59, 27, 49, 17, 57, 25 },
97 { 15, 47, 7, 39, 13, 45, 5, 37 },
98 { 63, 31, 55, 23, 61, 29, 53, 21 }
99 };
100int Floyd4x4[4][4] =
101 {
102 { 0, 8, 2, 10 },
103 { 12, 4, 14, 6 },
104 { 3, 11, 1, 9 },
105 { 15, 7, 13, 5 }
106 };
107
108cups_ib_t OnPixels[256], /* On-pixel LUT */
109 OffPixels[256]; /* Off-pixel LUT */
ef416fc2 110
111
112/*
113 * Local functions...
114 */
f301802f 115
116static void blank_line(cups_page_header2_t *header, unsigned char *row);
ef416fc2 117static void format_CMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
118static void format_CMYK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
119static void format_K(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
120static void format_KCMYcm(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
121static void format_KCMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
122#define format_RGB format_CMY
123static void format_RGBA(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
124static void format_W(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
125static void format_YMC(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
126static void format_YMCK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
127static void make_lut(cups_ib_t *, int, float, float);
a74454a7 128static int raster_cb(cups_page_header2_t *header, int preferred_bits);
ef416fc2 129
130
131/*
132 * 'main()' - Main entry...
133 */
134
135int /* O - Exit status */
136main(int argc, /* I - Number of command-line arguments */
137 char *argv[]) /* I - Command-line arguments */
138{
139 int i; /* Looping var */
140 cups_image_t *img; /* Image to print */
141 float xprint, /* Printable area */
142 yprint,
143 xinches, /* Total size in inches */
144 yinches;
145 float xsize, /* Total size in points */
146 ysize,
147 xsize2,
148 ysize2;
149 float aspect; /* Aspect ratio */
150 int xpages, /* # x pages */
151 ypages, /* # y pages */
152 xpage, /* Current x page */
153 ypage, /* Current y page */
154 xtemp, /* Bitmap width in pixels */
155 ytemp, /* Bitmap height in pixels */
156 page; /* Current page number */
a74454a7 157 int xc0, yc0, /* Corners of the page in image coords */
bd7854cb 158 xc1, yc1;
ef416fc2 159 ppd_file_t *ppd; /* PPD file */
a74454a7 160 ppd_choice_t *choice; /* PPD option choice */
ef416fc2 161 char *resolution, /* Output resolution */
162 *media_type; /* Media type */
163 ppd_profile_t *profile; /* Color profile */
164 ppd_profile_t userprofile; /* User-specified profile */
165 cups_raster_t *ras; /* Raster stream */
166 cups_page_header2_t header; /* Page header */
167 int num_options; /* Number of print options */
168 cups_option_t *options; /* Print options */
169 const char *val; /* Option value */
170 int slowcollate, /* Collate copies the slow way */
171 slowcopies; /* Make copies the "slow" way? */
172 float g; /* Gamma correction value */
173 float b; /* Brightness factor */
174 float zoom; /* Zoom facter */
175 int xppi, yppi; /* Pixels-per-inch */
176 int hue, sat; /* Hue and saturation adjustment */
177 cups_izoom_t *z; /* Image zoom buffer */
178 cups_iztype_t zoom_type; /* Image zoom type */
179 int primary, /* Primary image colorspace */
180 secondary; /* Secondary image colorspace */
181 cups_ib_t *row, /* Current row */
182 *r0, /* Top row */
183 *r1; /* Bottom row */
184 int y, /* Current Y coordinate on page */
185 iy, /* Current Y coordinate in image */
186 last_iy, /* Previous Y coordinate in image */
187 yerr0, /* Top Y error value */
f301802f 188 yerr1; /* Bottom Y error value */
ef416fc2 189 cups_ib_t lut[256]; /* Gamma/brightness LUT */
190 int plane, /* Current color plane */
191 num_planes; /* Number of color planes */
192 char filename[1024]; /* Name of file to print */
193
194
195 /*
196 * Make sure status messages are not buffered...
197 */
198
199 setbuf(stderr, NULL);
200
201 /*
202 * Check command-line...
203 */
204
205 if (argc < 6 || argc > 7)
206 {
c0e1af83 207 fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
208 argv[0]);
ef416fc2 209 return (1);
210 }
211
ef416fc2 212 /*
213 * See if we need to use the imagetops and pstoraster filters instead...
214 */
215
216 options = NULL;
217 num_options = cupsParseOptions(argv[5], 0, &options);
218
219 if (getenv("CLASSIFICATION") ||
220 cupsGetOption("page-label", num_options, options))
221 {
222 /*
223 * Yes, fork a copy of pstoraster and then transfer control to imagetops...
224 */
225
226 int mypipes[2]; /* New pipes for imagetops | pstoraster */
227 int pid; /* PID of pstoraster */
228
229
230 cupsFreeOptions(num_options, options);
231
232 if (pipe(mypipes))
233 {
234 perror("ERROR: Unable to create pipes for imagetops | pstoraster");
235 return (errno);
236 }
237
238 if ((pid = fork()) == 0)
239 {
240 /*
241 * Child process for pstoraster... Assign new pipe input to pstoraster...
242 */
243
97c9a8d7 244 dup2(mypipes[0], 0);
ef416fc2 245 close(mypipes[0]);
246 close(mypipes[1]);
247
248 execlp("pstoraster", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
249 NULL);
250 perror("ERROR: Unable to exec pstoraster");
251 return (errno);
252 }
253 else if (pid < 0)
254 {
255 /*
256 * Error!
257 */
258
259 perror("ERROR: Unable to fork pstoraster");
260 return (errno);
261 }
262
263 /*
264 * Update stdout so it points at the new pstoraster...
265 */
266
97c9a8d7 267 dup2(mypipes[1], 1);
ef416fc2 268 close(mypipes[0]);
269 close(mypipes[1]);
270
271 /*
272 * Run imagetops to get the classification or page labelling that was
273 * requested...
274 */
275
276 execlp("imagetops", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
277 argv[6], NULL);
278 perror("ERROR: Unable to exec imagetops");
279 return (errno);
280 }
281
282 /*
283 * Copy stdin as needed...
284 */
285
286 if (argc == 6)
287 {
288 int fd; /* File to write to */
289 char buffer[8192]; /* Buffer to read into */
290 int bytes; /* # of bytes to read */
291
292
293 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
294 {
295 perror("ERROR: Unable to copy image file");
296 return (1);
297 }
298
299 fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
300 filename);
301
302 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
303 write(fd, buffer, bytes);
304
305 close(fd);
306 }
307 else
308 strlcpy(filename, argv[6], sizeof(filename));
309
310 /*
311 * Process command-line options and write the prolog...
312 */
313
314 zoom = 0.0;
315 xppi = 0;
316 yppi = 0;
317 hue = 0;
318 sat = 100;
319 g = 1.0;
320 b = 1.0;
321
322 Copies = atoi(argv[4]);
323
324 ppd = SetCommonOptions(num_options, options, 0);
325
326 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
327 {
328 /*
329 * This IPP attribute is unnecessarily complicated...
330 *
331 * single-document, separate-documents-collated-copies, and
332 * single-document-new-sheet all require collated copies.
333 *
334 * separate-documents-collated-copies allows for uncollated copies.
335 */
336
337 Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
338 }
339
340 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
341 strcasecmp(val, "True") == 0)
342 Collate = 1;
343
344 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
bd7854cb 345 {
346 /*
347 * Get gamma value from 1 to 10000...
348 */
349
ef416fc2 350 g = atoi(val) * 0.001f;
351
bd7854cb 352 if (g < 0.001f)
353 g = 0.001f;
354 else if (g > 10.0f)
355 g = 10.0f;
356 }
357
ef416fc2 358 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
bd7854cb 359 {
360 /*
361 * Get brightness value from 10 to 1000.
362 */
363
ef416fc2 364 b = atoi(val) * 0.01f;
365
bd7854cb 366 if (b < 0.1f)
367 b = 0.1f;
368 else if (b > 10.0f)
369 b = 10.0f;
370 }
371
ef416fc2 372 if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
373 zoom = atoi(val) * 0.01;
ed6e7faf
MS
374 else if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
375 !strcasecmp(val, "true"))
376 zoom = 1.0;
377 else if ((val = cupsGetOption("fit-to-page", num_options, options)) != NULL &&
378 !strcasecmp(val, "true"))
bd7854cb 379 zoom = 1.0;
ef416fc2 380
381 if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
382 if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
383 yppi = xppi;
384
385 if ((val = cupsGetOption("position", num_options, options)) != NULL)
386 {
387 if (strcasecmp(val, "center") == 0)
388 {
389 XPosition = 0;
390 YPosition = 0;
391 }
392 else if (strcasecmp(val, "top") == 0)
393 {
394 XPosition = 0;
395 YPosition = 1;
396 }
397 else if (strcasecmp(val, "left") == 0)
398 {
399 XPosition = -1;
400 YPosition = 0;
401 }
402 else if (strcasecmp(val, "right") == 0)
403 {
404 XPosition = 1;
405 YPosition = 0;
406 }
407 else if (strcasecmp(val, "top-left") == 0)
408 {
409 XPosition = -1;
410 YPosition = 1;
411 }
412 else if (strcasecmp(val, "top-right") == 0)
413 {
414 XPosition = 1;
415 YPosition = 1;
416 }
417 else if (strcasecmp(val, "bottom") == 0)
418 {
419 XPosition = 0;
420 YPosition = -1;
421 }
422 else if (strcasecmp(val, "bottom-left") == 0)
423 {
424 XPosition = -1;
425 YPosition = -1;
426 }
427 else if (strcasecmp(val, "bottom-right") == 0)
428 {
429 XPosition = 1;
430 YPosition = -1;
431 }
432 }
433
434 if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
435 sat = atoi(val);
436
437 if ((val = cupsGetOption("hue", num_options, options)) != NULL)
438 hue = atoi(val);
439
09a101d6 440 if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
441 {
442 val = choice->choice;
443 choice->marked = 0;
444 }
445 else
446 val = cupsGetOption("mirror", num_options, options);
447
448 if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
449 !strcasecmp(val, "yes")))
ef416fc2 450 Flip = 1;
451
452 /*
453 * Set the needed options in the page header...
454 */
455
a74454a7 456 if (cupsRasterInterpretPPD(&header, ppd, num_options, options, raster_cb))
457 {
4d301e69 458 _cupsLangPuts(stderr, _("ERROR: Bad page setup\n"));
c0e1af83 459 fprintf(stderr, "DEBUG: %s\n", cupsRasterErrorString());
a74454a7 460 return (1);
461 }
ef416fc2 462
463 /*
464 * Get the media type and resolution that have been chosen...
465 */
466
467 if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
468 media_type = choice->choice;
469 else
470 media_type = "";
471
472 if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
473 resolution = choice->choice;
474 else
475 resolution = "";
476
477 /*
478 * Choose the appropriate colorspace...
479 */
480
481 switch (header.cupsColorSpace)
482 {
483 case CUPS_CSPACE_W :
f301802f 484 if (header.cupsBitsPerColor >= 8)
485 {
486 primary = CUPS_IMAGE_WHITE;
487 secondary = CUPS_IMAGE_WHITE;
488 }
489 else
490 {
491 primary = CUPS_IMAGE_BLACK;
492 secondary = CUPS_IMAGE_BLACK;
493 }
ef416fc2 494 break;
495
496 default :
497 case CUPS_CSPACE_RGB :
498 case CUPS_CSPACE_RGBA :
499 case CUPS_CSPACE_RGBW :
f301802f 500 if (header.cupsBitsPerColor >= 8)
501 {
502 primary = CUPS_IMAGE_RGB;
503 secondary = CUPS_IMAGE_RGB;
504 }
505 else
506 {
507 primary = CUPS_IMAGE_CMY;
508 secondary = CUPS_IMAGE_CMY;
509 }
ef416fc2 510 break;
511
512 case CUPS_CSPACE_K :
513 case CUPS_CSPACE_WHITE :
514 case CUPS_CSPACE_GOLD :
515 case CUPS_CSPACE_SILVER :
516 primary = CUPS_IMAGE_BLACK;
517 secondary = CUPS_IMAGE_BLACK;
ef416fc2 518 break;
519
520 case CUPS_CSPACE_CMYK :
521 case CUPS_CSPACE_YMCK :
522 case CUPS_CSPACE_KCMY :
f301802f 523 case CUPS_CSPACE_KCMYcm :
ef416fc2 524 case CUPS_CSPACE_GMCK :
525 case CUPS_CSPACE_GMCS :
f301802f 526 if (header.cupsBitsPerColor == 1)
ef416fc2 527 {
528 primary = CUPS_IMAGE_CMY;
529 secondary = CUPS_IMAGE_CMY;
ef416fc2 530 }
531 else
532 {
533 primary = CUPS_IMAGE_CMYK;
534 secondary = CUPS_IMAGE_CMYK;
ef416fc2 535 }
536 break;
f301802f 537
538 case CUPS_CSPACE_CMY :
539 case CUPS_CSPACE_YMC :
540 primary = CUPS_IMAGE_CMY;
541 secondary = CUPS_IMAGE_CMY;
542 break;
543 break;
ef416fc2 544 }
545
546 /*
547 * Find a color profile matching the current options...
548 */
549
550 if ((val = cupsGetOption("profile", num_options, options)) != NULL)
551 {
552 profile = &userprofile;
553 sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
554 &(userprofile.density), &(userprofile.gamma),
555 userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
556 userprofile.matrix[0] + 2,
557 userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
558 userprofile.matrix[1] + 2,
559 userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
560 userprofile.matrix[2] + 2);
561
562 userprofile.density *= 0.001f;
563 userprofile.gamma *= 0.001f;
564 userprofile.matrix[0][0] *= 0.001f;
565 userprofile.matrix[0][1] *= 0.001f;
566 userprofile.matrix[0][2] *= 0.001f;
567 userprofile.matrix[1][0] *= 0.001f;
568 userprofile.matrix[1][1] *= 0.001f;
569 userprofile.matrix[1][2] *= 0.001f;
570 userprofile.matrix[2][0] *= 0.001f;
571 userprofile.matrix[2][1] *= 0.001f;
572 userprofile.matrix[2][2] *= 0.001f;
573 }
574 else if (ppd != NULL)
575 {
576 fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
577 resolution, media_type);
578
579 for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
580 {
581 fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
582 profile->media_type);
583
584 if ((strcmp(profile->resolution, resolution) == 0 ||
585 profile->resolution[0] == '-') &&
586 (strcmp(profile->media_type, media_type) == 0 ||
587 profile->media_type[0] == '-'))
588 {
4d301e69 589 fputs("MATCH\n", stderr);
ef416fc2 590 break;
591 }
592 else
593 fputs("no.\n", stderr);
594 }
595
596 /*
597 * If we found a color profile, use it!
598 */
599
600 if (i >= ppd->num_profiles)
601 profile = NULL;
602 }
603 else
604 profile = NULL;
605
606 if (profile)
607 cupsImageSetProfile(profile->density, profile->gamma, profile->matrix);
608
609 cupsImageSetRasterColorSpace(header.cupsColorSpace);
610
611 /*
612 * Create a gamma/brightness LUT...
613 */
614
615 make_lut(lut, primary, g, b);
616
617 /*
618 * Open the input image to print...
619 */
620
4d301e69 621 _cupsLangPuts(stderr, _("INFO: Loading image file...\n"));
ef416fc2 622
f301802f 623 if (header.cupsColorSpace == CUPS_CSPACE_CIEXYZ ||
624 header.cupsColorSpace == CUPS_CSPACE_CIELab ||
625 header.cupsColorSpace >= CUPS_CSPACE_ICC1)
626 img = cupsImageOpen(filename, primary, secondary, sat, hue, NULL);
627 else
628 img = cupsImageOpen(filename, primary, secondary, sat, hue, lut);
ef416fc2 629
630 if (argc == 6)
631 unlink(filename);
632
633 if (img == NULL)
634 {
4d301e69 635 _cupsLangPuts(stderr, _("ERROR: Unable to open image file for printing\n"));
ef416fc2 636 ppdClose(ppd);
637 return (1);
638 }
639
640 /*
641 * Scale as necessary...
642 */
643
644 if (zoom == 0.0 && xppi == 0)
645 {
646 xppi = img->xppi;
647 yppi = img->yppi;
648 }
649
650 if (yppi == 0)
651 yppi = xppi;
652
653 fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
654 xppi, yppi, zoom);
655
656 if (xppi > 0)
657 {
658 /*
659 * Scale the image as neccesary to match the desired pixels-per-inch.
660 */
661
662 if (Orientation & 1)
663 {
664 xprint = (PageTop - PageBottom) / 72.0;
665 yprint = (PageRight - PageLeft) / 72.0;
666 }
667 else
668 {
669 xprint = (PageRight - PageLeft) / 72.0;
670 yprint = (PageTop - PageBottom) / 72.0;
671 }
672
673 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
674 xprint, yprint);
675
676 xinches = (float)img->xsize / (float)xppi;
677 yinches = (float)img->ysize / (float)yppi;
678
679 fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
680 xinches, yinches);
681
682 if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
683 {
684 xinches = xinches * atoi(val) / 100;
685 yinches = yinches * atoi(val) / 100;
686 }
687
688 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
689 cupsGetOption("landscape", num_options, options) == NULL)
690 {
691 /*
692 * Rotate the image if it will fit landscape but not portrait...
693 */
694
695 fputs("DEBUG: Auto orientation...\n", stderr);
696
697 if ((xinches > xprint || yinches > yprint) &&
698 xinches <= yprint && yinches <= xprint)
699 {
700 /*
701 * Rotate the image as needed...
702 */
703
704 fputs("DEBUG: Using landscape orientation...\n", stderr);
705
706 Orientation = (Orientation + 1) & 3;
707 xsize = yprint;
708 yprint = xprint;
709 xprint = xsize;
710 }
711 }
712 }
713 else
714 {
715 /*
716 * Scale percentage of page size...
717 */
718
719 xprint = (PageRight - PageLeft) / 72.0;
720 yprint = (PageTop - PageBottom) / 72.0;
721 aspect = (float)img->yppi / (float)img->xppi;
722
723 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
724 xprint, yprint);
725
726 fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
727 img->xppi, img->yppi, aspect);
728
729 xsize = xprint * zoom;
730 ysize = xsize * img->ysize / img->xsize / aspect;
731
732 if (ysize > (yprint * zoom))
733 {
734 ysize = yprint * zoom;
735 xsize = ysize * img->xsize * aspect / img->ysize;
736 }
737
738 xsize2 = yprint * zoom;
739 ysize2 = xsize2 * img->ysize / img->xsize / aspect;
740
741 if (ysize2 > (xprint * zoom))
742 {
743 ysize2 = xprint * zoom;
744 xsize2 = ysize2 * img->xsize * aspect / img->ysize;
745 }
746
747 fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
748 fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
749
750 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
751 cupsGetOption("landscape", num_options, options) == NULL)
752 {
753 /*
754 * Choose the rotation with the largest area, but prefer
755 * portrait if they are equal...
756 */
757
758 fputs("DEBUG: Auto orientation...\n", stderr);
759
760 if ((xsize * ysize) < (xsize2 * xsize2))
761 {
762 /*
763 * Do landscape orientation...
764 */
765
766 fputs("DEBUG: Using landscape orientation...\n", stderr);
767
768 Orientation = 1;
769 xinches = xsize2;
770 yinches = ysize2;
771 xprint = (PageTop - PageBottom) / 72.0;
772 yprint = (PageRight - PageLeft) / 72.0;
773 }
774 else
775 {
776 /*
777 * Do portrait orientation...
778 */
779
780 fputs("DEBUG: Using portrait orientation...\n", stderr);
781
782 Orientation = 0;
783 xinches = xsize;
784 yinches = ysize;
785 }
786 }
787 else if (Orientation & 1)
788 {
789 fputs("DEBUG: Using landscape orientation...\n", stderr);
790
791 xinches = xsize2;
792 yinches = ysize2;
793 xprint = (PageTop - PageBottom) / 72.0;
794 yprint = (PageRight - PageLeft) / 72.0;
795 }
796 else
797 {
798 fputs("DEBUG: Using portrait orientation...\n", stderr);
799
800 xinches = xsize;
801 yinches = ysize;
802 xprint = (PageRight - PageLeft) / 72.0;
803 yprint = (PageTop - PageBottom) / 72.0;
804 }
805 }
806
807 /*
808 * Compute the number of pages to print and the size of the image on each
809 * page...
810 */
811
812 xpages = ceil(xinches / xprint);
813 ypages = ceil(yinches / yprint);
814
815 xprint = xinches / xpages;
816 yprint = yinches / ypages;
817
818 fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
819 xpages, xprint, ypages, yprint);
820
821 /*
822 * Compute the bitmap size...
823 */
824
825 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
826 strcasecmp(choice->choice, "Custom") == 0)
827 {
828 float width, /* New width in points */
829 length; /* New length in points */
830
831
832 /*
833 * Use the correct width and length for the current orientation...
834 */
835
836 if (Orientation & 1)
837 {
838 width = yprint * 72.0;
839 length = xprint * 72.0;
840 }
841 else
842 {
843 width = xprint * 72.0;
844 length = yprint * 72.0;
845 }
846
847 /*
848 * Add margins to page size...
849 */
850
851 width += ppd->custom_margins[0] + ppd->custom_margins[2];
852 length += ppd->custom_margins[1] + ppd->custom_margins[3];
853
854 /*
855 * Enforce minimums...
856 */
857
858 if (width < ppd->custom_min[0])
859 width = ppd->custom_min[0];
860
861 if (length < ppd->custom_min[1])
862 length = ppd->custom_min[1];
863
864 fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
865 width / 72.0, length / 72.0);
866
867 /*
868 * Set the new custom size...
869 */
870
f301802f 871 strcpy(header.cupsPageSizeName, "Custom");
872
873 header.cupsPageSize[0] = width + 0.5;
874 header.cupsPageSize[1] = length + 0.5;
875 header.PageSize[0] = width + 0.5;
876 header.PageSize[1] = length + 0.5;
ef416fc2 877
878 /*
879 * Update page variables...
880 */
881
882 PageWidth = width;
883 PageLength = length;
884 PageLeft = ppd->custom_margins[0];
885 PageRight = width - ppd->custom_margins[2];
886 PageBottom = ppd->custom_margins[1];
887 PageTop = length - ppd->custom_margins[3];
888
889 /*
890 * Remove margins from page size...
891 */
892
893 width -= ppd->custom_margins[0] + ppd->custom_margins[2];
894 length -= ppd->custom_margins[1] + ppd->custom_margins[3];
895
896 /*
897 * Set the bitmap size...
898 */
899
900 header.cupsWidth = width * header.HWResolution[0] / 72.0;
901 header.cupsHeight = length * header.HWResolution[1] / 72.0;
f301802f 902
903 header.cupsBytesPerLine = (header.cupsBitsPerPixel *
904 header.cupsWidth + 7) / 8;
905
906 if (header.cupsColorOrder == CUPS_ORDER_BANDED)
907 header.cupsBytesPerLine *= header.cupsNumColors;
ef416fc2 908 }
909
910 header.Margins[0] = PageLeft;
911 header.Margins[1] = PageBottom;
912
913 fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
914 header.PageSize[1]);
915
916 switch (Orientation)
917 {
918 default :
919 switch (XPosition)
920 {
921 case -1 :
f301802f 922 header.cupsImagingBBox[0] = PageLeft;
923 header.cupsImagingBBox[2] = PageLeft + xprint * 72;
ef416fc2 924 break;
925 default :
f301802f 926 header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
927 header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
ef416fc2 928 break;
929 case 1 :
f301802f 930 header.cupsImagingBBox[0] = PageRight - xprint * 72;
931 header.cupsImagingBBox[2] = PageRight;
ef416fc2 932 break;
933 }
934
935 switch (YPosition)
936 {
937 case -1 :
f301802f 938 header.cupsImagingBBox[1] = PageBottom;
939 header.cupsImagingBBox[3] = PageBottom + yprint * 72;
ef416fc2 940 break;
941 default :
f301802f 942 header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
943 header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
ef416fc2 944 break;
945 case 1 :
f301802f 946 header.cupsImagingBBox[1] = PageTop - yprint * 72;
947 header.cupsImagingBBox[3] = PageTop;
ef416fc2 948 break;
949 }
950 break;
951
952 case 1 :
953 switch (XPosition)
954 {
955 case -1 :
f301802f 956 header.cupsImagingBBox[0] = PageBottom;
957 header.cupsImagingBBox[2] = PageBottom + yprint * 72;
ef416fc2 958 break;
959 default :
f301802f 960 header.cupsImagingBBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
961 header.cupsImagingBBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
ef416fc2 962 break;
963 case 1 :
f301802f 964 header.cupsImagingBBox[0] = PageTop - yprint * 72;
965 header.cupsImagingBBox[2] = PageTop;
ef416fc2 966 break;
967 }
968
969 switch (YPosition)
970 {
971 case -1 :
f301802f 972 header.cupsImagingBBox[1] = PageLeft;
973 header.cupsImagingBBox[3] = PageLeft + xprint * 72;
ef416fc2 974 break;
975 default :
f301802f 976 header.cupsImagingBBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
977 header.cupsImagingBBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
ef416fc2 978 break;
979 case 1 :
f301802f 980 header.cupsImagingBBox[1] = PageRight - xprint * 72;
981 header.cupsImagingBBox[3] = PageRight;
ef416fc2 982 break;
983 }
984 break;
985
986 case 2 :
987 switch (XPosition)
988 {
989 case 1 :
f301802f 990 header.cupsImagingBBox[0] = PageLeft;
991 header.cupsImagingBBox[2] = PageLeft + xprint * 72;
ef416fc2 992 break;
993 default :
f301802f 994 header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
995 header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
ef416fc2 996 break;
997 case -1 :
f301802f 998 header.cupsImagingBBox[0] = PageRight - xprint * 72;
999 header.cupsImagingBBox[2] = PageRight;
ef416fc2 1000 break;
1001 }
1002
1003 switch (YPosition)
1004 {
1005 case 1 :
f301802f 1006 header.cupsImagingBBox[1] = PageBottom;
1007 header.cupsImagingBBox[3] = PageBottom + yprint * 72;
ef416fc2 1008 break;
1009 default :
f301802f 1010 header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1011 header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
ef416fc2 1012 break;
1013 case -1 :
f301802f 1014 header.cupsImagingBBox[1] = PageTop - yprint * 72;
1015 header.cupsImagingBBox[3] = PageTop;
ef416fc2 1016 break;
1017 }
1018 break;
1019
1020 case 3 :
1021 switch (XPosition)
1022 {
1023 case 1 :
f301802f 1024 header.cupsImagingBBox[0] = PageBottom;
1025 header.cupsImagingBBox[2] = PageBottom + yprint * 72;
ef416fc2 1026 break;
1027 default :
f301802f 1028 header.cupsImagingBBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
1029 header.cupsImagingBBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
ef416fc2 1030 break;
1031 case -1 :
f301802f 1032 header.cupsImagingBBox[0] = PageTop - yprint * 72;
1033 header.cupsImagingBBox[2] = PageTop;
ef416fc2 1034 break;
1035 }
1036
1037 switch (YPosition)
1038 {
1039 case 1 :
f301802f 1040 header.cupsImagingBBox[1] = PageLeft;
1041 header.cupsImagingBBox[3] = PageLeft + xprint * 72;
ef416fc2 1042 break;
1043 default :
f301802f 1044 header.cupsImagingBBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
1045 header.cupsImagingBBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
ef416fc2 1046 break;
1047 case -1 :
f301802f 1048 header.cupsImagingBBox[1] = PageRight - xprint * 72;
1049 header.cupsImagingBBox[3] = PageRight;
ef416fc2 1050 break;
1051 }
1052 break;
1053 }
1054
f301802f 1055 header.ImagingBoundingBox[0] = header.cupsImagingBBox[0];
1056 header.ImagingBoundingBox[1] = header.cupsImagingBBox[1];
1057 header.ImagingBoundingBox[2] = header.cupsImagingBBox[2];
1058 header.ImagingBoundingBox[3] = header.cupsImagingBBox[3];
ef416fc2 1059
f301802f 1060 if (header.cupsColorOrder == CUPS_ORDER_PLANAR)
1061 num_planes = header.cupsNumColors;
1062 else
1063 num_planes = 1;
ef416fc2 1064
f301802f 1065 if (header.cupsBitsPerColor >= 8)
1066 zoom_type = CUPS_IZOOM_NORMAL;
1067 else
1068 zoom_type = CUPS_IZOOM_FAST;
ef416fc2 1069
1070 /*
1071 * See if we need to collate, and if so how we need to do it...
1072 */
1073
1074 if (xpages == 1 && ypages == 1)
1075 Collate = 0;
1076
1077 slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
1078 if (ppd != NULL)
1079 slowcopies = ppd->manual_copies;
1080 else
1081 slowcopies = 1;
1082
1083 if (Copies > 1 && !slowcollate && !slowcopies)
1084 {
1085 header.Collate = (cups_bool_t)Collate;
1086 header.NumCopies = Copies;
1087
1088 Copies = 1;
1089 }
1090 else
1091 header.NumCopies = 1;
1092
1093 /*
1094 * Create the dithering lookup tables...
1095 */
1096
1097 OnPixels[0] = 0x00;
1098 OnPixels[255] = 0xff;
1099 OffPixels[0] = 0x00;
1100 OffPixels[255] = 0xff;
1101
1102 switch (header.cupsBitsPerColor)
1103 {
1104 case 2 :
1105 for (i = 1; i < 255; i ++)
1106 {
1107 OnPixels[i] = 0x55 * (i / 85 + 1);
1108 OffPixels[i] = 0x55 * (i / 64);
1109 }
1110 break;
1111 case 4 :
1112 for (i = 1; i < 255; i ++)
1113 {
1114 OnPixels[i] = 17 * (i / 17 + 1);
1115 OffPixels[i] = 17 * (i / 16);
1116 }
ef416fc2 1117 break;
1118 }
1119
1120 /*
1121 * Output the pages...
1122 */
1123
1124 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
1125 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
1126 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
1127 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
1128 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
1129 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
1130 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
1131 fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
1132
f301802f 1133 row = malloc(2 * header.cupsBytesPerLine);
1134 ras = cupsRasterOpen(1, CUPS_RASTER_WRITE);
ef416fc2 1135
1136 for (i = 0, page = 1; i < Copies; i ++)
1137 for (xpage = 0; xpage < xpages; xpage ++)
1138 for (ypage = 0; ypage < ypages; ypage ++, page ++)
1139 {
c0e1af83 1140 fprintf(stderr, _("INFO: Formatting page %d...\n"), page);
ef416fc2 1141
1142 if (Orientation & 1)
1143 {
bd7854cb 1144 xc0 = img->xsize * ypage / ypages;
1145 xc1 = img->xsize * (ypage + 1) / ypages - 1;
1146 yc0 = img->ysize * xpage / xpages;
1147 yc1 = img->ysize * (xpage + 1) / xpages - 1;
ef416fc2 1148
1149 xtemp = header.HWResolution[0] * yprint;
1150 ytemp = header.HWResolution[1] * xprint;
1151 }
1152 else
1153 {
bd7854cb 1154 xc0 = img->xsize * xpage / xpages;
1155 xc1 = img->xsize * (xpage + 1) / xpages - 1;
1156 yc0 = img->ysize * ypage / ypages;
1157 yc1 = img->ysize * (ypage + 1) / ypages - 1;
ef416fc2 1158
1159 xtemp = header.HWResolution[0] * xprint;
1160 ytemp = header.HWResolution[1] * yprint;
1161 }
1162
1163 cupsRasterWriteHeader2(ras, &header);
1164
1165 for (plane = 0; plane < num_planes; plane ++)
1166 {
1167 /*
1168 * Initialize the image "zoom" engine...
1169 */
1170
1171 if (Flip)
b423cd4c 1172 z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, -xtemp, ytemp,
f301802f 1173 Orientation & 1, zoom_type);
ef416fc2 1174 else
b423cd4c 1175 z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, xtemp, ytemp,
f301802f 1176 Orientation & 1, zoom_type);
ef416fc2 1177
1178 /*
1179 * Write leading blank space as needed...
1180 */
1181
1182 if (header.cupsHeight > z->ysize && YPosition <= 0)
1183 {
f301802f 1184 blank_line(&header, row);
ef416fc2 1185
1186 y = header.cupsHeight - z->ysize;
1187 if (YPosition == 0)
1188 y /= 2;
1189
f301802f 1190 fprintf(stderr, "DEBUG: Writing %d leading blank lines...\n", y);
1191
ef416fc2 1192 for (; y > 0; y --)
1193 {
1194 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1195 header.cupsBytesPerLine)
1196 {
4d301e69
MS
1197 _cupsLangPuts(stderr,
1198 _("ERROR: Unable to write raster data to "
1199 "driver\n"));
ef416fc2 1200 cupsImageClose(img);
1201 exit(1);
1202 }
1203 }
1204 }
1205
1206 /*
1207 * Then write image data...
1208 */
1209
1210 for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
1211 y > 0;
1212 y --)
1213 {
1214 if (iy != last_iy)
1215 {
1216 if (zoom_type != CUPS_IZOOM_FAST && (iy - last_iy) > 1)
b423cd4c 1217 _cupsImageZoomFill(z, iy);
ef416fc2 1218
b423cd4c 1219 _cupsImageZoomFill(z, iy + z->yincr);
ef416fc2 1220
1221 last_iy = iy;
1222 }
1223
1224 /*
1225 * Format this line of raster data for the printer...
1226 */
1227
f301802f 1228 blank_line(&header, row);
ef416fc2 1229
1230 r0 = z->rows[z->row];
1231 r1 = z->rows[1 - z->row];
1232
1233 switch (header.cupsColorSpace)
1234 {
1235 case CUPS_CSPACE_W :
1236 format_W(&header, row, y, plane, z->xsize, z->ysize,
1237 yerr0, yerr1, r0, r1);
1238 break;
1239 default :
1240 case CUPS_CSPACE_RGB :
1241 format_RGB(&header, row, y, plane, z->xsize, z->ysize,
1242 yerr0, yerr1, r0, r1);
1243 break;
1244 case CUPS_CSPACE_RGBA :
1245 case CUPS_CSPACE_RGBW :
1246 format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
1247 yerr0, yerr1, r0, r1);
1248 break;
1249 case CUPS_CSPACE_K :
1250 case CUPS_CSPACE_WHITE :
1251 case CUPS_CSPACE_GOLD :
1252 case CUPS_CSPACE_SILVER :
1253 format_K(&header, row, y, plane, z->xsize, z->ysize,
1254 yerr0, yerr1, r0, r1);
1255 break;
1256 case CUPS_CSPACE_CMY :
1257 format_CMY(&header, row, y, plane, z->xsize, z->ysize,
1258 yerr0, yerr1, r0, r1);
1259 break;
1260 case CUPS_CSPACE_YMC :
1261 format_YMC(&header, row, y, plane, z->xsize, z->ysize,
1262 yerr0, yerr1, r0, r1);
1263 break;
1264 case CUPS_CSPACE_CMYK :
1265 format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
1266 yerr0, yerr1, r0, r1);
1267 break;
1268 case CUPS_CSPACE_YMCK :
1269 case CUPS_CSPACE_GMCK :
1270 case CUPS_CSPACE_GMCS :
1271 format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
1272 yerr0, yerr1, r0, r1);
1273 break;
f301802f 1274 case CUPS_CSPACE_KCMYcm :
1275 if (header.cupsBitsPerColor == 1)
1276 {
1277 format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
1278 yerr0, yerr1, r0, r1);
1279 break;
1280 }
ef416fc2 1281 case CUPS_CSPACE_KCMY :
1282 format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
1283 yerr0, yerr1, r0, r1);
1284 break;
ef416fc2 1285 }
1286
1287 /*
1288 * Write the raster data to the driver...
1289 */
1290
1291 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1292 header.cupsBytesPerLine)
1293 {
4d301e69
MS
1294 _cupsLangPuts(stderr,
1295 _("ERROR: Unable to write raster data to driver\n"));
ef416fc2 1296 cupsImageClose(img);
1297 exit(1);
1298 }
1299
1300 /*
1301 * Compute the next scanline in the image...
1302 */
1303
1304 iy += z->ystep;
1305 yerr0 += z->ymod;
1306 yerr1 -= z->ymod;
1307 if (yerr1 <= 0)
1308 {
1309 yerr0 -= z->ysize;
1310 yerr1 += z->ysize;
1311 iy += z->yincr;
1312 }
1313 }
1314
1315 /*
1316 * Write trailing blank space as needed...
1317 */
1318
1319 if (header.cupsHeight > z->ysize && YPosition >= 0)
1320 {
f301802f 1321 blank_line(&header, row);
ef416fc2 1322
1323 y = header.cupsHeight - z->ysize;
1324 if (YPosition == 0)
1325 y = y - y / 2;
1326
f301802f 1327 fprintf(stderr, "DEBUG: Writing %d trailing blank lines...\n", y);
1328
ef416fc2 1329 for (; y > 0; y --)
1330 {
1331 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1332 header.cupsBytesPerLine)
1333 {
4d301e69
MS
1334 _cupsLangPuts(stderr,
1335 _("ERROR: Unable to write raster data to "
1336 "driver\n"));
ef416fc2 1337 cupsImageClose(img);
1338 exit(1);
1339 }
1340 }
1341 }
1342
1343 /*
1344 * Free memory used for the "zoom" engine...
1345 */
1346
b423cd4c 1347 _cupsImageZoomDelete(z);
ef416fc2 1348 }
1349 }
1350
1351 /*
1352 * Close files...
1353 */
1354
1355 free(row);
1356 cupsRasterClose(ras);
1357 cupsImageClose(img);
1358 ppdClose(ppd);
1359
1360 return (0);
1361}
1362
1363
f301802f 1364/*
1365 * 'blank_line()' - Clear a line buffer to the blank value...
1366 */
1367
1368static void
1369blank_line(cups_page_header2_t *header, /* I - Page header */
1370 unsigned char *row) /* I - Row buffer */
1371{
1372 int count; /* Remaining bytes */
1373
1374
1375 count = header->cupsBytesPerLine;
1376
1377 switch (header->cupsColorSpace)
1378 {
1379 case CUPS_CSPACE_CIEXYZ :
1380 while (count > 2)
1381 {
1382 *row++ = 242;
1383 *row++ = 255;
1384 *row++ = 255;
1385 count -= 3;
1386 }
1387 break;
1388
1389 case CUPS_CSPACE_CIELab :
1390 case CUPS_CSPACE_ICC1 :
1391 case CUPS_CSPACE_ICC2 :
1392 case CUPS_CSPACE_ICC3 :
1393 case CUPS_CSPACE_ICC4 :
1394 case CUPS_CSPACE_ICC5 :
1395 case CUPS_CSPACE_ICC6 :
1396 case CUPS_CSPACE_ICC7 :
1397 case CUPS_CSPACE_ICC8 :
1398 case CUPS_CSPACE_ICC9 :
1399 case CUPS_CSPACE_ICCA :
1400 case CUPS_CSPACE_ICCB :
1401 case CUPS_CSPACE_ICCC :
1402 case CUPS_CSPACE_ICCD :
1403 case CUPS_CSPACE_ICCE :
1404 case CUPS_CSPACE_ICCF :
1405 while (count > 2)
1406 {
1407 *row++ = 255;
1408 *row++ = 128;
1409 *row++ = 128;
1410 count -= 3;
1411 }
1412 break;
1413
1414 case CUPS_CSPACE_K :
1415 case CUPS_CSPACE_CMY :
1416 case CUPS_CSPACE_CMYK :
1417 case CUPS_CSPACE_YMC :
1418 case CUPS_CSPACE_YMCK :
1419 case CUPS_CSPACE_KCMY :
1420 case CUPS_CSPACE_KCMYcm :
1421 case CUPS_CSPACE_GMCK :
1422 case CUPS_CSPACE_GMCS :
1423 case CUPS_CSPACE_WHITE :
1424 case CUPS_CSPACE_GOLD :
1425 case CUPS_CSPACE_SILVER :
1426 memset(row, 0, count);
1427 break;
1428
1429 default :
1430 memset(row, 255, count);
1431 break;
1432 }
1433}
1434
1435
ef416fc2 1436/*
1437 * 'format_CMY()' - Convert image data to CMY.
1438 */
1439
1440static void
1441format_CMY(cups_page_header2_t *header, /* I - Page header */
1442 unsigned char *row, /* IO - Bitmap data for device */
1443 int y, /* I - Current row */
1444 int z, /* I - Current plane */
1445 int xsize, /* I - Width of image data */
1446 int ysize, /* I - Height of image data */
1447 int yerr0, /* I - Top Y error */
1448 int yerr1, /* I - Bottom Y error */
a74454a7 1449 cups_ib_t *r0, /* I - Primary image data */
1450 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 1451{
a74454a7 1452 cups_ib_t *ptr, /* Pointer into row */
1453 *cptr, /* Pointer into cyan */
1454 *mptr, /* Pointer into magenta */
1455 *yptr, /* Pointer into yellow */
1456 bitmask; /* Current mask for pixel */
1457 int bitoffset; /* Current offset in line */
1458 int bandwidth; /* Width of a color band */
1459 int x, /* Current X coordinate on page */
1460 *dither; /* Pointer into dither array */
ef416fc2 1461
1462
1463 switch (XPosition)
1464 {
1465 case -1 :
1466 bitoffset = 0;
1467 break;
1468 default :
1469 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
1470 break;
1471 case 1 :
1472 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
1473 break;
1474 }
1475
1476 ptr = row + bitoffset / 8;
1477 bandwidth = header->cupsBytesPerLine / 3;
1478
1479 switch (header->cupsColorOrder)
1480 {
1481 case CUPS_ORDER_CHUNKED :
1482 switch (header->cupsBitsPerColor)
1483 {
1484 case 1 :
1485 bitmask = 64 >> (bitoffset & 7);
f301802f 1486 dither = Floyd16x16[y & 15];
ef416fc2 1487
1488 for (x = xsize ; x > 0; x --)
1489 {
1490 if (*r0++ > dither[x & 15])
1491 *ptr ^= bitmask;
1492 bitmask >>= 1;
1493
1494 if (*r0++ > dither[x & 15])
1495 *ptr ^= bitmask;
1496 bitmask >>= 1;
1497
1498 if (*r0++ > dither[x & 15])
1499 *ptr ^= bitmask;
1500
1501 if (bitmask > 1)
1502 bitmask >>= 2;
1503 else
1504 {
1505 bitmask = 64;
1506 ptr ++;
1507 }
1508 }
1509 break;
1510
1511 case 2 :
1512 dither = Floyd8x8[y & 7];
1513
1514 for (x = xsize ; x > 0; x --, r0 += 3)
1515 {
1516 if ((r0[0] & 63) > dither[x & 7])
1517 *ptr ^= (0x30 & OnPixels[r0[0]]);
1518 else
1519 *ptr ^= (0x30 & OffPixels[r0[0]]);
1520
1521 if ((r0[1] & 63) > dither[x & 7])
1522 *ptr ^= (0x0c & OnPixels[r0[1]]);
1523 else
1524 *ptr ^= (0x0c & OffPixels[r0[1]]);
1525
1526 if ((r0[2] & 63) > dither[x & 7])
1527 *ptr++ ^= (0x03 & OnPixels[r0[2]]);
1528 else
1529 *ptr++ ^= (0x03 & OffPixels[r0[2]]);
1530 }
1531 break;
1532
1533 case 4 :
1534 dither = Floyd4x4[y & 3];
1535
1536 for (x = xsize ; x > 0; x --, r0 += 3)
1537 {
1538 if ((r0[0] & 15) > dither[x & 3])
1539 *ptr++ ^= (0x0f & OnPixels[r0[0]]);
1540 else
1541 *ptr++ ^= (0x0f & OffPixels[r0[0]]);
1542
1543 if ((r0[1] & 15) > dither[x & 3])
1544 *ptr ^= (0xf0 & OnPixels[r0[1]]);
1545 else
1546 *ptr ^= (0xf0 & OffPixels[r0[1]]);
1547
1548 if ((r0[2] & 15) > dither[x & 3])
1549 *ptr++ ^= (0x0f & OnPixels[r0[2]]);
1550 else
1551 *ptr++ ^= (0x0f & OffPixels[r0[2]]);
1552 }
1553 break;
1554
1555 case 8 :
1556 for (x = xsize * 3; x > 0; x --, r0 ++, r1 ++)
1557 if (*r0 == *r1)
1558 *ptr++ = *r0;
1559 else
1560 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1561 break;
1562 }
1563 break;
1564
1565 case CUPS_ORDER_BANDED :
1566 cptr = ptr;
1567 mptr = ptr + bandwidth;
1568 yptr = ptr + 2 * bandwidth;
1569
1570 switch (header->cupsBitsPerColor)
1571 {
1572 case 1 :
1573 bitmask = 0x80 >> (bitoffset & 7);
f301802f 1574 dither = Floyd16x16[y & 15];
ef416fc2 1575
1576 for (x = xsize; x > 0; x --)
1577 {
1578 if (*r0++ > dither[x & 15])
1579 *cptr ^= bitmask;
1580 if (*r0++ > dither[x & 15])
1581 *mptr ^= bitmask;
1582 if (*r0++ > dither[x & 15])
1583 *yptr ^= bitmask;
1584
1585 if (bitmask > 1)
1586 bitmask >>= 1;
1587 else
1588 {
1589 bitmask = 0x80;
1590 cptr ++;
1591 mptr ++;
1592 yptr ++;
1593 }
1594 }
1595 break;
1596
1597 case 2 :
f301802f 1598 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 1599 dither = Floyd8x8[y & 7];
1600
1601 for (x = xsize; x > 0; x --)
1602 {
1603 if ((*r0 & 63) > dither[x & 7])
1604 *cptr ^= (bitmask & OnPixels[*r0++]);
1605 else
1606 *cptr ^= (bitmask & OffPixels[*r0++]);
1607
1608 if ((*r0 & 63) > dither[x & 7])
1609 *mptr ^= (bitmask & OnPixels[*r0++]);
1610 else
1611 *mptr ^= (bitmask & OffPixels[*r0++]);
1612
1613 if ((*r0 & 63) > dither[x & 7])
1614 *yptr ^= (bitmask & OnPixels[*r0++]);
1615 else
1616 *yptr ^= (bitmask & OffPixels[*r0++]);
1617
1618 if (bitmask > 3)
1619 bitmask >>= 2;
1620 else
1621 {
f301802f 1622 bitmask = 0xc0;
ef416fc2 1623
1624 cptr ++;
1625 mptr ++;
1626 yptr ++;
1627 }
1628 }
1629 break;
1630
1631 case 4 :
1632 bitmask = 0xf0 >> (bitoffset & 7);
1633 dither = Floyd4x4[y & 3];
1634
1635 for (x = xsize; x > 0; x --)
1636 {
1637 if ((*r0 & 15) > dither[x & 3])
1638 *cptr ^= (bitmask & OnPixels[*r0++]);
1639 else
1640 *cptr ^= (bitmask & OffPixels[*r0++]);
1641
1642 if ((*r0 & 15) > dither[x & 3])
1643 *mptr ^= (bitmask & OnPixels[*r0++]);
1644 else
1645 *mptr ^= (bitmask & OffPixels[*r0++]);
1646
1647 if ((*r0 & 15) > dither[x & 3])
1648 *yptr ^= (bitmask & OnPixels[*r0++]);
1649 else
1650 *yptr ^= (bitmask & OffPixels[*r0++]);
1651
1652 if (bitmask == 0xf0)
1653 bitmask = 0x0f;
1654 else
1655 {
1656 bitmask = 0xf0;
1657
1658 cptr ++;
1659 mptr ++;
1660 yptr ++;
1661 }
1662 }
1663 break;
1664
1665 case 8 :
1666 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
1667 {
1668 if (r0[0] == r1[0])
1669 *cptr++ = r0[0];
1670 else
1671 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
1672
1673 if (r0[1] == r1[1])
1674 *mptr++ = r0[1];
1675 else
1676 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
1677
1678 if (r0[2] == r1[2])
1679 *yptr++ = r0[2];
1680 else
1681 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
1682 }
1683 break;
1684 }
1685 break;
1686
1687 case CUPS_ORDER_PLANAR :
1688 switch (header->cupsBitsPerColor)
1689 {
1690 case 1 :
1691 bitmask = 0x80 >> (bitoffset & 7);
f301802f 1692 dither = Floyd16x16[y & 15];
ef416fc2 1693
1694 switch (z)
1695 {
1696 case 0 :
1697 for (x = xsize; x > 0; x --, r0 += 3)
1698 {
1699 if (r0[0] > dither[x & 15])
1700 *ptr ^= bitmask;
1701
1702 if (bitmask > 1)
1703 bitmask >>= 1;
1704 else
1705 {
1706 bitmask = 0x80;
1707 ptr ++;
1708 }
1709 }
1710 break;
1711
1712 case 1 :
1713 for (x = xsize; x > 0; x --, r0 += 3)
1714 {
1715 if (r0[1] > dither[x & 15])
1716 *ptr ^= bitmask;
1717
1718 if (bitmask > 1)
1719 bitmask >>= 1;
1720 else
1721 {
1722 bitmask = 0x80;
1723 ptr ++;
1724 }
1725 }
1726 break;
1727
1728 case 2 :
1729 for (x = xsize; x > 0; x --, r0 += 3)
1730 {
1731 if (r0[2] > dither[x & 15])
1732 *ptr ^= bitmask;
1733
1734 if (bitmask > 1)
1735 bitmask >>= 1;
1736 else
1737 {
1738 bitmask = 0x80;
1739 ptr ++;
1740 }
1741 }
1742 break;
1743 }
1744 break;
1745
1746 case 2 :
f301802f 1747 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 1748 dither = Floyd8x8[y & 7];
1749 r0 += z;
1750
1751 for (x = xsize; x > 0; x --, r0 += 3)
1752 {
1753 if ((*r0 & 63) > dither[x & 7])
1754 *ptr ^= (bitmask & OnPixels[*r0]);
1755 else
1756 *ptr ^= (bitmask & OffPixels[*r0]);
1757
1758 if (bitmask > 3)
1759 bitmask >>= 2;
1760 else
1761 {
f301802f 1762 bitmask = 0xc0;
ef416fc2 1763
1764 ptr ++;
1765 }
1766 }
1767 break;
1768
1769 case 4 :
1770 bitmask = 0xf0 >> (bitoffset & 7);
1771 dither = Floyd4x4[y & 3];
1772 r0 += z;
1773
1774 for (x = xsize; x > 0; x --, r0 += 3)
1775 {
1776 if ((*r0 & 15) > dither[x & 3])
1777 *ptr ^= (bitmask & OnPixels[*r0]);
1778 else
1779 *ptr ^= (bitmask & OffPixels[*r0]);
1780
1781 if (bitmask == 0xf0)
1782 bitmask = 0x0f;
1783 else
1784 {
1785 bitmask = 0xf0;
1786
1787 ptr ++;
1788 }
1789 }
1790 break;
1791
1792 case 8 :
1793 r0 += z;
1794 r1 += z;
1795
1796 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
1797 {
1798 if (*r0 == *r1)
1799 *ptr++ = *r0;
1800 else
1801 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1802 }
1803 break;
1804 }
1805 break;
1806 }
1807}
1808
1809
1810/*
1811 * 'format_CMYK()' - Convert image data to CMYK.
1812 */
1813
1814static void
a74454a7 1815format_CMYK(cups_page_header2_t *header,/* I - Page header */
ef416fc2 1816 unsigned char *row, /* IO - Bitmap data for device */
1817 int y, /* I - Current row */
1818 int z, /* I - Current plane */
1819 int xsize, /* I - Width of image data */
1820 int ysize, /* I - Height of image data */
1821 int yerr0, /* I - Top Y error */
1822 int yerr1, /* I - Bottom Y error */
a74454a7 1823 cups_ib_t *r0, /* I - Primary image data */
1824 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 1825{
a74454a7 1826 cups_ib_t *ptr, /* Pointer into row */
1827 *cptr, /* Pointer into cyan */
1828 *mptr, /* Pointer into magenta */
1829 *yptr, /* Pointer into yellow */
1830 *kptr, /* Pointer into black */
1831 bitmask; /* Current mask for pixel */
1832 int bitoffset; /* Current offset in line */
1833 int bandwidth; /* Width of a color band */
1834 int x, /* Current X coordinate on page */
1835 *dither; /* Pointer into dither array */
f301802f 1836 int pc, pm, py; /* CMY pixels */
ef416fc2 1837
1838
1839 switch (XPosition)
1840 {
1841 case -1 :
1842 bitoffset = 0;
1843 break;
1844 default :
1845 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
1846 break;
1847 case 1 :
1848 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
1849 break;
1850 }
1851
1852 ptr = row + bitoffset / 8;
1853 bandwidth = header->cupsBytesPerLine / 4;
1854
1855 switch (header->cupsColorOrder)
1856 {
1857 case CUPS_ORDER_CHUNKED :
1858 switch (header->cupsBitsPerColor)
1859 {
1860 case 1 :
1861 bitmask = 128 >> (bitoffset & 7);
f301802f 1862 dither = Floyd16x16[y & 15];
ef416fc2 1863
1864 for (x = xsize ; x > 0; x --)
1865 {
f301802f 1866 pc = *r0++ > dither[x & 15];
1867 pm = *r0++ > dither[x & 15];
1868 py = *r0++ > dither[x & 15];
ef416fc2 1869
f301802f 1870 if (pc && pm && py)
1871 {
1872 bitmask >>= 3;
ef416fc2 1873 *ptr ^= bitmask;
f301802f 1874 }
1875 else
1876 {
1877 if (pc)
1878 *ptr ^= bitmask;
1879 bitmask >>= 1;
ef416fc2 1880
f301802f 1881 if (pm)
1882 *ptr ^= bitmask;
1883 bitmask >>= 1;
ef416fc2 1884
f301802f 1885 if (py)
1886 *ptr ^= bitmask;
1887 bitmask >>= 1;
1888 }
ef416fc2 1889
1890 if (bitmask > 1)
1891 bitmask >>= 1;
1892 else
1893 {
1894 bitmask = 128;
1895 ptr ++;
1896 }
1897 }
1898 break;
1899
1900 case 2 :
1901 dither = Floyd8x8[y & 7];
1902
1903 for (x = xsize ; x > 0; x --, r0 += 4)
1904 {
1905 if ((r0[0] & 63) > dither[x & 7])
f301802f 1906 *ptr ^= (0xc0 & OnPixels[r0[0]]);
ef416fc2 1907 else
f301802f 1908 *ptr ^= (0xc0 & OffPixels[r0[0]]);
ef416fc2 1909
1910 if ((r0[1] & 63) > dither[x & 7])
1911 *ptr ^= (0x30 & OnPixels[r0[1]]);
1912 else
1913 *ptr ^= (0x30 & OffPixels[r0[1]]);
1914
1915 if ((r0[2] & 63) > dither[x & 7])
1916 *ptr ^= (0x0c & OnPixels[r0[2]]);
1917 else
1918 *ptr ^= (0x0c & OffPixels[r0[2]]);
1919
1920 if ((r0[3] & 63) > dither[x & 7])
1921 *ptr++ ^= (0x03 & OnPixels[r0[3]]);
1922 else
1923 *ptr++ ^= (0x03 & OffPixels[r0[3]]);
1924 }
1925 break;
1926
1927 case 4 :
1928 dither = Floyd4x4[y & 3];
1929
1930 for (x = xsize ; x > 0; x --, r0 += 4)
1931 {
1932 if ((r0[0] & 15) > dither[x & 3])
1933 *ptr ^= (0xf0 & OnPixels[r0[0]]);
1934 else
1935 *ptr ^= (0xf0 & OffPixels[r0[0]]);
1936
1937 if ((r0[1] & 15) > dither[x & 3])
1938 *ptr++ ^= (0x0f & OnPixels[r0[1]]);
1939 else
1940 *ptr++ ^= (0x0f & OffPixels[r0[1]]);
1941
1942 if ((r0[2] & 15) > dither[x & 3])
1943 *ptr ^= (0xf0 & OnPixels[r0[2]]);
1944 else
1945 *ptr ^= (0xf0 & OffPixels[r0[2]]);
1946
1947 if ((r0[3] & 15) > dither[x & 3])
1948 *ptr++ ^= (0x0f & OnPixels[r0[3]]);
1949 else
1950 *ptr++ ^= (0x0f & OffPixels[r0[3]]);
1951 }
1952 break;
1953
1954 case 8 :
1955 for (x = xsize * 4; x > 0; x --, r0 ++, r1 ++)
1956 if (*r0 == *r1)
1957 *ptr++ = *r0;
1958 else
1959 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1960 break;
1961 }
1962 break;
1963
1964 case CUPS_ORDER_BANDED :
1965 cptr = ptr;
1966 mptr = ptr + bandwidth;
1967 yptr = ptr + 2 * bandwidth;
1968 kptr = ptr + 3 * bandwidth;
1969
1970 switch (header->cupsBitsPerColor)
1971 {
1972 case 1 :
1973 bitmask = 0x80 >> (bitoffset & 7);
f301802f 1974 dither = Floyd16x16[y & 15];
ef416fc2 1975
1976 for (x = xsize; x > 0; x --)
1977 {
f301802f 1978 pc = *r0++ > dither[x & 15];
1979 pm = *r0++ > dither[x & 15];
1980 py = *r0++ > dither[x & 15];
1981
1982 if (pc && pm && py)
1983 *kptr ^= bitmask;
1984 else
1985 {
1986 if (pc)
1987 *cptr ^= bitmask;
1988 if (pm)
1989 *mptr ^= bitmask;
1990 if (py)
1991 *yptr ^= bitmask;
1992 }
ef416fc2 1993
1994 if (bitmask > 1)
1995 bitmask >>= 1;
1996 else
1997 {
1998 bitmask = 0x80;
1999 cptr ++;
2000 mptr ++;
2001 yptr ++;
2002 kptr ++;
2003 }
2004 }
2005 break;
2006
2007 case 2 :
f301802f 2008 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 2009 dither = Floyd8x8[y & 7];
2010
2011 for (x = xsize; x > 0; x --)
2012 {
2013 if ((*r0 & 63) > dither[x & 7])
2014 *cptr ^= (bitmask & OnPixels[*r0++]);
2015 else
2016 *cptr ^= (bitmask & OffPixels[*r0++]);
2017
2018 if ((*r0 & 63) > dither[x & 7])
2019 *mptr ^= (bitmask & OnPixels[*r0++]);
2020 else
2021 *mptr ^= (bitmask & OffPixels[*r0++]);
2022
2023 if ((*r0 & 63) > dither[x & 7])
2024 *yptr ^= (bitmask & OnPixels[*r0++]);
2025 else
2026 *yptr ^= (bitmask & OffPixels[*r0++]);
2027
2028 if ((*r0 & 63) > dither[x & 7])
2029 *kptr ^= (bitmask & OnPixels[*r0++]);
2030 else
2031 *kptr ^= (bitmask & OffPixels[*r0++]);
2032
2033 if (bitmask > 3)
2034 bitmask >>= 2;
2035 else
2036 {
f301802f 2037 bitmask = 0xc0;
ef416fc2 2038
2039 cptr ++;
2040 mptr ++;
2041 yptr ++;
2042 kptr ++;
2043 }
2044 }
2045 break;
2046
2047 case 4 :
2048 bitmask = 0xf0 >> (bitoffset & 7);
2049 dither = Floyd4x4[y & 3];
2050
2051 for (x = xsize; x > 0; x --)
2052 {
2053 if ((*r0 & 15) > dither[x & 3])
2054 *cptr ^= (bitmask & OnPixels[*r0++]);
2055 else
2056 *cptr ^= (bitmask & OffPixels[*r0++]);
2057
2058 if ((*r0 & 15) > dither[x & 3])
2059 *mptr ^= (bitmask & OnPixels[*r0++]);
2060 else
2061 *mptr ^= (bitmask & OffPixels[*r0++]);
2062
2063 if ((*r0 & 15) > dither[x & 3])
2064 *yptr ^= (bitmask & OnPixels[*r0++]);
2065 else
2066 *yptr ^= (bitmask & OffPixels[*r0++]);
2067
2068 if ((*r0 & 15) > dither[x & 3])
2069 *kptr ^= (bitmask & OnPixels[*r0++]);
2070 else
2071 *kptr ^= (bitmask & OffPixels[*r0++]);
2072
2073 if (bitmask == 0xf0)
2074 bitmask = 0x0f;
2075 else
2076 {
2077 bitmask = 0xf0;
2078
2079 cptr ++;
2080 mptr ++;
2081 yptr ++;
2082 kptr ++;
2083 }
2084 }
2085 break;
2086
2087 case 8 :
2088 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2089 {
2090 if (r0[0] == r1[0])
2091 *cptr++ = r0[0];
2092 else
2093 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2094
2095 if (r0[1] == r1[1])
2096 *mptr++ = r0[1];
2097 else
2098 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2099
2100 if (r0[2] == r1[2])
2101 *yptr++ = r0[2];
2102 else
2103 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2104
2105 if (r0[3] == r1[3])
2106 *kptr++ = r0[3];
2107 else
2108 *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2109 }
2110 break;
2111 }
2112 break;
2113
2114 case CUPS_ORDER_PLANAR :
2115 switch (header->cupsBitsPerColor)
2116 {
2117 case 1 :
2118 bitmask = 0x80 >> (bitoffset & 7);
f301802f 2119 dither = Floyd16x16[y & 15];
ef416fc2 2120
f301802f 2121 for (x = xsize; x > 0; x --)
ef416fc2 2122 {
f301802f 2123 pc = *r0++ > dither[x & 15];
2124 pm = *r0++ > dither[x & 15];
2125 py = *r0++ > dither[x & 15];
2126
2127 if ((pc && pm && py && z == 3) ||
2128 (pc && z == 0) || (pm && z == 1) || (py && z == 2))
ef416fc2 2129 *ptr ^= bitmask;
2130
2131 if (bitmask > 1)
2132 bitmask >>= 1;
2133 else
2134 {
2135 bitmask = 0x80;
2136 ptr ++;
2137 }
2138 }
2139 break;
2140
2141 case 2 :
f301802f 2142 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 2143 dither = Floyd8x8[y & 7];
2144 r0 += z;
2145
2146 for (x = xsize; x > 0; x --, r0 += 4)
2147 {
2148 if ((*r0 & 63) > dither[x & 7])
2149 *ptr ^= (bitmask & OnPixels[*r0]);
2150 else
2151 *ptr ^= (bitmask & OffPixels[*r0]);
2152
2153 if (bitmask > 3)
2154 bitmask >>= 2;
2155 else
2156 {
f301802f 2157 bitmask = 0xc0;
ef416fc2 2158
2159 ptr ++;
2160 }
2161 }
2162 break;
2163
2164 case 4 :
2165 bitmask = 0xf0 >> (bitoffset & 7);
2166 dither = Floyd4x4[y & 3];
2167 r0 += z;
2168
2169 for (x = xsize; x > 0; x --, r0 += 4)
2170 {
2171 if ((*r0 & 15) > dither[x & 3])
2172 *ptr ^= (bitmask & OnPixels[*r0]);
2173 else
2174 *ptr ^= (bitmask & OffPixels[*r0]);
2175
2176 if (bitmask == 0xf0)
2177 bitmask = 0x0f;
2178 else
2179 {
2180 bitmask = 0xf0;
2181
2182 ptr ++;
2183 }
2184 }
2185 break;
2186
2187 case 8 :
2188 r0 += z;
2189 r1 += z;
2190
2191 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2192 {
2193 if (*r0 == *r1)
2194 *ptr++ = *r0;
2195 else
2196 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2197 }
2198 break;
2199 }
2200 break;
2201 }
2202}
2203
2204
2205/*
2206 * 'format_K()' - Convert image data to black.
2207 */
2208
2209static void
2210format_K(cups_page_header2_t *header, /* I - Page header */
2211 unsigned char *row, /* IO - Bitmap data for device */
2212 int y, /* I - Current row */
2213 int z, /* I - Current plane */
2214 int xsize, /* I - Width of image data */
2215 int ysize, /* I - Height of image data */
2216 int yerr0, /* I - Top Y error */
2217 int yerr1, /* I - Bottom Y error */
a74454a7 2218 cups_ib_t *r0, /* I - Primary image data */
2219 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 2220{
a74454a7 2221 cups_ib_t *ptr, /* Pointer into row */
2222 bitmask; /* Current mask for pixel */
2223 int bitoffset; /* Current offset in line */
2224 int x, /* Current X coordinate on page */
2225 *dither; /* Pointer into dither array */
ef416fc2 2226
2227
2228 (void)z;
2229
2230 switch (XPosition)
2231 {
2232 case -1 :
2233 bitoffset = 0;
2234 break;
2235 default :
2236 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2237 break;
2238 case 1 :
2239 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2240 break;
2241 }
2242
2243 ptr = row + bitoffset / 8;
2244
2245 switch (header->cupsBitsPerColor)
2246 {
2247 case 1 :
2248 bitmask = 0x80 >> (bitoffset & 7);
f301802f 2249 dither = Floyd16x16[y & 15];
ef416fc2 2250
2251 for (x = xsize; x > 0; x --)
2252 {
2253 if (*r0++ > dither[x & 15])
2254 *ptr ^= bitmask;
2255
2256 if (bitmask > 1)
2257 bitmask >>= 1;
2258 else
2259 {
2260 bitmask = 0x80;
2261 ptr ++;
2262 }
2263 }
2264 break;
2265
2266 case 2 :
f301802f 2267 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 2268 dither = Floyd8x8[y & 7];
2269
2270 for (x = xsize; x > 0; x --)
2271 {
2272 if ((*r0 & 63) > dither[x & 7])
2273 *ptr ^= (bitmask & OnPixels[*r0++]);
2274 else
2275 *ptr ^= (bitmask & OffPixels[*r0++]);
2276
2277 if (bitmask > 3)
2278 bitmask >>= 2;
2279 else
2280 {
f301802f 2281 bitmask = 0xc0;
ef416fc2 2282
2283 ptr ++;
2284 }
2285 }
2286 break;
2287
2288 case 4 :
2289 bitmask = 0xf0 >> (bitoffset & 7);
2290 dither = Floyd4x4[y & 3];
2291
2292 for (x = xsize; x > 0; x --)
2293 {
2294 if ((*r0 & 15) > dither[x & 3])
2295 *ptr ^= (bitmask & OnPixels[*r0++]);
2296 else
2297 *ptr ^= (bitmask & OffPixels[*r0++]);
2298
2299 if (bitmask == 0xf0)
2300 bitmask = 0x0f;
2301 else
2302 {
2303 bitmask = 0xf0;
2304
2305 ptr ++;
2306 }
2307 }
2308 break;
2309
2310 case 8 :
2311 for (x = xsize; x > 0; x --, r0 ++, r1 ++)
2312 {
2313 if (*r0 == *r1)
2314 *ptr++ = *r0;
2315 else
2316 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2317 }
2318 break;
2319 }
2320}
2321
2322
2323/*
2324 * 'format_KCMY()' - Convert image data to KCMY.
2325 */
2326
2327static void
a74454a7 2328format_KCMY(cups_page_header2_t *header,/* I - Page header */
ef416fc2 2329 unsigned char *row, /* IO - Bitmap data for device */
2330 int y, /* I - Current row */
2331 int z, /* I - Current plane */
2332 int xsize, /* I - Width of image data */
2333 int ysize, /* I - Height of image data */
2334 int yerr0, /* I - Top Y error */
2335 int yerr1, /* I - Bottom Y error */
a74454a7 2336 cups_ib_t *r0, /* I - Primary image data */
2337 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 2338{
a74454a7 2339 cups_ib_t *ptr, /* Pointer into row */
2340 *cptr, /* Pointer into cyan */
2341 *mptr, /* Pointer into magenta */
2342 *yptr, /* Pointer into yellow */
2343 *kptr, /* Pointer into black */
2344 bitmask; /* Current mask for pixel */
2345 int bitoffset; /* Current offset in line */
2346 int bandwidth; /* Width of a color band */
2347 int x, /* Current X coordinate on page */
2348 *dither; /* Pointer into dither array */
f301802f 2349 int pc, pm, py; /* CMY pixels */
ef416fc2 2350
2351
2352 switch (XPosition)
2353 {
2354 case -1 :
2355 bitoffset = 0;
2356 break;
2357 default :
2358 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2359 break;
2360 case 1 :
2361 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2362 break;
2363 }
2364
2365 ptr = row + bitoffset / 8;
2366 bandwidth = header->cupsBytesPerLine / 4;
2367
2368 switch (header->cupsColorOrder)
2369 {
2370 case CUPS_ORDER_CHUNKED :
2371 switch (header->cupsBitsPerColor)
2372 {
2373 case 1 :
2374 bitmask = 128 >> (bitoffset & 7);
f301802f 2375 dither = Floyd16x16[y & 15];
ef416fc2 2376
f301802f 2377 for (x = xsize ; x > 0; x --)
ef416fc2 2378 {
f301802f 2379 pc = *r0++ > dither[x & 15];
2380 pm = *r0++ > dither[x & 15];
2381 py = *r0++ > dither[x & 15];
ef416fc2 2382
f301802f 2383 if (pc && pm && py)
2384 {
ef416fc2 2385 *ptr ^= bitmask;
f301802f 2386 bitmask >>= 3;
2387 }
2388 else
2389 {
2390 bitmask >>= 1;
2391 if (pc)
2392 *ptr ^= bitmask;
ef416fc2 2393
f301802f 2394 bitmask >>= 1;
2395 if (pm)
2396 *ptr ^= bitmask;
ef416fc2 2397
f301802f 2398 bitmask >>= 1;
2399 if (py)
2400 *ptr ^= bitmask;
2401 }
ef416fc2 2402
2403 if (bitmask > 1)
2404 bitmask >>= 1;
2405 else
2406 {
2407 bitmask = 128;
2408 ptr ++;
2409 }
2410 }
2411 break;
2412
2413 case 2 :
2414 dither = Floyd8x8[y & 7];
2415
2416 for (x = xsize ; x > 0; x --, r0 += 4)
2417 {
2418 if ((r0[3] & 63) > dither[x & 7])
f301802f 2419 *ptr ^= (0xc0 & OnPixels[r0[3]]);
ef416fc2 2420 else
f301802f 2421 *ptr ^= (0xc0 & OffPixels[r0[3]]);
ef416fc2 2422
2423 if ((r0[0] & 63) > dither[x & 7])
2424 *ptr ^= (0x30 & OnPixels[r0[0]]);
2425 else
2426 *ptr ^= (0x30 & OffPixels[r0[0]]);
2427
2428 if ((r0[1] & 63) > dither[x & 7])
2429 *ptr ^= (0x0c & OnPixels[r0[1]]);
2430 else
2431 *ptr ^= (0x0c & OffPixels[r0[1]]);
2432
2433 if ((r0[2] & 63) > dither[x & 7])
2434 *ptr++ ^= (0x03 & OnPixels[r0[2]]);
2435 else
2436 *ptr++ ^= (0x03 & OffPixels[r0[2]]);
2437 }
2438 break;
2439
2440 case 4 :
2441 dither = Floyd4x4[y & 3];
2442
2443 for (x = xsize ; x > 0; x --, r0 += 4)
2444 {
2445 if ((r0[3] & 15) > dither[x & 3])
2446 *ptr ^= (0xf0 & OnPixels[r0[3]]);
2447 else
2448 *ptr ^= (0xf0 & OffPixels[r0[3]]);
2449
2450 if ((r0[0] & 15) > dither[x & 3])
2451 *ptr++ ^= (0x0f & OnPixels[r0[0]]);
2452 else
2453 *ptr++ ^= (0x0f & OffPixels[r0[0]]);
2454
2455 if ((r0[1] & 15) > dither[x & 3])
2456 *ptr ^= (0xf0 & OnPixels[r0[1]]);
2457 else
2458 *ptr ^= (0xf0 & OffPixels[r0[1]]);
2459
2460 if ((r0[2] & 15) > dither[x & 3])
2461 *ptr++ ^= (0x0f & OnPixels[r0[2]]);
2462 else
2463 *ptr++ ^= (0x0f & OffPixels[r0[2]]);
2464 }
2465 break;
2466
2467 case 8 :
2468 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2469 {
2470 if (r0[3] == r1[3])
2471 *ptr++ = r0[3];
2472 else
2473 *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2474
2475 if (r0[0] == r1[0])
2476 *ptr++ = r0[0];
2477 else
2478 *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2479
2480 if (r0[1] == r1[1])
2481 *ptr++ = r0[1];
2482 else
2483 *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2484
2485 if (r0[2] == r1[2])
2486 *ptr++ = r0[2];
2487 else
2488 *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2489 }
2490 break;
2491 }
2492 break;
2493
2494 case CUPS_ORDER_BANDED :
2495 kptr = ptr;
2496 cptr = ptr + bandwidth;
2497 mptr = ptr + 2 * bandwidth;
2498 yptr = ptr + 3 * bandwidth;
2499
2500 switch (header->cupsBitsPerColor)
2501 {
2502 case 1 :
2503 bitmask = 0x80 >> (bitoffset & 7);
f301802f 2504 dither = Floyd16x16[y & 15];
ef416fc2 2505
2506 for (x = xsize; x > 0; x --)
2507 {
f301802f 2508 pc = *r0++ > dither[x & 15];
2509 pm = *r0++ > dither[x & 15];
2510 py = *r0++ > dither[x & 15];
2511
2512 if (pc && pm && py)
2513 *kptr ^= bitmask;
2514 else
2515 {
2516 if (pc)
2517 *cptr ^= bitmask;
2518 if (pm)
2519 *mptr ^= bitmask;
2520 if (py)
2521 *yptr ^= bitmask;
2522 }
ef416fc2 2523
2524 if (bitmask > 1)
2525 bitmask >>= 1;
2526 else
2527 {
2528 bitmask = 0x80;
2529 cptr ++;
2530 mptr ++;
2531 yptr ++;
2532 kptr ++;
2533 }
2534 }
2535 break;
2536
2537 case 2 :
f301802f 2538 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 2539 dither = Floyd8x8[y & 7];
2540
2541 for (x = xsize; x > 0; x --)
2542 {
2543 if ((*r0 & 63) > dither[x & 7])
2544 *cptr ^= (bitmask & OnPixels[*r0++]);
2545 else
2546 *cptr ^= (bitmask & OffPixels[*r0++]);
2547
2548 if ((*r0 & 63) > dither[x & 7])
2549 *mptr ^= (bitmask & OnPixels[*r0++]);
2550 else
2551 *mptr ^= (bitmask & OffPixels[*r0++]);
2552
2553 if ((*r0 & 63) > dither[x & 7])
2554 *yptr ^= (bitmask & OnPixels[*r0++]);
2555 else
2556 *yptr ^= (bitmask & OffPixels[*r0++]);
2557
2558 if ((*r0 & 63) > dither[x & 7])
2559 *kptr ^= (bitmask & OnPixels[*r0++]);
2560 else
2561 *kptr ^= (bitmask & OffPixels[*r0++]);
2562
2563 if (bitmask > 3)
2564 bitmask >>= 2;
2565 else
2566 {
f301802f 2567 bitmask = 0xc0;
ef416fc2 2568
2569 cptr ++;
2570 mptr ++;
2571 yptr ++;
2572 kptr ++;
2573 }
2574 }
2575 break;
2576
2577 case 4 :
2578 bitmask = 0xf0 >> (bitoffset & 7);
2579 dither = Floyd4x4[y & 3];
2580
2581 for (x = xsize; x > 0; x --)
2582 {
2583 if ((*r0 & 15) > dither[x & 3])
2584 *cptr ^= (bitmask & OnPixels[*r0++]);
2585 else
2586 *cptr ^= (bitmask & OffPixels[*r0++]);
2587
2588 if ((*r0 & 15) > dither[x & 3])
2589 *mptr ^= (bitmask & OnPixels[*r0++]);
2590 else
2591 *mptr ^= (bitmask & OffPixels[*r0++]);
2592
2593 if ((*r0 & 15) > dither[x & 3])
2594 *yptr ^= (bitmask & OnPixels[*r0++]);
2595 else
2596 *yptr ^= (bitmask & OffPixels[*r0++]);
2597
2598 if ((*r0 & 15) > dither[x & 3])
2599 *kptr ^= (bitmask & OnPixels[*r0++]);
2600 else
2601 *kptr ^= (bitmask & OffPixels[*r0++]);
2602
2603 if (bitmask == 0xf0)
2604 bitmask = 0x0f;
2605 else
2606 {
2607 bitmask = 0xf0;
2608
2609 cptr ++;
2610 mptr ++;
2611 yptr ++;
2612 kptr ++;
2613 }
2614 }
2615 break;
2616
2617 case 8 :
2618 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2619 {
2620 if (r0[0] == r1[0])
2621 *cptr++ = r0[0];
2622 else
2623 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2624
2625 if (r0[1] == r1[1])
2626 *mptr++ = r0[1];
2627 else
2628 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2629
2630 if (r0[2] == r1[2])
2631 *yptr++ = r0[2];
2632 else
2633 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2634
2635 if (r0[3] == r1[3])
2636 *kptr++ = r0[3];
2637 else
2638 *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2639 }
2640 break;
2641 }
2642 break;
2643
2644 case CUPS_ORDER_PLANAR :
2645 switch (header->cupsBitsPerColor)
2646 {
2647 case 1 :
2648 bitmask = 0x80 >> (bitoffset & 7);
f301802f 2649 dither = Floyd16x16[y & 15];
ef416fc2 2650
f301802f 2651 for (x = xsize; x > 0; x --)
ef416fc2 2652 {
f301802f 2653 pc = *r0++ > dither[x & 15];
2654 pm = *r0++ > dither[x & 15];
2655 py = *r0++ > dither[x & 15];
2656
2657 if ((pc && pm && py && z == 0) ||
2658 (pc && z == 1) || (pm && z == 2) || (py && z == 3))
ef416fc2 2659 *ptr ^= bitmask;
2660
2661 if (bitmask > 1)
2662 bitmask >>= 1;
2663 else
2664 {
2665 bitmask = 0x80;
2666 ptr ++;
2667 }
2668 }
2669 break;
2670
2671 case 2 :
f301802f 2672 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 2673 dither = Floyd8x8[y & 7];
2674 if (z == 0)
2675 r0 += 3;
2676 else
2677 r0 += z - 1;
2678
2679 for (x = xsize; x > 0; x --, r0 += 4)
2680 {
2681 if ((*r0 & 63) > dither[x & 7])
2682 *ptr ^= (bitmask & OnPixels[*r0]);
2683 else
2684 *ptr ^= (bitmask & OffPixels[*r0]);
2685
2686 if (bitmask > 3)
2687 bitmask >>= 2;
2688 else
2689 {
f301802f 2690 bitmask = 0xc0;
ef416fc2 2691
2692 ptr ++;
2693 }
2694 }
2695 break;
2696
2697 case 4 :
2698 bitmask = 0xf0 >> (bitoffset & 7);
2699 dither = Floyd4x4[y & 3];
2700 if (z == 0)
2701 r0 += 3;
2702 else
2703 r0 += z - 1;
2704
2705 for (x = xsize; x > 0; x --, r0 += 4)
2706 {
2707 if ((*r0 & 15) > dither[x & 3])
2708 *ptr ^= (bitmask & OnPixels[*r0]);
2709 else
2710 *ptr ^= (bitmask & OffPixels[*r0]);
2711
2712 if (bitmask == 0xf0)
2713 bitmask = 0x0f;
2714 else
2715 {
2716 bitmask = 0xf0;
2717
2718 ptr ++;
2719 }
2720 }
2721 break;
2722
2723 case 8 :
2724 if (z == 0)
2725 {
2726 r0 += 3;
2727 r1 += 3;
2728 }
2729 else
2730 {
2731 r0 += z - 1;
2732 r1 += z - 1;
2733 }
2734
2735 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2736 {
2737 if (*r0 == *r1)
2738 *ptr++ = *r0;
2739 else
2740 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2741 }
2742 break;
2743 }
2744 break;
2745 }
2746}
2747
2748
2749/*
2750 * 'format_KCMYcm()' - Convert image data to KCMYcm.
2751 */
2752
2753static void
a74454a7 2754format_KCMYcm(
2755 cups_page_header2_t *header, /* I - Page header */
2756 unsigned char *row, /* IO - Bitmap data for device */
2757 int y, /* I - Current row */
2758 int z, /* I - Current plane */
2759 int xsize, /* I - Width of image data */
2760 int ysize, /* I - Height of image data */
2761 int yerr0, /* I - Top Y error */
2762 int yerr1, /* I - Bottom Y error */
2763 cups_ib_t *r0, /* I - Primary image data */
2764 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 2765{
a74454a7 2766 int pc, pm, py, pk; /* Cyan, magenta, yellow, and black values */
2767 cups_ib_t *ptr, /* Pointer into row */
2768 *cptr, /* Pointer into cyan */
2769 *mptr, /* Pointer into magenta */
2770 *yptr, /* Pointer into yellow */
2771 *kptr, /* Pointer into black */
2772 *lcptr, /* Pointer into light cyan */
2773 *lmptr, /* Pointer into light magenta */
2774 bitmask; /* Current mask for pixel */
2775 int bitoffset; /* Current offset in line */
2776 int bandwidth; /* Width of a color band */
2777 int x, /* Current X coordinate on page */
2778 *dither; /* Pointer into dither array */
ef416fc2 2779
2780
2781 switch (XPosition)
2782 {
2783 case -1 :
2784 bitoffset = 0;
2785 break;
2786 default :
2787 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2788 break;
2789 case 1 :
2790 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2791 break;
2792 }
2793
f301802f 2794 ptr = row + bitoffset / 8;
2795 bandwidth = header->cupsBytesPerLine / 6;
ef416fc2 2796
2797 switch (header->cupsColorOrder)
2798 {
2799 case CUPS_ORDER_CHUNKED :
f301802f 2800 dither = Floyd16x16[y & 15];
ef416fc2 2801
f301802f 2802 for (x = xsize ; x > 0; x --)
2803 {
2804 pc = *r0++ > dither[x & 15];
2805 pm = *r0++ > dither[x & 15];
2806 py = *r0++ > dither[x & 15];
2807 pk = pc && pm && py;
2808
2809 if (pk)
2810 *ptr++ ^= 32; /* Black */
2811 else if (pc && pm)
2812 *ptr++ ^= 17; /* Blue (cyan + light magenta) */
2813 else if (pc && py)
2814 *ptr++ ^= 6; /* Green (light cyan + yellow) */
2815 else if (pm && py)
2816 *ptr++ ^= 12; /* Red (magenta + yellow) */
2817 else if (pc)
2818 *ptr++ ^= 16;
2819 else if (pm)
2820 *ptr++ ^= 8;
2821 else if (py)
2822 *ptr++ ^= 4;
2823 else
2824 ptr ++;
ef416fc2 2825 }
2826 break;
2827
2828 case CUPS_ORDER_BANDED :
2829 kptr = ptr;
2830 cptr = ptr + bandwidth;
2831 mptr = ptr + 2 * bandwidth;
2832 yptr = ptr + 3 * bandwidth;
2833 lcptr = ptr + 4 * bandwidth;
2834 lmptr = ptr + 5 * bandwidth;
2835
f301802f 2836 bitmask = 0x80 >> (bitoffset & 7);
2837 dither = Floyd16x16[y & 15];
ef416fc2 2838
f301802f 2839 for (x = xsize; x > 0; x --)
2840 {
2841 pc = *r0++ > dither[x & 15];
2842 pm = *r0++ > dither[x & 15];
2843 py = *r0++ > dither[x & 15];
2844 pk = pc && pm && py;
2845
2846 if (pk)
2847 *kptr ^= bitmask; /* Black */
2848 else if (pc && pm)
2849 {
2850 *cptr ^= bitmask; /* Blue (cyan + light magenta) */
2851 *lmptr ^= bitmask;
2852 }
2853 else if (pc && py)
2854 {
2855 *lcptr ^= bitmask; /* Green (light cyan + yellow) */
2856 *yptr ^= bitmask;
2857 }
2858 else if (pm && py)
2859 {
2860 *mptr ^= bitmask; /* Red (magenta + yellow) */
2861 *yptr ^= bitmask;
2862 }
2863 else if (pc)
2864 *cptr ^= bitmask;
2865 else if (pm)
2866 *mptr ^= bitmask;
2867 else if (py)
2868 *yptr ^= bitmask;
ef416fc2 2869
f301802f 2870 if (bitmask > 1)
2871 bitmask >>= 1;
2872 else
2873 {
2874 bitmask = 0x80;
2875 cptr ++;
2876 mptr ++;
2877 yptr ++;
2878 kptr ++;
2879 lcptr ++;
2880 lmptr ++;
2881 }
2882 }
ef416fc2 2883 break;
2884
2885 case CUPS_ORDER_PLANAR :
f301802f 2886 bitmask = 0x80 >> (bitoffset & 7);
2887 dither = Floyd16x16[y & 15];
ef416fc2 2888
f301802f 2889 for (x = xsize; x > 0; x --)
2890 {
2891 pc = *r0++ > dither[x & 15];
2892 pm = *r0++ > dither[x & 15];
2893 py = *r0++ > dither[x & 15];
2894 pk = pc && pm && py;
ef416fc2 2895
f301802f 2896 if (pk && z == 0)
2897 *ptr ^= bitmask;
2898 else if (pc && pm && (z == 1 || z == 5))
2899 *ptr ^= bitmask; /* Blue (cyan + light magenta) */
2900 else if (pc && py && (z == 3 || z == 4))
2901 *ptr ^= bitmask; /* Green (light cyan + yellow) */
2902 else if (pm && py && (z == 2 || z == 3))
2903 *ptr ^= bitmask; /* Red (magenta + yellow) */
2904 else if (pc && z == 1)
2905 *ptr ^= bitmask;
2906 else if (pm && z == 2)
2907 *ptr ^= bitmask;
2908 else if (py && z == 3)
2909 *ptr ^= bitmask;
ef416fc2 2910
f301802f 2911 if (bitmask > 1)
2912 bitmask >>= 1;
2913 else
2914 {
2915 bitmask = 0x80;
2916 ptr ++;
2917 }
2918 }
ef416fc2 2919 break;
2920 }
2921}
2922
2923
2924/*
2925 * 'format_RGBA()' - Convert image data to RGBA/RGBW.
2926 */
2927
2928static void
a74454a7 2929format_RGBA(cups_page_header2_t *header,/* I - Page header */
ef416fc2 2930 unsigned char *row, /* IO - Bitmap data for device */
2931 int y, /* I - Current row */
2932 int z, /* I - Current plane */
2933 int xsize, /* I - Width of image data */
2934 int ysize, /* I - Height of image data */
2935 int yerr0, /* I - Top Y error */
2936 int yerr1, /* I - Bottom Y error */
a74454a7 2937 cups_ib_t *r0, /* I - Primary image data */
2938 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 2939{
a74454a7 2940 cups_ib_t *ptr, /* Pointer into row */
2941 *cptr, /* Pointer into cyan */
2942 *mptr, /* Pointer into magenta */
2943 *yptr, /* Pointer into yellow */
2944 bitmask; /* Current mask for pixel */
2945 int bitoffset; /* Current offset in line */
2946 int bandwidth; /* Width of a color band */
2947 int x, /* Current X coordinate on page */
2948 *dither; /* Pointer into dither array */
ef416fc2 2949
2950
2951 switch (XPosition)
2952 {
2953 case -1 :
2954 bitoffset = 0;
2955 break;
2956 default :
2957 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2958 break;
2959 case 1 :
2960 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2961 break;
2962 }
2963
2964 ptr = row + bitoffset / 8;
2965 bandwidth = header->cupsBytesPerLine / 4;
2966
2967 switch (header->cupsColorOrder)
2968 {
2969 case CUPS_ORDER_CHUNKED :
2970 switch (header->cupsBitsPerColor)
2971 {
2972 case 1 :
2973 bitmask = 128 >> (bitoffset & 7);
f301802f 2974 dither = Floyd16x16[y & 15];
ef416fc2 2975
2976 for (x = xsize ; x > 0; x --)
2977 {
2978 if (*r0++ > dither[x & 15])
2979 *ptr ^= bitmask;
2980 bitmask >>= 1;
2981
2982 if (*r0++ > dither[x & 15])
2983 *ptr ^= bitmask;
2984 bitmask >>= 1;
2985
2986 if (*r0++ > dither[x & 15])
2987 *ptr ^= bitmask;
2988
2989 if (bitmask > 2)
ef416fc2 2990 bitmask >>= 2;
ef416fc2 2991 else
2992 {
2993 bitmask = 128;
f301802f 2994 ptr ++;
ef416fc2 2995 }
2996 }
2997 break;
2998
2999 case 2 :
3000 dither = Floyd8x8[y & 7];
3001
3002 for (x = xsize ; x > 0; x --, r0 += 3)
3003 {
3004 if ((r0[0] & 63) > dither[x & 7])
f301802f 3005 *ptr ^= (0xc0 & OnPixels[r0[0]]);
ef416fc2 3006 else
f301802f 3007 *ptr ^= (0xc0 & OffPixels[r0[0]]);
ef416fc2 3008
3009 if ((r0[1] & 63) > dither[x & 7])
3010 *ptr ^= (0x30 & OnPixels[r0[1]]);
3011 else
3012 *ptr ^= (0x30 & OffPixels[r0[1]]);
3013
3014 if ((r0[2] & 63) > dither[x & 7])
3015 *ptr ^= (0x0c & OnPixels[r0[2]]);
3016 else
3017 *ptr ^= (0x0c & OffPixels[r0[2]]);
3018
f301802f 3019 ptr ++;
ef416fc2 3020 }
3021 break;
3022
3023 case 4 :
3024 dither = Floyd4x4[y & 3];
3025
3026 for (x = xsize ; x > 0; x --, r0 += 3)
3027 {
3028 if ((r0[0] & 15) > dither[x & 3])
3029 *ptr ^= (0xf0 & OnPixels[r0[0]]);
3030 else
3031 *ptr ^= (0xf0 & OffPixels[r0[0]]);
3032
3033 if ((r0[1] & 15) > dither[x & 3])
3034 *ptr++ ^= (0x0f & OnPixels[r0[1]]);
3035 else
3036 *ptr++ ^= (0x0f & OffPixels[r0[1]]);
3037
3038 if ((r0[2] & 15) > dither[x & 3])
3039 *ptr ^= (0xf0 & OnPixels[r0[2]]);
3040 else
3041 *ptr ^= (0xf0 & OffPixels[r0[2]]);
3042
f301802f 3043 ptr ++;
ef416fc2 3044 }
3045 break;
3046
3047 case 8 :
3048 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3049 {
3050 if (r0[0] == r1[0])
3051 *ptr++ = r0[0];
3052 else
3053 *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3054
3055 if (r0[1] == r1[1])
3056 *ptr++ = r0[1];
3057 else
3058 *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3059
3060 if (r0[2] == r1[2])
3061 *ptr++ = r0[2];
3062 else
3063 *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3064
f301802f 3065 ptr ++;
ef416fc2 3066 }
3067 break;
3068 }
3069 break;
3070
3071 case CUPS_ORDER_BANDED :
3072 cptr = ptr;
3073 mptr = ptr + bandwidth;
3074 yptr = ptr + 2 * bandwidth;
3075
3076 memset(ptr + 3 * bandwidth, 255, bandwidth);
3077
3078 switch (header->cupsBitsPerColor)
3079 {
3080 case 1 :
3081 bitmask = 0x80 >> (bitoffset & 7);
f301802f 3082 dither = Floyd16x16[y & 15];
ef416fc2 3083
3084 for (x = xsize; x > 0; x --)
3085 {
3086 if (*r0++ > dither[x & 15])
3087 *cptr ^= bitmask;
3088 if (*r0++ > dither[x & 15])
3089 *mptr ^= bitmask;
3090 if (*r0++ > dither[x & 15])
3091 *yptr ^= bitmask;
3092
3093 if (bitmask > 1)
3094 bitmask >>= 1;
3095 else
3096 {
3097 bitmask = 0x80;
3098 cptr ++;
3099 mptr ++;
3100 yptr ++;
3101 }
3102 }
3103 break;
3104
3105 case 2 :
f301802f 3106 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 3107 dither = Floyd8x8[y & 7];
3108
3109 for (x = xsize; x > 0; x --)
3110 {
3111 if ((*r0 & 63) > dither[x & 7])
3112 *cptr ^= (bitmask & OnPixels[*r0++]);
3113 else
3114 *cptr ^= (bitmask & OffPixels[*r0++]);
3115
3116 if ((*r0 & 63) > dither[x & 7])
3117 *mptr ^= (bitmask & OnPixels[*r0++]);
3118 else
3119 *mptr ^= (bitmask & OffPixels[*r0++]);
3120
3121 if ((*r0 & 63) > dither[x & 7])
3122 *yptr ^= (bitmask & OnPixels[*r0++]);
3123 else
3124 *yptr ^= (bitmask & OffPixels[*r0++]);
3125
3126 if (bitmask > 3)
3127 bitmask >>= 2;
3128 else
3129 {
f301802f 3130 bitmask = 0xc0;
ef416fc2 3131
3132 cptr ++;
3133 mptr ++;
3134 yptr ++;
3135 }
3136 }
3137 break;
3138
3139 case 4 :
3140 bitmask = 0xf0 >> (bitoffset & 7);
3141 dither = Floyd4x4[y & 3];
3142
3143 for (x = xsize; x > 0; x --)
3144 {
3145 if ((*r0 & 15) > dither[x & 3])
3146 *cptr ^= (bitmask & OnPixels[*r0++]);
3147 else
3148 *cptr ^= (bitmask & OffPixels[*r0++]);
3149
3150 if ((*r0 & 15) > dither[x & 3])
3151 *mptr ^= (bitmask & OnPixels[*r0++]);
3152 else
3153 *mptr ^= (bitmask & OffPixels[*r0++]);
3154
3155 if ((*r0 & 15) > dither[x & 3])
3156 *yptr ^= (bitmask & OnPixels[*r0++]);
3157 else
3158 *yptr ^= (bitmask & OffPixels[*r0++]);
3159
3160 if (bitmask == 0xf0)
3161 bitmask = 0x0f;
3162 else
3163 {
3164 bitmask = 0xf0;
3165
3166 cptr ++;
3167 mptr ++;
3168 yptr ++;
3169 }
3170 }
3171 break;
3172
3173 case 8 :
3174 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3175 {
3176 if (r0[0] == r1[0])
3177 *cptr++ = r0[0];
3178 else
3179 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3180
3181 if (r0[1] == r1[1])
3182 *mptr++ = r0[1];
3183 else
3184 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3185
3186 if (r0[2] == r1[2])
3187 *yptr++ = r0[2];
3188 else
3189 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3190 }
3191 break;
3192 }
3193 break;
3194
3195 case CUPS_ORDER_PLANAR :
3196 if (z == 3)
3197 {
3198 memset(row, 255, header->cupsBytesPerLine);
3199 break;
3200 }
3201
3202 switch (header->cupsBitsPerColor)
3203 {
3204 case 1 :
3205 bitmask = 0x80 >> (bitoffset & 7);
f301802f 3206 dither = Floyd16x16[y & 15];
ef416fc2 3207
3208 switch (z)
3209 {
3210 case 0 :
3211 for (x = xsize; x > 0; x --, r0 += 3)
3212 {
3213 if (r0[0] > dither[x & 15])
3214 *ptr ^= bitmask;
3215
3216 if (bitmask > 1)
3217 bitmask >>= 1;
3218 else
3219 {
3220 bitmask = 0x80;
3221 ptr ++;
3222 }
3223 }
3224 break;
3225
3226 case 1 :
3227 for (x = xsize; x > 0; x --, r0 += 3)
3228 {
3229 if (r0[1] > dither[x & 15])
3230 *ptr ^= bitmask;
3231
3232 if (bitmask > 1)
3233 bitmask >>= 1;
3234 else
3235 {
3236 bitmask = 0x80;
3237 ptr ++;
3238 }
3239 }
3240 break;
3241
3242 case 2 :
3243 for (x = xsize; x > 0; x --, r0 += 3)
3244 {
3245 if (r0[2] > dither[x & 15])
3246 *ptr ^= bitmask;
3247
3248 if (bitmask > 1)
3249 bitmask >>= 1;
3250 else
3251 {
3252 bitmask = 0x80;
3253 ptr ++;
3254 }
3255 }
3256 break;
3257 }
3258 break;
3259
3260 case 2 :
f301802f 3261 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 3262 dither = Floyd8x8[y & 7];
3263 r0 += z;
3264
3265 for (x = xsize; x > 0; x --, r0 += 3)
3266 {
3267 if ((*r0 & 63) > dither[x & 7])
3268 *ptr ^= (bitmask & OnPixels[*r0]);
3269 else
3270 *ptr ^= (bitmask & OffPixels[*r0]);
3271
3272 if (bitmask > 3)
3273 bitmask >>= 2;
3274 else
3275 {
f301802f 3276 bitmask = 0xc0;
ef416fc2 3277
3278 ptr ++;
3279 }
3280 }
3281 break;
3282
3283 case 4 :
3284 bitmask = 0xf0 >> (bitoffset & 7);
3285 dither = Floyd4x4[y & 3];
3286 r0 += z;
3287
3288 for (x = xsize; x > 0; x --, r0 += 3)
3289 {
3290 if ((*r0 & 15) > dither[x & 3])
3291 *ptr ^= (bitmask & OnPixels[*r0]);
3292 else
3293 *ptr ^= (bitmask & OffPixels[*r0]);
3294
3295 if (bitmask == 0xf0)
3296 bitmask = 0x0f;
3297 else
3298 {
3299 bitmask = 0xf0;
3300
3301 ptr ++;
3302 }
3303 }
3304 break;
3305
3306 case 8 :
3307 r0 += z;
3308 r1 += z;
3309
3310 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3311 {
3312 if (*r0 == *r1)
3313 *ptr++ = *r0;
3314 else
3315 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3316 }
3317 break;
3318 }
3319 break;
3320 }
3321}
3322
3323
3324/*
3325 * 'format_W()' - Convert image data to luminance.
3326 */
3327
3328static void
3329format_W(cups_page_header2_t *header, /* I - Page header */
3330 unsigned char *row, /* IO - Bitmap data for device */
3331 int y, /* I - Current row */
3332 int z, /* I - Current plane */
3333 int xsize, /* I - Width of image data */
3334 int ysize, /* I - Height of image data */
3335 int yerr0, /* I - Top Y error */
3336 int yerr1, /* I - Bottom Y error */
a74454a7 3337 cups_ib_t *r0, /* I - Primary image data */
3338 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 3339{
a74454a7 3340 cups_ib_t *ptr, /* Pointer into row */
3341 bitmask; /* Current mask for pixel */
3342 int bitoffset; /* Current offset in line */
3343 int x, /* Current X coordinate on page */
3344 *dither; /* Pointer into dither array */
ef416fc2 3345
3346
3347 (void)z;
3348
3349 switch (XPosition)
3350 {
3351 case -1 :
3352 bitoffset = 0;
3353 break;
3354 default :
3355 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3356 break;
3357 case 1 :
3358 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3359 break;
3360 }
3361
3362 ptr = row + bitoffset / 8;
3363
3364 switch (header->cupsBitsPerColor)
3365 {
3366 case 1 :
3367 bitmask = 0x80 >> (bitoffset & 7);
f301802f 3368 dither = Floyd16x16[y & 15];
ef416fc2 3369
3370 for (x = xsize; x > 0; x --)
3371 {
3372 if (*r0++ > dither[x & 15])
3373 *ptr ^= bitmask;
3374
3375 if (bitmask > 1)
3376 bitmask >>= 1;
3377 else
3378 {
3379 bitmask = 0x80;
3380 ptr ++;
3381 }
3382 }
3383 break;
3384
3385 case 2 :
f301802f 3386 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 3387 dither = Floyd8x8[y & 7];
3388
3389 for (x = xsize; x > 0; x --)
3390 {
3391 if ((*r0 & 63) > dither[x & 7])
3392 *ptr ^= (bitmask & OnPixels[*r0++]);
3393 else
3394 *ptr ^= (bitmask & OffPixels[*r0++]);
3395
3396 if (bitmask > 3)
3397 bitmask >>= 2;
3398 else
3399 {
f301802f 3400 bitmask = 0xc0;
ef416fc2 3401
3402 ptr ++;
3403 }
3404 }
3405 break;
3406
3407 case 4 :
3408 bitmask = 0xf0 >> (bitoffset & 7);
3409 dither = Floyd4x4[y & 3];
3410
3411 for (x = xsize; x > 0; x --)
3412 {
3413 if ((*r0 & 15) > dither[x & 3])
3414 *ptr ^= (bitmask & OnPixels[*r0++]);
3415 else
3416 *ptr ^= (bitmask & OffPixels[*r0++]);
3417
3418 if (bitmask == 0xf0)
3419 bitmask = 0x0f;
3420 else
3421 {
3422 bitmask = 0xf0;
3423
3424 ptr ++;
3425 }
3426 }
3427 break;
3428
3429 case 8 :
3430 for (x = xsize; x > 0; x --, r0 ++, r1 ++)
3431 {
3432 if (*r0 == *r1)
3433 *ptr++ = *r0;
3434 else
3435 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3436 }
3437 break;
3438 }
3439}
3440
3441
3442/*
3443 * 'format_YMC()' - Convert image data to YMC.
3444 */
3445
3446static void
3447format_YMC(cups_page_header2_t *header, /* I - Page header */
3448 unsigned char *row, /* IO - Bitmap data for device */
3449 int y, /* I - Current row */
3450 int z, /* I - Current plane */
3451 int xsize, /* I - Width of image data */
3452 int ysize, /* I - Height of image data */
3453 int yerr0, /* I - Top Y error */
3454 int yerr1, /* I - Bottom Y error */
a74454a7 3455 cups_ib_t *r0, /* I - Primary image data */
3456 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 3457{
a74454a7 3458 cups_ib_t *ptr, /* Pointer into row */
3459 *cptr, /* Pointer into cyan */
3460 *mptr, /* Pointer into magenta */
3461 *yptr, /* Pointer into yellow */
3462 bitmask; /* Current mask for pixel */
3463 int bitoffset; /* Current offset in line */
3464 int bandwidth; /* Width of a color band */
3465 int x, /* Current X coordinate on page */
3466 *dither; /* Pointer into dither array */
ef416fc2 3467
3468
3469 switch (XPosition)
3470 {
3471 case -1 :
3472 bitoffset = 0;
3473 break;
3474 default :
3475 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3476 break;
3477 case 1 :
3478 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3479 break;
3480 }
3481
3482 ptr = row + bitoffset / 8;
3483 bandwidth = header->cupsBytesPerLine / 3;
3484
3485 switch (header->cupsColorOrder)
3486 {
3487 case CUPS_ORDER_CHUNKED :
3488 switch (header->cupsBitsPerColor)
3489 {
3490 case 1 :
3491 bitmask = 64 >> (bitoffset & 7);
f301802f 3492 dither = Floyd16x16[y & 15];
ef416fc2 3493
3494 for (x = xsize ; x > 0; x --, r0 += 3)
3495 {
3496 if (r0[2] > dither[x & 15])
3497 *ptr ^= bitmask;
3498 bitmask >>= 1;
3499
3500 if (r0[1] > dither[x & 15])
3501 *ptr ^= bitmask;
3502 bitmask >>= 1;
3503
3504 if (r0[0] > dither[x & 15])
3505 *ptr ^= bitmask;
3506
3507 if (bitmask > 1)
3508 bitmask >>= 2;
3509 else
3510 {
3511 bitmask = 64;
3512 ptr ++;
3513 }
3514 }
3515 break;
3516
3517 case 2 :
3518 dither = Floyd8x8[y & 7];
3519
3520 for (x = xsize ; x > 0; x --, r0 += 3)
3521 {
3522 if ((r0[2] & 63) > dither[x & 7])
3523 *ptr ^= (0x30 & OnPixels[r0[2]]);
3524 else
3525 *ptr ^= (0x30 & OffPixels[r0[2]]);
3526
3527 if ((r0[1] & 63) > dither[x & 7])
3528 *ptr ^= (0x0c & OnPixels[r0[1]]);
3529 else
3530 *ptr ^= (0x0c & OffPixels[r0[1]]);
3531
3532 if ((r0[0] & 63) > dither[x & 7])
3533 *ptr++ ^= (0x03 & OnPixels[r0[0]]);
3534 else
3535 *ptr++ ^= (0x03 & OffPixels[r0[0]]);
3536 }
3537 break;
3538
3539 case 4 :
3540 dither = Floyd4x4[y & 3];
3541
3542 for (x = xsize ; x > 0; x --, r0 += 3)
3543 {
3544 if ((r0[2] & 15) > dither[x & 3])
3545 *ptr++ ^= (0x0f & OnPixels[r0[2]]);
3546 else
3547 *ptr++ ^= (0x0f & OffPixels[r0[2]]);
3548
3549 if ((r0[1] & 15) > dither[x & 3])
3550 *ptr ^= (0xf0 & OnPixels[r0[1]]);
3551 else
3552 *ptr ^= (0xf0 & OffPixels[r0[1]]);
3553
3554 if ((r0[0] & 15) > dither[x & 3])
3555 *ptr++ ^= (0x0f & OnPixels[r0[0]]);
3556 else
3557 *ptr++ ^= (0x0f & OffPixels[r0[0]]);
3558 }
3559 break;
3560
3561 case 8 :
3562 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3563 {
3564 if (r0[2] == r1[2])
3565 *ptr++ = r0[2];
3566 else
3567 *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3568
3569 if (r0[1] == r1[1])
3570 *ptr++ = r0[1];
3571 else
3572 *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3573
3574 if (r0[0] == r1[0])
3575 *ptr++ = r0[0];
3576 else
3577 *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3578 }
3579 break;
3580 }
3581 break;
3582
3583 case CUPS_ORDER_BANDED :
3584 yptr = ptr;
3585 mptr = ptr + bandwidth;
3586 cptr = ptr + 2 * bandwidth;
3587
3588 switch (header->cupsBitsPerColor)
3589 {
3590 case 1 :
3591 bitmask = 0x80 >> (bitoffset & 7);
f301802f 3592 dither = Floyd16x16[y & 15];
ef416fc2 3593
3594 for (x = xsize; x > 0; x --)
3595 {
3596 if (*r0++ > dither[x & 15])
3597 *cptr ^= bitmask;
3598 if (*r0++ > dither[x & 15])
3599 *mptr ^= bitmask;
3600 if (*r0++ > dither[x & 15])
3601 *yptr ^= bitmask;
3602
3603 if (bitmask > 1)
3604 bitmask >>= 1;
3605 else
3606 {
3607 bitmask = 0x80;
3608 cptr ++;
3609 mptr ++;
3610 yptr ++;
3611 }
3612 }
3613 break;
3614
3615 case 2 :
f301802f 3616 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 3617 dither = Floyd8x8[y & 7];
3618
3619 for (x = xsize; x > 0; x --)
3620 {
3621 if ((*r0 & 63) > dither[x & 7])
3622 *cptr ^= (bitmask & OnPixels[*r0++]);
3623 else
3624 *cptr ^= (bitmask & OffPixels[*r0++]);
3625
3626 if ((*r0 & 63) > dither[x & 7])
3627 *mptr ^= (bitmask & OnPixels[*r0++]);
3628 else
3629 *mptr ^= (bitmask & OffPixels[*r0++]);
3630
3631 if ((*r0 & 63) > dither[x & 7])
3632 *yptr ^= (bitmask & OnPixels[*r0++]);
3633 else
3634 *yptr ^= (bitmask & OffPixels[*r0++]);
3635
3636 if (bitmask > 3)
3637 bitmask >>= 2;
3638 else
3639 {
f301802f 3640 bitmask = 0xc0;
ef416fc2 3641
3642 cptr ++;
3643 mptr ++;
3644 yptr ++;
3645 }
3646 }
3647 break;
3648
3649 case 4 :
3650 bitmask = 0xf0 >> (bitoffset & 7);
3651 dither = Floyd4x4[y & 3];
3652
3653 for (x = xsize; x > 0; x --)
3654 {
3655 if ((*r0 & 15) > dither[x & 3])
3656 *cptr ^= (bitmask & OnPixels[*r0++]);
3657 else
3658 *cptr ^= (bitmask & OffPixels[*r0++]);
3659
3660 if ((*r0 & 15) > dither[x & 3])
3661 *mptr ^= (bitmask & OnPixels[*r0++]);
3662 else
3663 *mptr ^= (bitmask & OffPixels[*r0++]);
3664
3665 if ((*r0 & 15) > dither[x & 3])
3666 *yptr ^= (bitmask & OnPixels[*r0++]);
3667 else
3668 *yptr ^= (bitmask & OffPixels[*r0++]);
3669
3670 if (bitmask == 0xf0)
3671 bitmask = 0x0f;
3672 else
3673 {
3674 bitmask = 0xf0;
3675
3676 cptr ++;
3677 mptr ++;
3678 yptr ++;
3679 }
3680 }
3681 break;
3682
3683 case 8 :
3684 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3685 {
3686 if (r0[0] == r1[0])
3687 *cptr++ = r0[0];
3688 else
3689 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3690
3691 if (r0[1] == r1[1])
3692 *mptr++ = r0[1];
3693 else
3694 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3695
3696 if (r0[2] == r1[2])
3697 *yptr++ = r0[2];
3698 else
3699 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3700 }
3701 break;
3702 }
3703 break;
3704
3705 case CUPS_ORDER_PLANAR :
3706 switch (header->cupsBitsPerColor)
3707 {
3708 case 1 :
3709 bitmask = 0x80 >> (bitoffset & 7);
f301802f 3710 dither = Floyd16x16[y & 15];
ef416fc2 3711
3712 switch (z)
3713 {
3714 case 2 :
3715 for (x = xsize; x > 0; x --, r0 += 3)
3716 {
3717 if (r0[0] > dither[x & 15])
3718 *ptr ^= bitmask;
3719
3720 if (bitmask > 1)
3721 bitmask >>= 1;
3722 else
3723 {
3724 bitmask = 0x80;
3725 ptr ++;
3726 }
3727 }
3728 break;
3729
3730 case 1 :
3731 for (x = xsize; x > 0; x --, r0 += 3)
3732 {
3733 if (r0[1] > dither[x & 15])
3734 *ptr ^= bitmask;
3735
3736 if (bitmask > 1)
3737 bitmask >>= 1;
3738 else
3739 {
3740 bitmask = 0x80;
3741 ptr ++;
3742 }
3743 }
3744 break;
3745
3746 case 0 :
3747 for (x = xsize; x > 0; x --, r0 += 3)
3748 {
3749 if (r0[2] > dither[x & 15])
3750 *ptr ^= bitmask;
3751
3752 if (bitmask > 1)
3753 bitmask >>= 1;
3754 else
3755 {
3756 bitmask = 0x80;
3757 ptr ++;
3758 }
3759 }
3760 break;
3761 }
3762 break;
3763
3764 case 2 :
f301802f 3765 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 3766 dither = Floyd8x8[y & 7];
3767 z = 2 - z;
3768 r0 += z;
3769
3770 for (x = xsize; x > 0; x --, r0 += 3)
3771 {
3772 if ((*r0 & 63) > dither[x & 7])
3773 *ptr ^= (bitmask & OnPixels[*r0]);
3774 else
3775 *ptr ^= (bitmask & OffPixels[*r0]);
3776
3777 if (bitmask > 3)
3778 bitmask >>= 2;
3779 else
3780 {
f301802f 3781 bitmask = 0xc0;
ef416fc2 3782
3783 ptr ++;
3784 }
3785 }
3786 break;
3787
3788 case 4 :
3789 bitmask = 0xf0 >> (bitoffset & 7);
3790 dither = Floyd4x4[y & 3];
3791 z = 2 - z;
3792 r0 += z;
3793
3794 for (x = xsize; x > 0; x --, r0 += 3)
3795 {
3796 if ((*r0 & 15) > dither[x & 3])
3797 *ptr ^= (bitmask & OnPixels[*r0]);
3798 else
3799 *ptr ^= (bitmask & OffPixels[*r0]);
3800
3801 if (bitmask == 0xf0)
3802 bitmask = 0x0f;
3803 else
3804 {
3805 bitmask = 0xf0;
3806
3807 ptr ++;
3808 }
3809 }
3810 break;
3811
3812 case 8 :
3813 z = 2 - z;
3814 r0 += z;
3815 r1 += z;
3816
3817 for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
3818 {
3819 if (*r0 == *r1)
3820 *ptr++ = *r0;
3821 else
3822 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3823 }
3824 break;
3825 }
3826 break;
3827 }
3828}
3829
3830
3831/*
3832 * 'format_YMCK()' - Convert image data to YMCK.
3833 */
3834
3835static void
a74454a7 3836format_YMCK(cups_page_header2_t *header,/* I - Page header */
ef416fc2 3837 unsigned char *row, /* IO - Bitmap data for device */
3838 int y, /* I - Current row */
3839 int z, /* I - Current plane */
3840 int xsize, /* I - Width of image data */
3841 int ysize, /* I - Height of image data */
3842 int yerr0, /* I - Top Y error */
3843 int yerr1, /* I - Bottom Y error */
a74454a7 3844 cups_ib_t *r0, /* I - Primary image data */
3845 cups_ib_t *r1) /* I - Image data for interpolation */
ef416fc2 3846{
a74454a7 3847 cups_ib_t *ptr, /* Pointer into row */
3848 *cptr, /* Pointer into cyan */
3849 *mptr, /* Pointer into magenta */
3850 *yptr, /* Pointer into yellow */
3851 *kptr, /* Pointer into black */
3852 bitmask; /* Current mask for pixel */
3853 int bitoffset; /* Current offset in line */
3854 int bandwidth; /* Width of a color band */
3855 int x, /* Current X coordinate on page */
3856 *dither; /* Pointer into dither array */
f301802f 3857 int pc, pm, py; /* CMY pixels */
ef416fc2 3858
3859
3860 switch (XPosition)
3861 {
3862 case -1 :
3863 bitoffset = 0;
3864 break;
3865 default :
3866 bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3867 break;
3868 case 1 :
3869 bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3870 break;
3871 }
3872
3873 ptr = row + bitoffset / 8;
3874 bandwidth = header->cupsBytesPerLine / 4;
3875
3876 switch (header->cupsColorOrder)
3877 {
3878 case CUPS_ORDER_CHUNKED :
3879 switch (header->cupsBitsPerColor)
3880 {
3881 case 1 :
3882 bitmask = 128 >> (bitoffset & 7);
f301802f 3883 dither = Floyd16x16[y & 15];
ef416fc2 3884
f301802f 3885 for (x = xsize ; x > 0; x --)
ef416fc2 3886 {
f301802f 3887 pc = *r0++ > dither[x & 15];
3888 pm = *r0++ > dither[x & 15];
3889 py = *r0++ > dither[x & 15];
ef416fc2 3890
f301802f 3891 if (pc && pm && py)
3892 {
3893 bitmask >>= 3;
ef416fc2 3894 *ptr ^= bitmask;
f301802f 3895 }
3896 else
3897 {
3898 if (py)
3899 *ptr ^= bitmask;
3900 bitmask >>= 1;
ef416fc2 3901
f301802f 3902 if (pm)
3903 *ptr ^= bitmask;
3904 bitmask >>= 1;
ef416fc2 3905
f301802f 3906 if (pc)
3907 *ptr ^= bitmask;
3908 bitmask >>= 1;
3909 }
ef416fc2 3910
3911 if (bitmask > 1)
3912 bitmask >>= 1;
3913 else
3914 {
3915 bitmask = 128;
3916
3917 ptr ++;
3918 }
3919 }
3920 break;
3921
3922 case 2 :
3923 dither = Floyd8x8[y & 7];
3924
3925 for (x = xsize ; x > 0; x --, r0 += 4)
3926 {
3927 if ((r0[2] & 63) > dither[x & 7])
f301802f 3928 *ptr ^= (0xc0 & OnPixels[r0[2]]);
ef416fc2 3929 else
f301802f 3930 *ptr ^= (0xc0 & OffPixels[r0[2]]);
ef416fc2 3931
3932 if ((r0[1] & 63) > dither[x & 7])
3933 *ptr ^= (0x30 & OnPixels[r0[1]]);
3934 else
3935 *ptr ^= (0x30 & OffPixels[r0[1]]);
3936
3937 if ((r0[0] & 63) > dither[x & 7])
3938 *ptr ^= (0x0c & OnPixels[r0[0]]);
3939 else
3940 *ptr ^= (0x0c & OffPixels[r0[0]]);
3941
3942 if ((r0[3] & 63) > dither[x & 7])
3943 *ptr++ ^= (0x03 & OnPixels[r0[3]]);
3944 else
3945 *ptr++ ^= (0x03 & OffPixels[r0[3]]);
3946 }
3947 break;
3948
3949 case 4 :
3950 dither = Floyd4x4[y & 3];
3951
3952 for (x = xsize ; x > 0; x --, r0 += 4)
3953 {
3954 if ((r0[2] & 15) > dither[x & 3])
3955 *ptr ^= (0xf0 & OnPixels[r0[2]]);
3956 else
3957 *ptr ^= (0xf0 & OffPixels[r0[2]]);
3958
3959 if ((r0[1] & 15) > dither[x & 3])
3960 *ptr++ ^= (0x0f & OnPixels[r0[1]]);
3961 else
3962 *ptr++ ^= (0x0f & OffPixels[r0[1]]);
3963
3964 if ((r0[0] & 15) > dither[x & 3])
3965 *ptr ^= (0xf0 & OnPixels[r0[0]]);
3966 else
3967 *ptr ^= (0xf0 & OffPixels[r0[0]]);
3968
3969 if ((r0[3] & 15) > dither[x & 3])
3970 *ptr++ ^= (0x0f & OnPixels[r0[3]]);
3971 else
3972 *ptr++ ^= (0x0f & OffPixels[r0[3]]);
3973 }
3974 break;
3975
3976 case 8 :
3977 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
3978 {
3979 if (r0[2] == r1[2])
3980 *ptr++ = r0[2];
3981 else
3982 *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3983
3984 if (r0[1] == r1[1])
3985 *ptr++ = r0[1];
3986 else
3987 *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3988
3989 if (r0[0] == r1[0])
3990 *ptr++ = r0[0];
3991 else
3992 *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3993
3994 if (r0[3] == r1[3])
3995 *ptr++ = r0[3];
3996 else
3997 *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
3998 }
3999 break;
4000 }
4001 break;
4002
4003 case CUPS_ORDER_BANDED :
4004 yptr = ptr;
4005 mptr = ptr + bandwidth;
4006 cptr = ptr + 2 * bandwidth;
4007 kptr = ptr + 3 * bandwidth;
4008
4009 switch (header->cupsBitsPerColor)
4010 {
4011 case 1 :
4012 bitmask = 0x80 >> (bitoffset & 7);
f301802f 4013 dither = Floyd16x16[y & 15];
ef416fc2 4014
4015 for (x = xsize; x > 0; x --)
4016 {
f301802f 4017 pc = *r0++ > dither[x & 15];
4018 pm = *r0++ > dither[x & 15];
4019 py = *r0++ > dither[x & 15];
4020
4021 if (pc && pm && py)
4022 *kptr ^= bitmask;
4023 else
4024 {
4025 if (pc)
4026 *cptr ^= bitmask;
4027 if (pm)
4028 *mptr ^= bitmask;
4029 if (py)
4030 *yptr ^= bitmask;
4031 }
ef416fc2 4032
4033 if (bitmask > 1)
4034 bitmask >>= 1;
4035 else
4036 {
4037 bitmask = 0x80;
4038
4039 cptr ++;
4040 mptr ++;
4041 yptr ++;
4042 kptr ++;
4043 }
4044 }
4045 break;
4046
4047 case 2 :
f301802f 4048 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 4049 dither = Floyd8x8[y & 7];
4050
4051 for (x = xsize; x > 0; x --)
4052 {
4053 if ((*r0 & 63) > dither[x & 7])
4054 *cptr ^= (bitmask & OnPixels[*r0++]);
4055 else
4056 *cptr ^= (bitmask & OffPixels[*r0++]);
4057
4058 if ((*r0 & 63) > dither[x & 7])
4059 *mptr ^= (bitmask & OnPixels[*r0++]);
4060 else
4061 *mptr ^= (bitmask & OffPixels[*r0++]);
4062
4063 if ((*r0 & 63) > dither[x & 7])
4064 *yptr ^= (bitmask & OnPixels[*r0++]);
4065 else
4066 *yptr ^= (bitmask & OffPixels[*r0++]);
4067
4068 if ((*r0 & 63) > dither[x & 7])
4069 *kptr ^= (bitmask & OnPixels[*r0++]);
4070 else
4071 *kptr ^= (bitmask & OffPixels[*r0++]);
4072
4073 if (bitmask > 3)
4074 bitmask >>= 2;
4075 else
4076 {
f301802f 4077 bitmask = 0xc0;
ef416fc2 4078
4079 cptr ++;
4080 mptr ++;
4081 yptr ++;
4082 kptr ++;
4083 }
4084 }
4085 break;
4086
4087 case 4 :
4088 bitmask = 0xf0 >> (bitoffset & 7);
4089 dither = Floyd4x4[y & 3];
4090
4091 for (x = xsize; x > 0; x --)
4092 {
4093 if ((*r0 & 15) > dither[x & 3])
4094 *cptr ^= (bitmask & OnPixels[*r0++]);
4095 else
4096 *cptr ^= (bitmask & OffPixels[*r0++]);
4097
4098 if ((*r0 & 15) > dither[x & 3])
4099 *mptr ^= (bitmask & OnPixels[*r0++]);
4100 else
4101 *mptr ^= (bitmask & OffPixels[*r0++]);
4102
4103 if ((*r0 & 15) > dither[x & 3])
4104 *yptr ^= (bitmask & OnPixels[*r0++]);
4105 else
4106 *yptr ^= (bitmask & OffPixels[*r0++]);
4107
4108 if ((*r0 & 15) > dither[x & 3])
4109 *kptr ^= (bitmask & OnPixels[*r0++]);
4110 else
4111 *kptr ^= (bitmask & OffPixels[*r0++]);
4112
4113 if (bitmask == 0xf0)
4114 bitmask = 0x0f;
4115 else
4116 {
4117 bitmask = 0xf0;
4118
4119 cptr ++;
4120 mptr ++;
4121 yptr ++;
4122 kptr ++;
4123 }
4124 }
4125 break;
4126
4127 case 8 :
4128 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
4129 {
4130 if (r0[0] == r1[0])
4131 *cptr++ = r0[0];
4132 else
4133 *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
4134
4135 if (r0[1] == r1[1])
4136 *mptr++ = r0[1];
4137 else
4138 *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
4139
4140 if (r0[2] == r1[2])
4141 *yptr++ = r0[2];
4142 else
4143 *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
4144
4145 if (r0[3] == r1[3])
4146 *kptr++ = r0[3];
4147 else
4148 *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
4149 }
4150 break;
4151 }
4152 break;
4153
4154 case CUPS_ORDER_PLANAR :
4155 switch (header->cupsBitsPerColor)
4156 {
4157 case 1 :
4158 bitmask = 0x80 >> (bitoffset & 7);
f301802f 4159 dither = Floyd16x16[y & 15];
ef416fc2 4160
f301802f 4161 for (x = xsize; x > 0; x --)
ef416fc2 4162 {
f301802f 4163 pc = *r0++ > dither[x & 15];
4164 pm = *r0++ > dither[x & 15];
4165 py = *r0++ > dither[x & 15];
4166
4167 if ((pc && pm && py && z == 3) ||
4168 (pc && z == 2) || (pm && z == 1) || (py && z == 0))
ef416fc2 4169 *ptr ^= bitmask;
4170
4171 if (bitmask > 1)
4172 bitmask >>= 1;
4173 else
4174 {
4175 bitmask = 0x80;
4176 ptr ++;
4177 }
4178 }
4179 break;
4180
4181 case 2 :
f301802f 4182 bitmask = 0xc0 >> (bitoffset & 7);
ef416fc2 4183 dither = Floyd8x8[y & 7];
4184 if (z == 3)
4185 r0 += 3;
4186 else
4187 r0 += 2 - z;
4188
4189 for (x = xsize; x > 0; x --, r0 += 4)
4190 {
4191 if ((*r0 & 63) > dither[x & 7])
4192 *ptr ^= (bitmask & OnPixels[*r0]);
4193 else
4194 *ptr ^= (bitmask & OffPixels[*r0]);
4195
4196 if (bitmask > 3)
4197 bitmask >>= 2;
4198 else
4199 {
f301802f 4200 bitmask = 0xc0;
ef416fc2 4201
4202 ptr ++;
4203 }
4204 }
4205 break;
4206
4207 case 4 :
4208 bitmask = 0xf0 >> (bitoffset & 7);
4209 dither = Floyd4x4[y & 3];
4210 if (z == 3)
4211 r0 += 3;
4212 else
4213 r0 += 2 - z;
4214
4215 for (x = xsize; x > 0; x --, r0 += 4)
4216 {
4217 if ((*r0 & 15) > dither[x & 3])
4218 *ptr ^= (bitmask & OnPixels[*r0]);
4219 else
4220 *ptr ^= (bitmask & OffPixels[*r0]);
4221
4222 if (bitmask == 0xf0)
4223 bitmask = 0x0f;
4224 else
4225 {
4226 bitmask = 0xf0;
4227
4228 ptr ++;
4229 }
4230 }
4231 break;
4232
4233 case 8 :
4234 if (z == 3)
4235 {
4236 r0 += 3;
4237 r1 += 3;
4238 }
4239 else
4240 {
4241 r0 += 2 - z;
4242 r1 += 2 - z;
4243 }
4244
4245 for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
4246 {
4247 if (*r0 == *r1)
4248 *ptr++ = *r0;
4249 else
4250 *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
4251 }
4252 break;
4253 }
4254 break;
4255 }
4256}
4257
4258
4259/*
4260 * 'make_lut()' - Make a lookup table given gamma and brightness values.
4261 */
4262
4263static void
4264make_lut(cups_ib_t *lut, /* I - Lookup table */
4265 int colorspace, /* I - Colorspace */
4266 float g, /* I - Image gamma */
4267 float b) /* I - Image brightness */
4268{
4269 int i; /* Looping var */
4270 int v; /* Current value */
4271
4272
4273 g = 1.0 / g;
4274 b = 1.0 / b;
4275
4276 for (i = 0; i < 256; i ++)
4277 {
4278 if (colorspace < 0)
4279 v = 255.0 * b * (1.0 - pow(1.0 - (float)i / 255.0, g)) + 0.5;
4280 else
4281 v = 255.0 * (1.0 - b * (1.0 - pow((float)i / 255.0, g))) + 0.5;
4282
4283 if (v < 0)
4284 *lut++ = 0;
4285 else if (v > 255)
4286 *lut++ = 255;
4287 else
4288 *lut++ = v;
4289 }
4290}
4291
4292
4293/*
a74454a7 4294 * 'raster_cb()' - Validate the page header.
4295 */
4296
4297static int /* O - 0 if OK, -1 if not */
4298raster_cb(
4299 cups_page_header2_t *header, /* IO - Raster header */
4300 int preferred_bits) /* I - Preferred bits per color */
4301{
4302 /*
4303 * Ensure that colorimetric colorspaces use at least 8 bits per
4304 * component...
4305 */
4306
4307 if ((header->cupsColorSpace == CUPS_CSPACE_CIEXYZ ||
4308 header->cupsColorSpace == CUPS_CSPACE_CIELab ||
4309 header->cupsColorSpace >= CUPS_CSPACE_ICC1) &&
4310 header->cupsBitsPerColor < 8)
4311 header->cupsBitsPerColor = 8;
4312
4313 return (0);
4314}
4315
4316
4317/*
75bd9771 4318 * End of "$Id: imagetoraster.c 7306 2008-02-15 00:52:38Z mike $".
ef416fc2 4319 */