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