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