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