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