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