]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/imagetoraster.c
Merge changes from CUPS 1.4svn-r8162.
[thirdparty/cups.git] / filter / imagetoraster.c
1 /*
2 * "$Id: imagetoraster.c 7306 2008-02-15 00:52:38Z mike $"
3 *
4 * Image file to raster filter for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
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/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * main() - Main entry...
20 * blank_line() - Clear a line buffer to the blank value...
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.
31 * raster_cb() - Validate the page header.
32 */
33
34 /*
35 * Include necessary headers...
36 */
37
38 #include "common.h"
39 #include "image-private.h"
40 #include <unistd.h>
41 #include <math.h>
42 #include <cups/i18n.h>
43
44
45 /*
46 * Globals...
47 */
48
49 int 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 */
54 int Floyd16x16[16][16] = /* Traditional Floyd ordered dither */
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 };
89 int 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 };
100 int 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
108 cups_ib_t OnPixels[256], /* On-pixel LUT */
109 OffPixels[256]; /* Off-pixel LUT */
110
111
112 /*
113 * Local functions...
114 */
115
116 static void blank_line(cups_page_header2_t *header, unsigned char *row);
117 static 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);
118 static 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);
119 static 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);
120 static 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);
121 static 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
123 static 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);
124 static 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);
125 static 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);
126 static 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);
127 static void make_lut(cups_ib_t *, int, float, float);
128 static int raster_cb(cups_page_header2_t *header, int preferred_bits);
129
130
131 /*
132 * 'main()' - Main entry...
133 */
134
135 int /* O - Exit status */
136 main(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 */
157 int xc0, yc0, /* Corners of the page in image coords */
158 xc1, yc1;
159 ppd_file_t *ppd; /* PPD file */
160 ppd_choice_t *choice; /* PPD option choice */
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 */
188 yerr1; /* Bottom Y error value */
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 {
207 fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
208 argv[0]);
209 return (1);
210 }
211
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
244 close(0);
245 dup(mypipes[0]);
246 close(mypipes[0]);
247 close(mypipes[1]);
248
249 execlp("pstoraster", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
250 NULL);
251 perror("ERROR: Unable to exec pstoraster");
252 return (errno);
253 }
254 else if (pid < 0)
255 {
256 /*
257 * Error!
258 */
259
260 perror("ERROR: Unable to fork pstoraster");
261 return (errno);
262 }
263
264 /*
265 * Update stdout so it points at the new pstoraster...
266 */
267
268 close(1);
269 dup(mypipes[1]);
270 close(mypipes[0]);
271 close(mypipes[1]);
272
273 /*
274 * Run imagetops to get the classification or page labelling that was
275 * requested...
276 */
277
278 execlp("imagetops", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
279 argv[6], NULL);
280 perror("ERROR: Unable to exec imagetops");
281 return (errno);
282 }
283
284 /*
285 * Copy stdin as needed...
286 */
287
288 if (argc == 6)
289 {
290 int fd; /* File to write to */
291 char buffer[8192]; /* Buffer to read into */
292 int bytes; /* # of bytes to read */
293
294
295 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
296 {
297 perror("ERROR: Unable to copy image file");
298 return (1);
299 }
300
301 fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
302 filename);
303
304 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
305 write(fd, buffer, bytes);
306
307 close(fd);
308 }
309 else
310 strlcpy(filename, argv[6], sizeof(filename));
311
312 /*
313 * Process command-line options and write the prolog...
314 */
315
316 zoom = 0.0;
317 xppi = 0;
318 yppi = 0;
319 hue = 0;
320 sat = 100;
321 g = 1.0;
322 b = 1.0;
323
324 Copies = atoi(argv[4]);
325
326 ppd = SetCommonOptions(num_options, options, 0);
327
328 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
329 {
330 /*
331 * This IPP attribute is unnecessarily complicated...
332 *
333 * single-document, separate-documents-collated-copies, and
334 * single-document-new-sheet all require collated copies.
335 *
336 * separate-documents-collated-copies allows for uncollated copies.
337 */
338
339 Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
340 }
341
342 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
343 strcasecmp(val, "True") == 0)
344 Collate = 1;
345
346 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
347 {
348 /*
349 * Get gamma value from 1 to 10000...
350 */
351
352 g = atoi(val) * 0.001f;
353
354 if (g < 0.001f)
355 g = 0.001f;
356 else if (g > 10.0f)
357 g = 10.0f;
358 }
359
360 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
361 {
362 /*
363 * Get brightness value from 10 to 1000.
364 */
365
366 b = atoi(val) * 0.01f;
367
368 if (b < 0.1f)
369 b = 0.1f;
370 else if (b > 10.0f)
371 b = 10.0f;
372 }
373
374 if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
375 zoom = atoi(val) * 0.01;
376 else if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
377 !strcasecmp(val, "true"))
378 zoom = 1.0;
379 else if ((val = cupsGetOption("fit-to-page", num_options, options)) != NULL &&
380 !strcasecmp(val, "true"))
381 zoom = 1.0;
382
383 if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
384 if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
385 yppi = xppi;
386
387 if ((val = cupsGetOption("position", num_options, options)) != NULL)
388 {
389 if (strcasecmp(val, "center") == 0)
390 {
391 XPosition = 0;
392 YPosition = 0;
393 }
394 else if (strcasecmp(val, "top") == 0)
395 {
396 XPosition = 0;
397 YPosition = 1;
398 }
399 else if (strcasecmp(val, "left") == 0)
400 {
401 XPosition = -1;
402 YPosition = 0;
403 }
404 else if (strcasecmp(val, "right") == 0)
405 {
406 XPosition = 1;
407 YPosition = 0;
408 }
409 else if (strcasecmp(val, "top-left") == 0)
410 {
411 XPosition = -1;
412 YPosition = 1;
413 }
414 else if (strcasecmp(val, "top-right") == 0)
415 {
416 XPosition = 1;
417 YPosition = 1;
418 }
419 else if (strcasecmp(val, "bottom") == 0)
420 {
421 XPosition = 0;
422 YPosition = -1;
423 }
424 else if (strcasecmp(val, "bottom-left") == 0)
425 {
426 XPosition = -1;
427 YPosition = -1;
428 }
429 else if (strcasecmp(val, "bottom-right") == 0)
430 {
431 XPosition = 1;
432 YPosition = -1;
433 }
434 }
435
436 if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
437 sat = atoi(val);
438
439 if ((val = cupsGetOption("hue", num_options, options)) != NULL)
440 hue = atoi(val);
441
442 if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
443 {
444 val = choice->choice;
445 choice->marked = 0;
446 }
447 else
448 val = cupsGetOption("mirror", num_options, options);
449
450 if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
451 !strcasecmp(val, "yes")))
452 Flip = 1;
453
454 /*
455 * Set the needed options in the page header...
456 */
457
458 if (cupsRasterInterpretPPD(&header, ppd, num_options, options, raster_cb))
459 {
460 fputs(_("ERROR: Bad page setup!\n"), stderr);
461 fprintf(stderr, "DEBUG: %s\n", cupsRasterErrorString());
462 return (1);
463 }
464
465 /*
466 * Get the media type and resolution that have been chosen...
467 */
468
469 if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
470 media_type = choice->choice;
471 else
472 media_type = "";
473
474 if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
475 resolution = choice->choice;
476 else
477 resolution = "";
478
479 /*
480 * Choose the appropriate colorspace...
481 */
482
483 switch (header.cupsColorSpace)
484 {
485 case CUPS_CSPACE_W :
486 if (header.cupsBitsPerColor >= 8)
487 {
488 primary = CUPS_IMAGE_WHITE;
489 secondary = CUPS_IMAGE_WHITE;
490 }
491 else
492 {
493 primary = CUPS_IMAGE_BLACK;
494 secondary = CUPS_IMAGE_BLACK;
495 }
496 break;
497
498 default :
499 case CUPS_CSPACE_RGB :
500 case CUPS_CSPACE_RGBA :
501 case CUPS_CSPACE_RGBW :
502 if (header.cupsBitsPerColor >= 8)
503 {
504 primary = CUPS_IMAGE_RGB;
505 secondary = CUPS_IMAGE_RGB;
506 }
507 else
508 {
509 primary = CUPS_IMAGE_CMY;
510 secondary = CUPS_IMAGE_CMY;
511 }
512 break;
513
514 case CUPS_CSPACE_K :
515 case CUPS_CSPACE_WHITE :
516 case CUPS_CSPACE_GOLD :
517 case CUPS_CSPACE_SILVER :
518 primary = CUPS_IMAGE_BLACK;
519 secondary = CUPS_IMAGE_BLACK;
520 break;
521
522 case CUPS_CSPACE_CMYK :
523 case CUPS_CSPACE_YMCK :
524 case CUPS_CSPACE_KCMY :
525 case CUPS_CSPACE_KCMYcm :
526 case CUPS_CSPACE_GMCK :
527 case CUPS_CSPACE_GMCS :
528 if (header.cupsBitsPerColor == 1)
529 {
530 primary = CUPS_IMAGE_CMY;
531 secondary = CUPS_IMAGE_CMY;
532 }
533 else
534 {
535 primary = CUPS_IMAGE_CMYK;
536 secondary = CUPS_IMAGE_CMYK;
537 }
538 break;
539
540 case CUPS_CSPACE_CMY :
541 case CUPS_CSPACE_YMC :
542 primary = CUPS_IMAGE_CMY;
543 secondary = CUPS_IMAGE_CMY;
544 break;
545 break;
546 }
547
548 /*
549 * Find a color profile matching the current options...
550 */
551
552 if ((val = cupsGetOption("profile", num_options, options)) != NULL)
553 {
554 profile = &userprofile;
555 sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
556 &(userprofile.density), &(userprofile.gamma),
557 userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
558 userprofile.matrix[0] + 2,
559 userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
560 userprofile.matrix[1] + 2,
561 userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
562 userprofile.matrix[2] + 2);
563
564 userprofile.density *= 0.001f;
565 userprofile.gamma *= 0.001f;
566 userprofile.matrix[0][0] *= 0.001f;
567 userprofile.matrix[0][1] *= 0.001f;
568 userprofile.matrix[0][2] *= 0.001f;
569 userprofile.matrix[1][0] *= 0.001f;
570 userprofile.matrix[1][1] *= 0.001f;
571 userprofile.matrix[1][2] *= 0.001f;
572 userprofile.matrix[2][0] *= 0.001f;
573 userprofile.matrix[2][1] *= 0.001f;
574 userprofile.matrix[2][2] *= 0.001f;
575 }
576 else if (ppd != NULL)
577 {
578 fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
579 resolution, media_type);
580
581 for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
582 {
583 fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
584 profile->media_type);
585
586 if ((strcmp(profile->resolution, resolution) == 0 ||
587 profile->resolution[0] == '-') &&
588 (strcmp(profile->media_type, media_type) == 0 ||
589 profile->media_type[0] == '-'))
590 {
591 fputs("MATCH!\n", stderr);
592 break;
593 }
594 else
595 fputs("no.\n", stderr);
596 }
597
598 /*
599 * If we found a color profile, use it!
600 */
601
602 if (i >= ppd->num_profiles)
603 profile = NULL;
604 }
605 else
606 profile = NULL;
607
608 if (profile)
609 cupsImageSetProfile(profile->density, profile->gamma, profile->matrix);
610
611 cupsImageSetRasterColorSpace(header.cupsColorSpace);
612
613 /*
614 * Create a gamma/brightness LUT...
615 */
616
617 make_lut(lut, primary, g, b);
618
619 /*
620 * Open the input image to print...
621 */
622
623 fputs(_("INFO: Loading image file...\n"), stderr);
624
625 if (header.cupsColorSpace == CUPS_CSPACE_CIEXYZ ||
626 header.cupsColorSpace == CUPS_CSPACE_CIELab ||
627 header.cupsColorSpace >= CUPS_CSPACE_ICC1)
628 img = cupsImageOpen(filename, primary, secondary, sat, hue, NULL);
629 else
630 img = cupsImageOpen(filename, primary, secondary, sat, hue, lut);
631
632 if (argc == 6)
633 unlink(filename);
634
635 if (img == NULL)
636 {
637 fputs(_("ERROR: Unable to open image file for printing!\n"), stderr);
638 ppdClose(ppd);
639 return (1);
640 }
641
642 /*
643 * Scale as necessary...
644 */
645
646 if (zoom == 0.0 && xppi == 0)
647 {
648 xppi = img->xppi;
649 yppi = img->yppi;
650 }
651
652 if (yppi == 0)
653 yppi = xppi;
654
655 fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
656 xppi, yppi, zoom);
657
658 if (xppi > 0)
659 {
660 /*
661 * Scale the image as neccesary to match the desired pixels-per-inch.
662 */
663
664 if (Orientation & 1)
665 {
666 xprint = (PageTop - PageBottom) / 72.0;
667 yprint = (PageRight - PageLeft) / 72.0;
668 }
669 else
670 {
671 xprint = (PageRight - PageLeft) / 72.0;
672 yprint = (PageTop - PageBottom) / 72.0;
673 }
674
675 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
676 xprint, yprint);
677
678 xinches = (float)img->xsize / (float)xppi;
679 yinches = (float)img->ysize / (float)yppi;
680
681 fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
682 xinches, yinches);
683
684 if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
685 {
686 xinches = xinches * atoi(val) / 100;
687 yinches = yinches * atoi(val) / 100;
688 }
689
690 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
691 cupsGetOption("landscape", num_options, options) == NULL)
692 {
693 /*
694 * Rotate the image if it will fit landscape but not portrait...
695 */
696
697 fputs("DEBUG: Auto orientation...\n", stderr);
698
699 if ((xinches > xprint || yinches > yprint) &&
700 xinches <= yprint && yinches <= xprint)
701 {
702 /*
703 * Rotate the image as needed...
704 */
705
706 fputs("DEBUG: Using landscape orientation...\n", stderr);
707
708 Orientation = (Orientation + 1) & 3;
709 xsize = yprint;
710 yprint = xprint;
711 xprint = xsize;
712 }
713 }
714 }
715 else
716 {
717 /*
718 * Scale percentage of page size...
719 */
720
721 xprint = (PageRight - PageLeft) / 72.0;
722 yprint = (PageTop - PageBottom) / 72.0;
723 aspect = (float)img->yppi / (float)img->xppi;
724
725 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
726 xprint, yprint);
727
728 fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
729 img->xppi, img->yppi, aspect);
730
731 xsize = xprint * zoom;
732 ysize = xsize * img->ysize / img->xsize / aspect;
733
734 if (ysize > (yprint * zoom))
735 {
736 ysize = yprint * zoom;
737 xsize = ysize * img->xsize * aspect / img->ysize;
738 }
739
740 xsize2 = yprint * zoom;
741 ysize2 = xsize2 * img->ysize / img->xsize / aspect;
742
743 if (ysize2 > (xprint * zoom))
744 {
745 ysize2 = xprint * zoom;
746 xsize2 = ysize2 * img->xsize * aspect / img->ysize;
747 }
748
749 fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
750 fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
751
752 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
753 cupsGetOption("landscape", num_options, options) == NULL)
754 {
755 /*
756 * Choose the rotation with the largest area, but prefer
757 * portrait if they are equal...
758 */
759
760 fputs("DEBUG: Auto orientation...\n", stderr);
761
762 if ((xsize * ysize) < (xsize2 * xsize2))
763 {
764 /*
765 * Do landscape orientation...
766 */
767
768 fputs("DEBUG: Using landscape orientation...\n", stderr);
769
770 Orientation = 1;
771 xinches = xsize2;
772 yinches = ysize2;
773 xprint = (PageTop - PageBottom) / 72.0;
774 yprint = (PageRight - PageLeft) / 72.0;
775 }
776 else
777 {
778 /*
779 * Do portrait orientation...
780 */
781
782 fputs("DEBUG: Using portrait orientation...\n", stderr);
783
784 Orientation = 0;
785 xinches = xsize;
786 yinches = ysize;
787 }
788 }
789 else if (Orientation & 1)
790 {
791 fputs("DEBUG: Using landscape orientation...\n", stderr);
792
793 xinches = xsize2;
794 yinches = ysize2;
795 xprint = (PageTop - PageBottom) / 72.0;
796 yprint = (PageRight - PageLeft) / 72.0;
797 }
798 else
799 {
800 fputs("DEBUG: Using portrait orientation...\n", stderr);
801
802 xinches = xsize;
803 yinches = ysize;
804 xprint = (PageRight - PageLeft) / 72.0;
805 yprint = (PageTop - PageBottom) / 72.0;
806 }
807 }
808
809 /*
810 * Compute the number of pages to print and the size of the image on each
811 * page...
812 */
813
814 xpages = ceil(xinches / xprint);
815 ypages = ceil(yinches / yprint);
816
817 xprint = xinches / xpages;
818 yprint = yinches / ypages;
819
820 fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
821 xpages, xprint, ypages, yprint);
822
823 /*
824 * Compute the bitmap size...
825 */
826
827 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
828 strcasecmp(choice->choice, "Custom") == 0)
829 {
830 float width, /* New width in points */
831 length; /* New length in points */
832
833
834 /*
835 * Use the correct width and length for the current orientation...
836 */
837
838 if (Orientation & 1)
839 {
840 width = yprint * 72.0;
841 length = xprint * 72.0;
842 }
843 else
844 {
845 width = xprint * 72.0;
846 length = yprint * 72.0;
847 }
848
849 /*
850 * Add margins to page size...
851 */
852
853 width += ppd->custom_margins[0] + ppd->custom_margins[2];
854 length += ppd->custom_margins[1] + ppd->custom_margins[3];
855
856 /*
857 * Enforce minimums...
858 */
859
860 if (width < ppd->custom_min[0])
861 width = ppd->custom_min[0];
862
863 if (length < ppd->custom_min[1])
864 length = ppd->custom_min[1];
865
866 fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
867 width / 72.0, length / 72.0);
868
869 /*
870 * Set the new custom size...
871 */
872
873 strcpy(header.cupsPageSizeName, "Custom");
874
875 header.cupsPageSize[0] = width + 0.5;
876 header.cupsPageSize[1] = length + 0.5;
877 header.PageSize[0] = width + 0.5;
878 header.PageSize[1] = length + 0.5;
879
880 /*
881 * Update page variables...
882 */
883
884 PageWidth = width;
885 PageLength = length;
886 PageLeft = ppd->custom_margins[0];
887 PageRight = width - ppd->custom_margins[2];
888 PageBottom = ppd->custom_margins[1];
889 PageTop = length - ppd->custom_margins[3];
890
891 /*
892 * Remove margins from page size...
893 */
894
895 width -= ppd->custom_margins[0] + ppd->custom_margins[2];
896 length -= ppd->custom_margins[1] + ppd->custom_margins[3];
897
898 /*
899 * Set the bitmap size...
900 */
901
902 header.cupsWidth = width * header.HWResolution[0] / 72.0;
903 header.cupsHeight = length * header.HWResolution[1] / 72.0;
904
905 header.cupsBytesPerLine = (header.cupsBitsPerPixel *
906 header.cupsWidth + 7) / 8;
907
908 if (header.cupsColorOrder == CUPS_ORDER_BANDED)
909 header.cupsBytesPerLine *= header.cupsNumColors;
910 }
911
912 header.Margins[0] = PageLeft;
913 header.Margins[1] = PageBottom;
914
915 fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
916 header.PageSize[1]);
917
918 switch (Orientation)
919 {
920 default :
921 switch (XPosition)
922 {
923 case -1 :
924 header.cupsImagingBBox[0] = PageLeft;
925 header.cupsImagingBBox[2] = PageLeft + xprint * 72;
926 break;
927 default :
928 header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
929 header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
930 break;
931 case 1 :
932 header.cupsImagingBBox[0] = PageRight - xprint * 72;
933 header.cupsImagingBBox[2] = PageRight;
934 break;
935 }
936
937 switch (YPosition)
938 {
939 case -1 :
940 header.cupsImagingBBox[1] = PageBottom;
941 header.cupsImagingBBox[3] = PageBottom + yprint * 72;
942 break;
943 default :
944 header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
945 header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
946 break;
947 case 1 :
948 header.cupsImagingBBox[1] = PageTop - yprint * 72;
949 header.cupsImagingBBox[3] = PageTop;
950 break;
951 }
952 break;
953
954 case 1 :
955 switch (XPosition)
956 {
957 case -1 :
958 header.cupsImagingBBox[0] = PageBottom;
959 header.cupsImagingBBox[2] = PageBottom + yprint * 72;
960 break;
961 default :
962 header.cupsImagingBBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
963 header.cupsImagingBBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
964 break;
965 case 1 :
966 header.cupsImagingBBox[0] = PageTop - yprint * 72;
967 header.cupsImagingBBox[2] = PageTop;
968 break;
969 }
970
971 switch (YPosition)
972 {
973 case -1 :
974 header.cupsImagingBBox[1] = PageLeft;
975 header.cupsImagingBBox[3] = PageLeft + xprint * 72;
976 break;
977 default :
978 header.cupsImagingBBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
979 header.cupsImagingBBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
980 break;
981 case 1 :
982 header.cupsImagingBBox[1] = PageRight - xprint * 72;
983 header.cupsImagingBBox[3] = PageRight;
984 break;
985 }
986 break;
987
988 case 2 :
989 switch (XPosition)
990 {
991 case 1 :
992 header.cupsImagingBBox[0] = PageLeft;
993 header.cupsImagingBBox[2] = PageLeft + xprint * 72;
994 break;
995 default :
996 header.cupsImagingBBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
997 header.cupsImagingBBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
998 break;
999 case -1 :
1000 header.cupsImagingBBox[0] = PageRight - xprint * 72;
1001 header.cupsImagingBBox[2] = PageRight;
1002 break;
1003 }
1004
1005 switch (YPosition)
1006 {
1007 case 1 :
1008 header.cupsImagingBBox[1] = PageBottom;
1009 header.cupsImagingBBox[3] = PageBottom + yprint * 72;
1010 break;
1011 default :
1012 header.cupsImagingBBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1013 header.cupsImagingBBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
1014 break;
1015 case -1 :
1016 header.cupsImagingBBox[1] = PageTop - yprint * 72;
1017 header.cupsImagingBBox[3] = PageTop;
1018 break;
1019 }
1020 break;
1021
1022 case 3 :
1023 switch (XPosition)
1024 {
1025 case 1 :
1026 header.cupsImagingBBox[0] = PageBottom;
1027 header.cupsImagingBBox[2] = PageBottom + yprint * 72;
1028 break;
1029 default :
1030 header.cupsImagingBBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
1031 header.cupsImagingBBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
1032 break;
1033 case -1 :
1034 header.cupsImagingBBox[0] = PageTop - yprint * 72;
1035 header.cupsImagingBBox[2] = PageTop;
1036 break;
1037 }
1038
1039 switch (YPosition)
1040 {
1041 case 1 :
1042 header.cupsImagingBBox[1] = PageLeft;
1043 header.cupsImagingBBox[3] = PageLeft + xprint * 72;
1044 break;
1045 default :
1046 header.cupsImagingBBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
1047 header.cupsImagingBBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
1048 break;
1049 case -1 :
1050 header.cupsImagingBBox[1] = PageRight - xprint * 72;
1051 header.cupsImagingBBox[3] = PageRight;
1052 break;
1053 }
1054 break;
1055 }
1056
1057 header.ImagingBoundingBox[0] = header.cupsImagingBBox[0];
1058 header.ImagingBoundingBox[1] = header.cupsImagingBBox[1];
1059 header.ImagingBoundingBox[2] = header.cupsImagingBBox[2];
1060 header.ImagingBoundingBox[3] = header.cupsImagingBBox[3];
1061
1062 if (header.cupsColorOrder == CUPS_ORDER_PLANAR)
1063 num_planes = header.cupsNumColors;
1064 else
1065 num_planes = 1;
1066
1067 if (header.cupsBitsPerColor >= 8)
1068 zoom_type = CUPS_IZOOM_NORMAL;
1069 else
1070 zoom_type = CUPS_IZOOM_FAST;
1071
1072 /*
1073 * See if we need to collate, and if so how we need to do it...
1074 */
1075
1076 if (xpages == 1 && ypages == 1)
1077 Collate = 0;
1078
1079 slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
1080 if (ppd != NULL)
1081 slowcopies = ppd->manual_copies;
1082 else
1083 slowcopies = 1;
1084
1085 if (Copies > 1 && !slowcollate && !slowcopies)
1086 {
1087 header.Collate = (cups_bool_t)Collate;
1088 header.NumCopies = Copies;
1089
1090 Copies = 1;
1091 }
1092 else
1093 header.NumCopies = 1;
1094
1095 /*
1096 * Create the dithering lookup tables...
1097 */
1098
1099 OnPixels[0] = 0x00;
1100 OnPixels[255] = 0xff;
1101 OffPixels[0] = 0x00;
1102 OffPixels[255] = 0xff;
1103
1104 switch (header.cupsBitsPerColor)
1105 {
1106 case 2 :
1107 for (i = 1; i < 255; i ++)
1108 {
1109 OnPixels[i] = 0x55 * (i / 85 + 1);
1110 OffPixels[i] = 0x55 * (i / 64);
1111 }
1112 break;
1113 case 4 :
1114 for (i = 1; i < 255; i ++)
1115 {
1116 OnPixels[i] = 17 * (i / 17 + 1);
1117 OffPixels[i] = 17 * (i / 16);
1118 }
1119 break;
1120 }
1121
1122 /*
1123 * Output the pages...
1124 */
1125
1126 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
1127 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
1128 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
1129 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
1130 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
1131 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
1132 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
1133 fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
1134
1135 row = malloc(2 * header.cupsBytesPerLine);
1136 ras = cupsRasterOpen(1, CUPS_RASTER_WRITE);
1137
1138 for (i = 0, page = 1; i < Copies; i ++)
1139 for (xpage = 0; xpage < xpages; xpage ++)
1140 for (ypage = 0; ypage < ypages; ypage ++, page ++)
1141 {
1142 fprintf(stderr, _("INFO: Formatting page %d...\n"), page);
1143
1144 if (Orientation & 1)
1145 {
1146 xc0 = img->xsize * ypage / ypages;
1147 xc1 = img->xsize * (ypage + 1) / ypages - 1;
1148 yc0 = img->ysize * xpage / xpages;
1149 yc1 = img->ysize * (xpage + 1) / xpages - 1;
1150
1151 xtemp = header.HWResolution[0] * yprint;
1152 ytemp = header.HWResolution[1] * xprint;
1153 }
1154 else
1155 {
1156 xc0 = img->xsize * xpage / xpages;
1157 xc1 = img->xsize * (xpage + 1) / xpages - 1;
1158 yc0 = img->ysize * ypage / ypages;
1159 yc1 = img->ysize * (ypage + 1) / ypages - 1;
1160
1161 xtemp = header.HWResolution[0] * xprint;
1162 ytemp = header.HWResolution[1] * yprint;
1163 }
1164
1165 cupsRasterWriteHeader2(ras, &header);
1166
1167 for (plane = 0; plane < num_planes; plane ++)
1168 {
1169 /*
1170 * Initialize the image "zoom" engine...
1171 */
1172
1173 if (Flip)
1174 z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, -xtemp, ytemp,
1175 Orientation & 1, zoom_type);
1176 else
1177 z = _cupsImageZoomNew(img, xc0, yc0, xc1, yc1, xtemp, ytemp,
1178 Orientation & 1, zoom_type);
1179
1180 /*
1181 * Write leading blank space as needed...
1182 */
1183
1184 if (header.cupsHeight > z->ysize && YPosition <= 0)
1185 {
1186 blank_line(&header, row);
1187
1188 y = header.cupsHeight - z->ysize;
1189 if (YPosition == 0)
1190 y /= 2;
1191
1192 fprintf(stderr, "DEBUG: Writing %d leading blank lines...\n", y);
1193
1194 for (; y > 0; y --)
1195 {
1196 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1197 header.cupsBytesPerLine)
1198 {
1199 fputs(_("ERROR: Unable to write raster data to driver!\n"),
1200 stderr);
1201 cupsImageClose(img);
1202 exit(1);
1203 }
1204 }
1205 }
1206
1207 /*
1208 * Then write image data...
1209 */
1210
1211 for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
1212 y > 0;
1213 y --)
1214 {
1215 if (iy != last_iy)
1216 {
1217 if (zoom_type != CUPS_IZOOM_FAST && (iy - last_iy) > 1)
1218 _cupsImageZoomFill(z, iy);
1219
1220 _cupsImageZoomFill(z, iy + z->yincr);
1221
1222 last_iy = iy;
1223 }
1224
1225 /*
1226 * Format this line of raster data for the printer...
1227 */
1228
1229 blank_line(&header, row);
1230
1231 r0 = z->rows[z->row];
1232 r1 = z->rows[1 - z->row];
1233
1234 switch (header.cupsColorSpace)
1235 {
1236 case CUPS_CSPACE_W :
1237 format_W(&header, row, y, plane, z->xsize, z->ysize,
1238 yerr0, yerr1, r0, r1);
1239 break;
1240 default :
1241 case CUPS_CSPACE_RGB :
1242 format_RGB(&header, row, y, plane, z->xsize, z->ysize,
1243 yerr0, yerr1, r0, r1);
1244 break;
1245 case CUPS_CSPACE_RGBA :
1246 case CUPS_CSPACE_RGBW :
1247 format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
1248 yerr0, yerr1, r0, r1);
1249 break;
1250 case CUPS_CSPACE_K :
1251 case CUPS_CSPACE_WHITE :
1252 case CUPS_CSPACE_GOLD :
1253 case CUPS_CSPACE_SILVER :
1254 format_K(&header, row, y, plane, z->xsize, z->ysize,
1255 yerr0, yerr1, r0, r1);
1256 break;
1257 case CUPS_CSPACE_CMY :
1258 format_CMY(&header, row, y, plane, z->xsize, z->ysize,
1259 yerr0, yerr1, r0, r1);
1260 break;
1261 case CUPS_CSPACE_YMC :
1262 format_YMC(&header, row, y, plane, z->xsize, z->ysize,
1263 yerr0, yerr1, r0, r1);
1264 break;
1265 case CUPS_CSPACE_CMYK :
1266 format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
1267 yerr0, yerr1, r0, r1);
1268 break;
1269 case CUPS_CSPACE_YMCK :
1270 case CUPS_CSPACE_GMCK :
1271 case CUPS_CSPACE_GMCS :
1272 format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
1273 yerr0, yerr1, r0, r1);
1274 break;
1275 case CUPS_CSPACE_KCMYcm :
1276 if (header.cupsBitsPerColor == 1)
1277 {
1278 format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
1279 yerr0, yerr1, r0, r1);
1280 break;
1281 }
1282 case CUPS_CSPACE_KCMY :
1283 format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
1284 yerr0, yerr1, r0, r1);
1285 break;
1286 }
1287
1288 /*
1289 * Write the raster data to the driver...
1290 */
1291
1292 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1293 header.cupsBytesPerLine)
1294 {
1295 fputs(_("ERROR: Unable to write raster data to driver!\n"),
1296 stderr);
1297 cupsImageClose(img);
1298 exit(1);
1299 }
1300
1301 /*
1302 * Compute the next scanline in the image...
1303 */
1304
1305 iy += z->ystep;
1306 yerr0 += z->ymod;
1307 yerr1 -= z->ymod;
1308 if (yerr1 <= 0)
1309 {
1310 yerr0 -= z->ysize;
1311 yerr1 += z->ysize;
1312 iy += z->yincr;
1313 }
1314 }
1315
1316 /*
1317 * Write trailing blank space as needed...
1318 */
1319
1320 if (header.cupsHeight > z->ysize && YPosition >= 0)
1321 {
1322 blank_line(&header, row);
1323
1324 y = header.cupsHeight - z->ysize;
1325 if (YPosition == 0)
1326 y = y - y / 2;
1327
1328 fprintf(stderr, "DEBUG: Writing %d trailing blank lines...\n", y);
1329
1330 for (; y > 0; y --)
1331 {
1332 if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1333 header.cupsBytesPerLine)
1334 {
1335 fputs(_("ERROR: Unable to write raster data to driver!\n"),
1336 stderr);
1337 cupsImageClose(img);
1338 exit(1);
1339 }
1340 }
1341 }
1342
1343 /*
1344 * Free memory used for the "zoom" engine...
1345 */
1346
1347 _cupsImageZoomDelete(z);
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
1364 /*
1365 * 'blank_line()' - Clear a line buffer to the blank value...
1366 */
1367
1368 static void
1369 blank_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
1436 /*
1437 * 'format_CMY()' - Convert image data to CMY.
1438 */
1439
1440 static void
1441 format_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 */
1449 cups_ib_t *r0, /* I - Primary image data */
1450 cups_ib_t *r1) /* I - Image data for interpolation */
1451 {
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 */
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);
1486 dither = Floyd16x16[y & 15];
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);
1574 dither = Floyd16x16[y & 15];
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 :
1598 bitmask = 0xc0 >> (bitoffset & 7);
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 {
1622 bitmask = 0xc0;
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);
1692 dither = Floyd16x16[y & 15];
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 :
1747 bitmask = 0xc0 >> (bitoffset & 7);
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 {
1762 bitmask = 0xc0;
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
1814 static void
1815 format_CMYK(cups_page_header2_t *header,/* I - Page header */
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 */
1823 cups_ib_t *r0, /* I - Primary image data */
1824 cups_ib_t *r1) /* I - Image data for interpolation */
1825 {
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 */
1836 int pc, pm, py; /* CMY pixels */
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);
1862 dither = Floyd16x16[y & 15];
1863
1864 for (x = xsize ; x > 0; x --)
1865 {
1866 pc = *r0++ > dither[x & 15];
1867 pm = *r0++ > dither[x & 15];
1868 py = *r0++ > dither[x & 15];
1869
1870 if (pc && pm && py)
1871 {
1872 bitmask >>= 3;
1873 *ptr ^= bitmask;
1874 }
1875 else
1876 {
1877 if (pc)
1878 *ptr ^= bitmask;
1879 bitmask >>= 1;
1880
1881 if (pm)
1882 *ptr ^= bitmask;
1883 bitmask >>= 1;
1884
1885 if (py)
1886 *ptr ^= bitmask;
1887 bitmask >>= 1;
1888 }
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])
1906 *ptr ^= (0xc0 & OnPixels[r0[0]]);
1907 else
1908 *ptr ^= (0xc0 & OffPixels[r0[0]]);
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);
1974 dither = Floyd16x16[y & 15];
1975
1976 for (x = xsize; x > 0; x --)
1977 {
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 }
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 :
2008 bitmask = 0xc0 >> (bitoffset & 7);
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 {
2037 bitmask = 0xc0;
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);
2119 dither = Floyd16x16[y & 15];
2120
2121 for (x = xsize; x > 0; x --)
2122 {
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))
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 :
2142 bitmask = 0xc0 >> (bitoffset & 7);
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 {
2157 bitmask = 0xc0;
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
2209 static void
2210 format_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 */
2218 cups_ib_t *r0, /* I - Primary image data */
2219 cups_ib_t *r1) /* I - Image data for interpolation */
2220 {
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 */
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);
2249 dither = Floyd16x16[y & 15];
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 :
2267 bitmask = 0xc0 >> (bitoffset & 7);
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 {
2281 bitmask = 0xc0;
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
2327 static void
2328 format_KCMY(cups_page_header2_t *header,/* I - Page header */
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 */
2336 cups_ib_t *r0, /* I - Primary image data */
2337 cups_ib_t *r1) /* I - Image data for interpolation */
2338 {
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 */
2349 int pc, pm, py; /* CMY pixels */
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);
2375 dither = Floyd16x16[y & 15];
2376
2377 for (x = xsize ; x > 0; x --)
2378 {
2379 pc = *r0++ > dither[x & 15];
2380 pm = *r0++ > dither[x & 15];
2381 py = *r0++ > dither[x & 15];
2382
2383 if (pc && pm && py)
2384 {
2385 *ptr ^= bitmask;
2386 bitmask >>= 3;
2387 }
2388 else
2389 {
2390 bitmask >>= 1;
2391 if (pc)
2392 *ptr ^= bitmask;
2393
2394 bitmask >>= 1;
2395 if (pm)
2396 *ptr ^= bitmask;
2397
2398 bitmask >>= 1;
2399 if (py)
2400 *ptr ^= bitmask;
2401 }
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])
2419 *ptr ^= (0xc0 & OnPixels[r0[3]]);
2420 else
2421 *ptr ^= (0xc0 & OffPixels[r0[3]]);
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);
2504 dither = Floyd16x16[y & 15];
2505
2506 for (x = xsize; x > 0; x --)
2507 {
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 }
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 :
2538 bitmask = 0xc0 >> (bitoffset & 7);
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 {
2567 bitmask = 0xc0;
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);
2649 dither = Floyd16x16[y & 15];
2650
2651 for (x = xsize; x > 0; x --)
2652 {
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))
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 :
2672 bitmask = 0xc0 >> (bitoffset & 7);
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 {
2690 bitmask = 0xc0;
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
2753 static void
2754 format_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 */
2765 {
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 */
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
2794 ptr = row + bitoffset / 8;
2795 bandwidth = header->cupsBytesPerLine / 6;
2796
2797 switch (header->cupsColorOrder)
2798 {
2799 case CUPS_ORDER_CHUNKED :
2800 dither = Floyd16x16[y & 15];
2801
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 ++;
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
2836 bitmask = 0x80 >> (bitoffset & 7);
2837 dither = Floyd16x16[y & 15];
2838
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;
2869
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 }
2883 break;
2884
2885 case CUPS_ORDER_PLANAR :
2886 bitmask = 0x80 >> (bitoffset & 7);
2887 dither = Floyd16x16[y & 15];
2888
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;
2895
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;
2910
2911 if (bitmask > 1)
2912 bitmask >>= 1;
2913 else
2914 {
2915 bitmask = 0x80;
2916 ptr ++;
2917 }
2918 }
2919 break;
2920 }
2921 }
2922
2923
2924 /*
2925 * 'format_RGBA()' - Convert image data to RGBA/RGBW.
2926 */
2927
2928 static void
2929 format_RGBA(cups_page_header2_t *header,/* I - Page header */
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 */
2937 cups_ib_t *r0, /* I - Primary image data */
2938 cups_ib_t *r1) /* I - Image data for interpolation */
2939 {
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 */
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);
2974 dither = Floyd16x16[y & 15];
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)
2990 bitmask >>= 2;
2991 else
2992 {
2993 bitmask = 128;
2994 ptr ++;
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])
3005 *ptr ^= (0xc0 & OnPixels[r0[0]]);
3006 else
3007 *ptr ^= (0xc0 & OffPixels[r0[0]]);
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
3019 ptr ++;
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
3043 ptr ++;
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
3065 ptr ++;
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);
3082 dither = Floyd16x16[y & 15];
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 :
3106 bitmask = 0xc0 >> (bitoffset & 7);
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 {
3130 bitmask = 0xc0;
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);
3206 dither = Floyd16x16[y & 15];
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 :
3261 bitmask = 0xc0 >> (bitoffset & 7);
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 {
3276 bitmask = 0xc0;
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
3328 static void
3329 format_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 */
3337 cups_ib_t *r0, /* I - Primary image data */
3338 cups_ib_t *r1) /* I - Image data for interpolation */
3339 {
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 */
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);
3368 dither = Floyd16x16[y & 15];
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 :
3386 bitmask = 0xc0 >> (bitoffset & 7);
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 {
3400 bitmask = 0xc0;
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
3446 static void
3447 format_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 */
3455 cups_ib_t *r0, /* I - Primary image data */
3456 cups_ib_t *r1) /* I - Image data for interpolation */
3457 {
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 */
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);
3492 dither = Floyd16x16[y & 15];
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);
3592 dither = Floyd16x16[y & 15];
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 :
3616 bitmask = 0xc0 >> (bitoffset & 7);
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 {
3640 bitmask = 0xc0;
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);
3710 dither = Floyd16x16[y & 15];
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 :
3765 bitmask = 0xc0 >> (bitoffset & 7);
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 {
3781 bitmask = 0xc0;
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
3835 static void
3836 format_YMCK(cups_page_header2_t *header,/* I - Page header */
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 */
3844 cups_ib_t *r0, /* I - Primary image data */
3845 cups_ib_t *r1) /* I - Image data for interpolation */
3846 {
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 */
3857 int pc, pm, py; /* CMY pixels */
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);
3883 dither = Floyd16x16[y & 15];
3884
3885 for (x = xsize ; x > 0; x --)
3886 {
3887 pc = *r0++ > dither[x & 15];
3888 pm = *r0++ > dither[x & 15];
3889 py = *r0++ > dither[x & 15];
3890
3891 if (pc && pm && py)
3892 {
3893 bitmask >>= 3;
3894 *ptr ^= bitmask;
3895 }
3896 else
3897 {
3898 if (py)
3899 *ptr ^= bitmask;
3900 bitmask >>= 1;
3901
3902 if (pm)
3903 *ptr ^= bitmask;
3904 bitmask >>= 1;
3905
3906 if (pc)
3907 *ptr ^= bitmask;
3908 bitmask >>= 1;
3909 }
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])
3928 *ptr ^= (0xc0 & OnPixels[r0[2]]);
3929 else
3930 *ptr ^= (0xc0 & OffPixels[r0[2]]);
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);
4013 dither = Floyd16x16[y & 15];
4014
4015 for (x = xsize; x > 0; x --)
4016 {
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 }
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 :
4048 bitmask = 0xc0 >> (bitoffset & 7);
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 {
4077 bitmask = 0xc0;
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);
4159 dither = Floyd16x16[y & 15];
4160
4161 for (x = xsize; x > 0; x --)
4162 {
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))
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 :
4182 bitmask = 0xc0 >> (bitoffset & 7);
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 {
4200 bitmask = 0xc0;
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
4263 static void
4264 make_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 /*
4294 * 'raster_cb()' - Validate the page header.
4295 */
4296
4297 static int /* O - 0 if OK, -1 if not */
4298 raster_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 /*
4318 * End of "$Id: imagetoraster.c 7306 2008-02-15 00:52:38Z mike $".
4319 */