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