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