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