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