Load cups into easysw/current.
[thirdparty/cups.git] / filter / imagetoraster.c
1 /*
2  * "$Id: imagetoraster.c 4767 2005-10-10 19:23:23Z mike $"
3  *
4  *   Image file to raster filter for the Common UNIX Printing System (CUPS).
5  *
6  *   Copyright 1993-2005 by Easy Software Products.
7  *
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:
14  *
15  *       Attn: CUPS Licensing Information
16  *       Easy Software Products
17  *       44141 Airport View Drive, Suite 204
18  *       Hollywood, Maryland 20636 USA
19  *
20  *       Voice: (301) 373-9600
21  *       EMail: cups-info@cups.org
22  *         WWW: http://www.cups.org
23  *
24  *   This file is subject to the Apple OS-Developed Software exception.
25  *
26  * Contents:
27  *
28  *   main()          - Main entry...
29  *   exec_code()     - Execute PostScript setpagedevice commands as
30  *                     appropriate.
31  *   format_CMY()    - Convert image data to CMY.
32  *   format_CMYK()   - Convert image data to CMYK.
33  *   format_K()      - Convert image data to black.
34  *   format_KCMY()   - Convert image data to KCMY.
35  *   format_KCMYcm() - Convert image data to KCMYcm.
36  *   format_RGBA()   - Convert image data to RGBA/RGBW.
37  *   format_W()      - Convert image data to luminance.
38  *   format_YMC()    - Convert image data to YMC.
39  *   format_YMCK()   - Convert image data to YMCK.
40  *   make_lut()      - Make a lookup table given gamma and brightness values.
41  */
42
43 /*
44  * Include necessary headers...
45  */
46
47 #include "common.h"
48 #include "image-private.h"
49 #include "raster.h"
50 #include <unistd.h>
51 #include <math.h>
52
53
54 /*
55  * Globals...
56  */
57
58 int     Flip = 0,                       /* Flip/mirror pages */
59         XPosition = 0,                  /* Horizontal position on page */
60         YPosition = 0,                  /* Vertical position on page */
61         Collate = 0,                    /* Collate copies? */
62         Copies = 1;                     /* Number of copies */
63 int     Floyd16x16[16][16] =            /* Traditional Floyd ordered dither */
64         {
65           { 0,   128, 32,  160, 8,   136, 40,  168,
66             2,   130, 34,  162, 10,  138, 42,  170 },
67           { 192, 64,  224, 96,  200, 72,  232, 104,
68             194, 66,  226, 98,  202, 74,  234, 106 },
69           { 48,  176, 16,  144, 56,  184, 24,  152,
70             50,  178, 18,  146, 58,  186, 26,  154 },
71           { 240, 112, 208, 80,  248, 120, 216, 88,
72             242, 114, 210, 82,  250, 122, 218, 90 },
73           { 12,  140, 44,  172, 4,   132, 36,  164,
74             14,  142, 46,  174, 6,   134, 38,  166 },
75           { 204, 76,  236, 108, 196, 68,  228, 100,
76             206, 78,  238, 110, 198, 70,  230, 102 },
77           { 60,  188, 28,  156, 52,  180, 20,  148,
78             62,  190, 30,  158, 54,  182, 22,  150 },
79           { 252, 124, 220, 92,  244, 116, 212, 84,
80             254, 126, 222, 94,  246, 118, 214, 86 },
81           { 3,   131, 35,  163, 11,  139, 43,  171,
82             1,   129, 33,  161, 9,   137, 41,  169 },
83           { 195, 67,  227, 99,  203, 75,  235, 107,
84             193, 65,  225, 97,  201, 73,  233, 105 },
85           { 51,  179, 19,  147, 59,  187, 27,  155,
86             49,  177, 17,  145, 57,  185, 25,  153 },
87           { 243, 115, 211, 83,  251, 123, 219, 91,
88             241, 113, 209, 81,  249, 121, 217, 89 },
89           { 15,  143, 47,  175, 7,   135, 39,  167,
90             13,  141, 45,  173, 5,   133, 37,  165 },
91           { 207, 79,  239, 111, 199, 71,  231, 103,
92             205, 77,  237, 109, 197, 69,  229, 101 },
93           { 63,  191, 31,  159, 55,  183, 23,  151,
94             61,  189, 29,  157, 53,  181, 21,  149 },
95           { 254, 127, 223, 95,  247, 119, 215, 87,
96             253, 125, 221, 93,  245, 117, 213, 85 }
97         };
98 int     Floyd8x8[8][8] =
99         {
100           {  0, 32,  8, 40,  2, 34, 10, 42 },
101           { 48, 16, 56, 24, 50, 18, 58, 26 },
102           { 12, 44,  4, 36, 14, 46,  6, 38 },
103           { 60, 28, 52, 20, 62, 30, 54, 22 },
104           {  3, 35, 11, 43,  1, 33,  9, 41 },
105           { 51, 19, 59, 27, 49, 17, 57, 25 },
106           { 15, 47,  7, 39, 13, 45,  5, 37 },
107           { 63, 31, 55, 23, 61, 29, 53, 21 }
108         };
109 int     Floyd4x4[4][4] =
110         {
111           {  0,  8,  2, 10 },
112           { 12,  4, 14,  6 },
113           {  3, 11,  1,  9 },
114           { 15,  7, 13,  5 }
115         };
116
117 cups_ib_t       OnPixels[256],          /* On-pixel LUT */
118                 OffPixels[256];         /* Off-pixel LUT */
119 int             Planes[] =              /* Number of planes for each colorspace */
120                 {
121                   1,                    /* CUPS_CSPACE_W */
122                   3,                    /* CUPS_CSPACE_RGB */
123                   4,                    /* CUPS_CSPACE_RGBA */
124                   1,                    /* CUPS_CSPACE_K */
125                   3,                    /* CUPS_CSPACE_CMY */
126                   3,                    /* CUPS_CSPACE_YMC */
127                   4,                    /* CUPS_CSPACE_CMYK */
128                   4,                    /* CUPS_CSPACE_YMCK */
129                   4,                    /* CUPS_CSPACE_KCMY */
130                   6,                    /* CUPS_CSPACE_KCMYcm */
131                   4,                    /* CUPS_CSPACE_GMCK */
132                   4,                    /* CUPS_CSPACE_GMCS */
133                   1,                    /* CUPS_CSPACE_WHITE */
134                   1,                    /* CUPS_CSPACE_GOLD */
135                   1,                    /* CUPS_CSPACE_SILVER */
136                   3,                    /* CUPS_CSPACE_CIEXYZ */
137                   3,                    /* CUPS_CSPACE_CIELab */
138                   4,                    /* CUPS_CSPACE_RGBW */
139                   0,                    /* ... reserved ... */
140                   0,                    /* ... reserved ... */
141                   0,                    /* ... reserved ... */
142                   0,                    /* ... reserved ... */
143                   0,                    /* ... reserved ... */
144                   0,                    /* ... reserved ... */
145                   0,                    /* ... reserved ... */
146                   0,                    /* ... reserved ... */
147                   0,                    /* ... reserved ... */
148                   0,                    /* ... reserved ... */
149                   0,                    /* ... reserved ... */
150                   0,                    /* ... reserved ... */
151                   0,                    /* ... reserved ... */
152                   0,                    /* ... reserved ... */
153                   3,                    /* CUPS_CSPACE_ICC1 */
154                   3,                    /* CUPS_CSPACE_ICC2 */
155                   3,                    /* CUPS_CSPACE_ICC3 */
156                   3,                    /* CUPS_CSPACE_ICC4 */
157                   3,                    /* CUPS_CSPACE_ICC5 */
158                   3,                    /* CUPS_CSPACE_ICC6 */
159                   3,                    /* CUPS_CSPACE_ICC7 */
160                   3,                    /* CUPS_CSPACE_ICC8 */
161                   3,                    /* CUPS_CSPACE_ICC9 */
162                   3,                    /* CUPS_CSPACE_ICCA */
163                   3,                    /* CUPS_CSPACE_ICCB */
164                   3,                    /* CUPS_CSPACE_ICCC */
165                   3,                    /* CUPS_CSPACE_ICCD */
166                   3,                    /* CUPS_CSPACE_ICCE */
167                   3                     /* CUPS_CSPACE_ICCF */
168                 };
169
170
171 /*
172  * Local functions...
173  */
174  
175 static void     exec_code(cups_page_header2_t *header, const char *code);
176 static void     format_CMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
177 static void     format_CMYK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
178 static void     format_K(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
179 static void     format_KCMYcm(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
180 static void     format_KCMY(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
181 #define         format_RGB format_CMY
182 static void     format_RGBA(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
183 static void     format_W(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
184 static void     format_YMC(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
185 static void     format_YMCK(cups_page_header2_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, cups_ib_t *r0, cups_ib_t *r1);
186 static void     make_lut(cups_ib_t *, int, float, float);
187
188
189 /*
190  * 'main()' - Main entry...
191  */
192
193 int                                     /* O - Exit status */
194 main(int  argc,                         /* I - Number of command-line arguments */
195      char *argv[])                      /* I - Command-line arguments */
196 {
197   int                   i;              /* Looping var */
198   cups_image_t          *img;           /* Image to print */
199   float                 xprint,         /* Printable area */
200                         yprint,
201                         xinches,        /* Total size in inches */
202                         yinches;
203   float                 xsize,          /* Total size in points */
204                         ysize,
205                         xsize2,
206                         ysize2;
207   float                 aspect;         /* Aspect ratio */
208   int                   xpages,         /* # x pages */
209                         ypages,         /* # y pages */
210                         xpage,          /* Current x page */
211                         ypage,          /* Current y page */
212                         xtemp,          /* Bitmap width in pixels */
213                         ytemp,          /* Bitmap height in pixels */
214                         page;           /* Current page number */
215   int                   x0, y0,         /* Corners of the page in image coords */
216                         x1, y1;
217   ppd_file_t            *ppd;           /* PPD file */
218   ppd_choice_t          *choice,        /* PPD option choice */
219                         **choices;      /* List of marked choices */
220   int                   count;          /* Number of marked choices */
221   char                  *resolution,    /* Output resolution */
222                         *media_type;    /* Media type */
223   ppd_profile_t         *profile;       /* Color profile */
224   ppd_profile_t         userprofile;    /* User-specified profile */
225   cups_raster_t         *ras;           /* Raster stream */
226   cups_page_header2_t   header;         /* Page header */
227   int                   num_options;    /* Number of print options */
228   cups_option_t         *options;       /* Print options */
229   const char            *val;           /* Option value */
230   int                   slowcollate,    /* Collate copies the slow way */
231                         slowcopies;     /* Make copies the "slow" way? */
232   float                 g;              /* Gamma correction value */
233   float                 b;              /* Brightness factor */
234   float                 zoom;           /* Zoom facter */
235   int                   xppi, yppi;     /* Pixels-per-inch */
236   int                   hue, sat;       /* Hue and saturation adjustment */
237   cups_izoom_t          *z;             /* Image zoom buffer */
238   cups_iztype_t         zoom_type;      /* Image zoom type */
239   int                   primary,        /* Primary image colorspace */
240                         secondary;      /* Secondary image colorspace */
241   cups_ib_t             *row,           /* Current row */
242                         *r0,            /* Top row */
243                         *r1;            /* Bottom row */
244   int                   y,              /* Current Y coordinate on page */
245                         iy,             /* Current Y coordinate in image */
246                         last_iy,        /* Previous Y coordinate in image */
247                         yerr0,          /* Top Y error value */
248                         yerr1,          /* Bottom Y error value */
249                         blank;          /* Blank value */
250   cups_ib_t             lut[256];       /* Gamma/brightness LUT */
251   int                   plane,          /* Current color plane */
252                         num_planes;     /* Number of color planes */
253   char                  filename[1024]; /* Name of file to print */
254
255
256  /*
257   * Make sure status messages are not buffered...
258   */
259
260   setbuf(stderr, NULL);
261
262  /*
263   * Check command-line...
264   */
265
266   if (argc < 6 || argc > 7)
267   {
268     fputs("ERROR: imagetoraster job-id user title copies options [file]\n", stderr);
269     return (1);
270   }
271
272   fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
273           argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
274
275  /*
276   * See if we need to use the imagetops and pstoraster filters instead...
277   */
278
279   options     = NULL;
280   num_options = cupsParseOptions(argv[5], 0, &options);
281
282   if (getenv("CLASSIFICATION") ||
283       cupsGetOption("page-label", num_options, options))
284   {
285    /*
286     * Yes, fork a copy of pstoraster and then transfer control to imagetops...
287     */
288
289     int mypipes[2];             /* New pipes for imagetops | pstoraster */
290     int pid;                    /* PID of pstoraster */
291
292
293     cupsFreeOptions(num_options, options);
294
295     if (pipe(mypipes))
296     {
297       perror("ERROR: Unable to create pipes for imagetops | pstoraster");
298       return (errno);
299     }
300
301     if ((pid = fork()) == 0)
302     {
303      /*
304       * Child process for pstoraster...  Assign new pipe input to pstoraster...
305       */
306
307       close(0);
308       dup(mypipes[0]);
309       close(mypipes[0]);
310       close(mypipes[1]);
311
312       execlp("pstoraster", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
313              NULL);
314       perror("ERROR: Unable to exec pstoraster");
315       return (errno);
316     }
317     else if (pid < 0)
318     {
319      /*
320       * Error!
321       */
322
323       perror("ERROR: Unable to fork pstoraster");
324       return (errno);
325     }
326
327    /*
328     * Update stdout so it points at the new pstoraster...
329     */
330
331     close(1);
332     dup(mypipes[1]);
333     close(mypipes[0]);
334     close(mypipes[1]);
335
336    /*
337     * Run imagetops to get the classification or page labelling that was
338     * requested...
339     */
340
341     execlp("imagetops", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
342            argv[6], NULL);
343     perror("ERROR: Unable to exec imagetops");
344     return (errno);
345   }
346
347  /*
348   * Copy stdin as needed...
349   */
350
351   if (argc == 6)
352   {
353     int         fd;             /* File to write to */
354     char        buffer[8192];   /* Buffer to read into */
355     int         bytes;          /* # of bytes to read */
356
357
358     if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
359     {
360       perror("ERROR: Unable to copy image file");
361       return (1);
362     }
363
364     fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
365             filename);
366
367     while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
368       write(fd, buffer, bytes);
369
370     close(fd);
371   }
372   else
373     strlcpy(filename, argv[6], sizeof(filename));
374
375  /*
376   * Process command-line options and write the prolog...
377   */
378
379   zoom = 0.0;
380   xppi = 0;
381   yppi = 0;
382   hue  = 0;
383   sat  = 100;
384   g    = 1.0;
385   b    = 1.0;
386
387   Copies = atoi(argv[4]);
388
389   ppd = SetCommonOptions(num_options, options, 0);
390
391   if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
392   {
393    /*
394     * This IPP attribute is unnecessarily complicated...
395     *
396     *   single-document, separate-documents-collated-copies, and
397     *   single-document-new-sheet all require collated copies.
398     *
399     *   separate-documents-collated-copies allows for uncollated copies.
400     */
401
402     Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
403   }
404
405   if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
406       strcasecmp(val, "True") == 0)
407     Collate = 1;
408
409   if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
410     g = atoi(val) * 0.001f;
411
412   if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
413     b = atoi(val) * 0.01f;
414
415   if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
416     zoom = atoi(val) * 0.01;
417
418   if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
419     if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
420       yppi = xppi;
421
422   if ((val = cupsGetOption("position", num_options, options)) != NULL)
423   {
424     if (strcasecmp(val, "center") == 0)
425     {
426       XPosition = 0;
427       YPosition = 0;
428     }
429     else if (strcasecmp(val, "top") == 0)
430     {
431       XPosition = 0;
432       YPosition = 1;
433     }
434     else if (strcasecmp(val, "left") == 0)
435     {
436       XPosition = -1;
437       YPosition = 0;
438     }
439     else if (strcasecmp(val, "right") == 0)
440     {
441       XPosition = 1;
442       YPosition = 0;
443     }
444     else if (strcasecmp(val, "top-left") == 0)
445     {
446       XPosition = -1;
447       YPosition = 1;
448     }
449     else if (strcasecmp(val, "top-right") == 0)
450     {
451       XPosition = 1;
452       YPosition = 1;
453     }
454     else if (strcasecmp(val, "bottom") == 0)
455     {
456       XPosition = 0;
457       YPosition = -1;
458     }
459     else if (strcasecmp(val, "bottom-left") == 0)
460     {
461       XPosition = -1;
462       YPosition = -1;
463     }
464     else if (strcasecmp(val, "bottom-right") == 0)
465     {
466       XPosition = 1;
467       YPosition = -1;
468     }
469   }
470
471   if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
472     sat = atoi(val);
473
474   if ((val = cupsGetOption("hue", num_options, options)) != NULL)
475     hue = atoi(val);
476
477   if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
478       strcasecmp(val, "True") == 0)
479     Flip = 1;
480
481  /*
482   * Set the needed options in the page header...
483   */
484
485   memset(&header, 0, sizeof(header));
486   header.HWResolution[0]  = 100;
487   header.HWResolution[1]  = 100;
488   header.cupsBitsPerColor = 1;
489   header.cupsColorOrder   = CUPS_ORDER_CHUNKED;
490   header.cupsColorSpace   = CUPS_CSPACE_K;
491
492   if (ppd && ppd->patches)
493     exec_code(&header, ppd->patches);
494
495   if ((count = ppdCollect(ppd, PPD_ORDER_DOCUMENT, &choices)) > 0)
496     for (i = 0; i < count; i ++)
497       exec_code(&header, choices[i]->code);
498
499   if ((count = ppdCollect(ppd, PPD_ORDER_ANY, &choices)) > 0)
500     for (i = 0; i < count; i ++)
501       exec_code(&header, choices[i]->code);
502
503   if ((count = ppdCollect(ppd, PPD_ORDER_PROLOG, &choices)) > 0)
504     for (i = 0; i < count; i ++)
505       exec_code(&header, choices[i]->code);
506
507   if ((count = ppdCollect(ppd, PPD_ORDER_PAGE, &choices)) > 0)
508     for (i = 0; i < count; i ++)
509       exec_code(&header, choices[i]->code);
510
511  /*
512   * Get the media type and resolution that have been chosen...
513   */
514
515   if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
516     media_type = choice->choice;
517   else
518     media_type = "";
519
520   if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
521     resolution = choice->choice;
522   else
523     resolution = "";
524
525  /*
526   * Choose the appropriate colorspace...
527   */
528
529   switch (header.cupsColorSpace)
530   {
531     case CUPS_CSPACE_W :
532         primary   = CUPS_IMAGE_WHITE;
533         secondary = CUPS_IMAGE_WHITE;
534         header.cupsBitsPerPixel = header.cupsBitsPerColor;
535         break;
536
537     default :
538     case CUPS_CSPACE_RGB :
539     case CUPS_CSPACE_RGBA :
540     case CUPS_CSPACE_RGBW :
541         primary   = CUPS_IMAGE_RGB;
542         secondary = CUPS_IMAGE_RGB;
543
544        /*
545         * Ensure that colorimetric colorspaces use at least 8 bits per
546         * component...
547         */
548
549         if (header.cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
550             header.cupsBitsPerColor < 8)
551           header.cupsBitsPerColor = 8;
552
553         if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
554         {
555           if (header.cupsBitsPerColor >= 8)
556             header.cupsBitsPerPixel = header.cupsBitsPerColor * 3;
557           else
558             header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
559         }
560         else
561           header.cupsBitsPerPixel = header.cupsBitsPerColor;
562         break;
563
564     case CUPS_CSPACE_K :
565     case CUPS_CSPACE_WHITE :
566     case CUPS_CSPACE_GOLD :
567     case CUPS_CSPACE_SILVER :
568         primary   = CUPS_IMAGE_BLACK;
569         secondary = CUPS_IMAGE_BLACK;
570         header.cupsBitsPerPixel = header.cupsBitsPerColor;
571         break;
572
573     case CUPS_CSPACE_CMYK :
574     case CUPS_CSPACE_YMCK :
575     case CUPS_CSPACE_KCMY :
576     case CUPS_CSPACE_GMCK :
577     case CUPS_CSPACE_GMCS :
578         primary   = CUPS_IMAGE_CMYK;
579         secondary = CUPS_IMAGE_CMYK;
580
581         if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
582           header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
583         else
584           header.cupsBitsPerPixel = header.cupsBitsPerColor;
585         break;
586
587     case CUPS_CSPACE_CMY :
588     case CUPS_CSPACE_YMC :
589         primary   = CUPS_IMAGE_CMY;
590         secondary = CUPS_IMAGE_CMY;
591
592         if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
593         {
594           if (header.cupsBitsPerColor >= 8)
595             header.cupsBitsPerPixel = 24;
596           else
597             header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
598         }
599         else
600           header.cupsBitsPerPixel = header.cupsBitsPerColor;
601         break;
602
603     case CUPS_CSPACE_KCMYcm :
604         if (header.cupsBitsPerPixel == 1)
605         {
606           primary   = CUPS_IMAGE_CMY;
607           secondary = CUPS_IMAGE_CMY;
608
609           if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
610             header.cupsBitsPerPixel = 8;
611           else
612             header.cupsBitsPerPixel = 1;
613         }
614         else
615         {
616           primary   = CUPS_IMAGE_CMYK;
617           secondary = CUPS_IMAGE_CMYK;
618
619           if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
620             header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
621           else
622             header.cupsBitsPerPixel = header.cupsBitsPerColor;
623         }
624         break;
625   }
626
627  /*
628   * Find a color profile matching the current options...
629   */
630
631   if ((val = cupsGetOption("profile", num_options, options)) != NULL)
632   {
633     profile = &userprofile;
634     sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
635            &(userprofile.density), &(userprofile.gamma),
636            userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
637            userprofile.matrix[0] + 2,
638            userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
639            userprofile.matrix[1] + 2,
640            userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
641            userprofile.matrix[2] + 2);
642
643     userprofile.density      *= 0.001f;
644     userprofile.gamma        *= 0.001f;
645     userprofile.matrix[0][0] *= 0.001f;
646     userprofile.matrix[0][1] *= 0.001f;
647     userprofile.matrix[0][2] *= 0.001f;
648     userprofile.matrix[1][0] *= 0.001f;
649     userprofile.matrix[1][1] *= 0.001f;
650     userprofile.matrix[1][2] *= 0.001f;
651     userprofile.matrix[2][0] *= 0.001f;
652     userprofile.matrix[2][1] *= 0.001f;
653     userprofile.matrix[2][2] *= 0.001f;
654   }
655   else if (ppd != NULL)
656   {
657     fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
658             resolution, media_type);
659
660     for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
661     {
662       fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
663               profile->media_type);
664
665       if ((strcmp(profile->resolution, resolution) == 0 ||
666            profile->resolution[0] == '-') &&
667           (strcmp(profile->media_type, media_type) == 0 ||
668            profile->media_type[0] == '-'))
669       {
670         fputs("MATCH!\n", stderr);
671         break;
672       }
673       else
674         fputs("no.\n", stderr);
675     }
676
677    /*
678     * If we found a color profile, use it!
679     */
680
681     if (i >= ppd->num_profiles)
682       profile = NULL;
683   }
684   else
685     profile = NULL;
686
687   if (profile)
688     cupsImageSetProfile(profile->density, profile->gamma, profile->matrix);
689
690   cupsImageSetRasterColorSpace(header.cupsColorSpace);
691
692  /*
693   * Create a gamma/brightness LUT...
694   */
695
696   make_lut(lut, primary, g, b);
697
698  /*
699   * Open the input image to print...
700   */
701
702   fputs("INFO: Loading image file...\n", stderr);
703
704   img = cupsImageOpen(filename, primary, secondary, sat, hue, lut);
705
706   if (argc == 6)
707     unlink(filename);
708
709   if (img == NULL)
710   {
711     fputs("ERROR: Unable to open image file for printing!\n", stderr);
712     ppdClose(ppd);
713     return (1);
714   }
715
716  /*
717   * Scale as necessary...
718   */
719
720   if (zoom == 0.0 && xppi == 0)
721   {
722     xppi = img->xppi;
723     yppi = img->yppi;
724   }
725
726   if (yppi == 0)
727     yppi = xppi;
728
729   fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
730           xppi, yppi, zoom);
731
732   if (xppi > 0)
733   {
734    /*
735     * Scale the image as neccesary to match the desired pixels-per-inch.
736     */
737     
738     if (Orientation & 1)
739     {
740       xprint = (PageTop - PageBottom) / 72.0;
741       yprint = (PageRight - PageLeft) / 72.0;
742     }
743     else
744     {
745       xprint = (PageRight - PageLeft) / 72.0;
746       yprint = (PageTop - PageBottom) / 72.0;
747     }
748
749     fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
750             xprint, yprint);
751
752     xinches = (float)img->xsize / (float)xppi;
753     yinches = (float)img->ysize / (float)yppi;
754
755     fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
756             xinches, yinches);
757
758     if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
759     {
760       xinches = xinches * atoi(val) / 100;
761       yinches = yinches * atoi(val) / 100;
762     }
763
764     if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
765         cupsGetOption("landscape", num_options, options) == NULL)
766     {
767      /*
768       * Rotate the image if it will fit landscape but not portrait...
769       */
770
771       fputs("DEBUG: Auto orientation...\n", stderr);
772
773       if ((xinches > xprint || yinches > yprint) &&
774           xinches <= yprint && yinches <= xprint)
775       {
776        /*
777         * Rotate the image as needed...
778         */
779
780         fputs("DEBUG: Using landscape orientation...\n", stderr);
781
782         Orientation = (Orientation + 1) & 3;
783         xsize       = yprint;
784         yprint      = xprint;
785         xprint      = xsize;
786       }
787     }
788   }
789   else
790   {
791    /*
792     * Scale percentage of page size...
793     */
794
795     xprint = (PageRight - PageLeft) / 72.0;
796     yprint = (PageTop - PageBottom) / 72.0;
797     aspect = (float)img->yppi / (float)img->xppi;
798
799     fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
800             xprint, yprint);
801
802     fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
803             img->xppi, img->yppi, aspect);
804
805     xsize = xprint * zoom;
806     ysize = xsize * img->ysize / img->xsize / aspect;
807
808     if (ysize > (yprint * zoom))
809     {
810       ysize = yprint * zoom;
811       xsize = ysize * img->xsize * aspect / img->ysize;
812     }
813
814     xsize2 = yprint * zoom;
815     ysize2 = xsize2 * img->ysize / img->xsize / aspect;
816
817     if (ysize2 > (xprint * zoom))
818     {
819       ysize2 = xprint * zoom;
820       xsize2 = ysize2 * img->xsize * aspect / img->ysize;
821     }
822
823     fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
824     fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
825
826     if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
827         cupsGetOption("landscape", num_options, options) == NULL)
828     {
829      /*
830       * Choose the rotation with the largest area, but prefer
831       * portrait if they are equal...
832       */
833
834       fputs("DEBUG: Auto orientation...\n", stderr);
835
836       if ((xsize * ysize) < (xsize2 * xsize2))
837       {
838        /*
839         * Do landscape orientation...
840         */
841
842         fputs("DEBUG: Using landscape orientation...\n", stderr);
843
844         Orientation = 1;
845         xinches     = xsize2;
846         yinches     = ysize2;
847         xprint      = (PageTop - PageBottom) / 72.0;
848         yprint      = (PageRight - PageLeft) / 72.0;
849       }
850       else
851       {
852        /*
853         * Do portrait orientation...
854         */
855
856         fputs("DEBUG: Using portrait orientation...\n", stderr);
857
858         Orientation = 0;
859         xinches     = xsize;
860         yinches     = ysize;
861       }
862     }
863     else if (Orientation & 1)
864     {
865       fputs("DEBUG: Using landscape orientation...\n", stderr);
866
867       xinches     = xsize2;
868       yinches     = ysize2;
869       xprint      = (PageTop - PageBottom) / 72.0;
870       yprint      = (PageRight - PageLeft) / 72.0;
871     }
872     else
873     {
874       fputs("DEBUG: Using portrait orientation...\n", stderr);
875
876       xinches     = xsize;
877       yinches     = ysize;
878       xprint      = (PageRight - PageLeft) / 72.0;
879       yprint      = (PageTop - PageBottom) / 72.0;
880     }
881   }
882
883  /*
884   * Compute the number of pages to print and the size of the image on each
885   * page...
886   */
887
888   xpages = ceil(xinches / xprint);
889   ypages = ceil(yinches / yprint);
890
891   xprint = xinches / xpages;
892   yprint = yinches / ypages;
893
894   fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
895           xpages, xprint, ypages, yprint);
896
897  /*
898   * Compute the bitmap size...
899   */
900
901   if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
902       strcasecmp(choice->choice, "Custom") == 0)
903   {
904     float       width,          /* New width in points */
905                 length;         /* New length in points */
906
907
908    /*
909     * Use the correct width and length for the current orientation...
910     */
911
912     if (Orientation & 1)
913     {
914       width  = yprint * 72.0;
915       length = xprint * 72.0;
916     }
917     else
918     {
919       width  = xprint * 72.0;
920       length = yprint * 72.0;
921     }
922
923    /*
924     * Add margins to page size...
925     */
926
927     width  += ppd->custom_margins[0] + ppd->custom_margins[2];
928     length += ppd->custom_margins[1] + ppd->custom_margins[3];
929
930    /*
931     * Enforce minimums...
932     */
933
934     if (width < ppd->custom_min[0])
935       width = ppd->custom_min[0];
936
937     if (length < ppd->custom_min[1])
938       length = ppd->custom_min[1];
939
940     fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
941             width / 72.0, length / 72.0);
942
943    /*
944     * Set the new custom size...
945     */
946
947     header.PageSize[0] = width + 0.5;
948     header.PageSize[1] = length + 0.5;
949
950    /*
951     * Update page variables...
952     */
953
954     PageWidth  = width;
955     PageLength = length;
956     PageLeft   = ppd->custom_margins[0];
957     PageRight  = width - ppd->custom_margins[2];
958     PageBottom = ppd->custom_margins[1];
959     PageTop    = length - ppd->custom_margins[3];
960
961    /*
962     * Remove margins from page size...
963     */
964
965     width  -= ppd->custom_margins[0] + ppd->custom_margins[2];
966     length -= ppd->custom_margins[1] + ppd->custom_margins[3];
967
968    /*
969     * Set the bitmap size...
970     */
971
972     header.cupsWidth  = width * header.HWResolution[0] / 72.0;
973     header.cupsHeight = length * header.HWResolution[1] / 72.0;
974   }
975   else
976   {
977     header.cupsWidth   = (PageRight - PageLeft) * header.HWResolution[0] / 72.0;
978     header.cupsHeight  = (PageTop - PageBottom) * header.HWResolution[1] / 72.0;
979     header.PageSize[0] = PageWidth;
980     header.PageSize[1] = PageLength;
981   }
982
983   header.Margins[0] = PageLeft;
984   header.Margins[1] = PageBottom;
985
986   fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
987           header.PageSize[1]);
988
989   switch (Orientation)
990   {
991     default :
992         switch (XPosition)
993         {
994           case -1 :
995               header.ImagingBoundingBox[0] = PageLeft;
996               header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
997               break;
998           default :
999               header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
1000               header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
1001               break;
1002           case 1 :
1003               header.ImagingBoundingBox[0] = PageRight - xprint * 72;
1004               header.ImagingBoundingBox[2] = PageRight;
1005               break;
1006         }
1007
1008         switch (YPosition)
1009         {
1010           case -1 :
1011               header.ImagingBoundingBox[1] = PageBottom;
1012               header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
1013               break;
1014           default :
1015               header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1016               header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
1017               break;
1018           case 1 :
1019               header.ImagingBoundingBox[1] = PageTop - yprint * 72;
1020               header.ImagingBoundingBox[3] = PageTop;
1021               break;
1022         }
1023         break;
1024
1025     case 1 :
1026         switch (XPosition)
1027         {
1028           case -1 :
1029               header.ImagingBoundingBox[0] = PageBottom;
1030               header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
1031               break;
1032           default :
1033               header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
1034               header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
1035               break;
1036           case 1 :
1037               header.ImagingBoundingBox[0] = PageTop - yprint * 72;
1038               header.ImagingBoundingBox[2] = PageTop;
1039               break;
1040         }
1041
1042         switch (YPosition)
1043         {
1044           case -1 :
1045               header.ImagingBoundingBox[1] = PageLeft;
1046               header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
1047               break;
1048           default :
1049               header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
1050               header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
1051               break;
1052           case 1 :
1053               header.ImagingBoundingBox[1] = PageRight - xprint * 72;
1054               header.ImagingBoundingBox[3] = PageRight;
1055               break;
1056         }
1057         break;
1058
1059     case 2 :
1060         switch (XPosition)
1061         {
1062           case 1 :
1063               header.ImagingBoundingBox[0] = PageLeft;
1064               header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
1065               break;
1066           default :
1067               header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
1068               header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
1069               break;
1070           case -1 :
1071               header.ImagingBoundingBox[0] = PageRight - xprint * 72;
1072               header.ImagingBoundingBox[2] = PageRight;
1073               break;
1074         }
1075
1076         switch (YPosition)
1077         {
1078           case 1 :
1079               header.ImagingBoundingBox[1] = PageBottom;
1080               header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
1081               break;
1082           default :
1083               header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
1084               header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
1085               break;
1086           case -1 :
1087               header.ImagingBoundingBox[1] = PageTop - yprint * 72;
1088               header.ImagingBoundingBox[3] = PageTop;
1089               break;
1090         }
1091         break;
1092
1093     case 3 :
1094         switch (XPosition)
1095         {
1096           case 1 :
1097               header.ImagingBoundingBox[0] = PageBottom;
1098               header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
1099               break;
1100           default :
1101               header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
1102               header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
1103               break;
1104           case -1 :
1105               header.ImagingBoundingBox[0] = PageTop - yprint * 72;
1106               header.ImagingBoundingBox[2] = PageTop;
1107               break;
1108         }
1109
1110         switch (YPosition)
1111         {
1112           case 1 :
1113               header.ImagingBoundingBox[1] = PageLeft;
1114               header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
1115               break;
1116           default :
1117               header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
1118               header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
1119               break;
1120           case -1 :
1121               header.ImagingBoundingBox[1] = PageRight - xprint * 72;
1122               header.ImagingBoundingBox[3] = PageRight;
1123               break;
1124         }
1125         break;
1126   }
1127
1128   switch (header.cupsColorOrder)
1129   {
1130     default :
1131         header.cupsBytesPerLine = (header.cupsBitsPerPixel *
1132                                    header.cupsWidth + 7) / 8;
1133         num_planes = 1;
1134         break;
1135
1136     case CUPS_ORDER_BANDED :
1137         if (header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
1138             header.cupsBitsPerColor > 1)
1139           header.cupsBytesPerLine = (header.cupsBitsPerPixel *
1140                                      header.cupsWidth + 7) / 8 * 4;
1141         else
1142           header.cupsBytesPerLine = (header.cupsBitsPerPixel *
1143                                      header.cupsWidth + 7) / 8 *
1144                                     Planes[header.cupsColorSpace];
1145         num_planes = 1;
1146         break;
1147
1148     case CUPS_ORDER_PLANAR :
1149         header.cupsBytesPerLine = (header.cupsBitsPerPixel *
1150                                    header.cupsWidth + 7) / 8;
1151         num_planes = Planes[header.cupsColorSpace];
1152         break;
1153   }
1154
1155  if (header.cupsBitsPerColor >= 8)
1156    zoom_type = CUPS_IZOOM_NORMAL;
1157  else
1158    zoom_type = CUPS_IZOOM_FAST;
1159
1160  /*
1161   * See if we need to collate, and if so how we need to do it...
1162   */
1163
1164   if (xpages == 1 && ypages == 1)
1165     Collate = 0;
1166
1167   slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
1168   if (ppd != NULL)
1169     slowcopies = ppd->manual_copies;
1170   else
1171     slowcopies = 1;
1172
1173   if (Copies > 1 && !slowcollate && !slowcopies)
1174   {
1175     header.Collate   = (cups_bool_t)Collate;
1176     header.NumCopies = Copies;
1177
1178     Copies = 1;
1179   }
1180   else
1181     header.NumCopies = 1;
1182
1183  /*
1184   * Create the dithering lookup tables...
1185   */
1186
1187   OnPixels[0]    = 0x00;
1188   OnPixels[255]  = 0xff;
1189   OffPixels[0]   = 0x00;
1190   OffPixels[255] = 0xff;
1191
1192   switch (header.cupsBitsPerColor)
1193   {
1194     case 2 :
1195         for (i = 1; i < 255; i ++)
1196         {
1197           OnPixels[i]  = 0x55 * (i / 85 + 1);
1198           OffPixels[i] = 0x55 * (i / 64);
1199         }
1200         break;
1201     case 4 :
1202         for (i = 1; i < 255; i ++)
1203         {
1204           OnPixels[i]  = 17 * (i / 17 + 1);
1205           OffPixels[i] = 17 * (i / 16);
1206         }
1207
1208         OnPixels[255] = OffPixels[255] = 0xff;
1209         break;
1210   }
1211
1212  /*
1213   * Output the pages...
1214   */
1215
1216   fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
1217   fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
1218   fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
1219   fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
1220   fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
1221   fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
1222   fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
1223   fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
1224
1225   row   = malloc(2 * header.cupsBytesPerLine);
1226   ras   = cupsRasterOpen(1, CUPS_RASTER_WRITE);
1227   blank = img->colorspace < 0 ? 0 : ~0;
1228
1229   for (i = 0, page = 1; i < Copies; i ++)
1230     for (xpage = 0; xpage < xpages; xpage ++)
1231       for (ypage = 0; ypage < ypages; ypage ++, page ++)
1232       {
1233         fprintf(stderr, "INFO: Formatting page %d...\n", page);
1234
1235         if (Orientation & 1)
1236         {
1237           x0    = img->xsize * ypage / ypages;
1238           x1    = img->xsize * (ypage + 1) / ypages - 1;
1239           y0    = img->ysize * xpage / xpages;
1240           y1    = img->ysize * (xpage + 1) / xpages - 1;
1241
1242           xtemp = header.HWResolution[0] * yprint;
1243           ytemp = header.HWResolution[1] * xprint;
1244         }
1245         else
1246         {
1247           x0    = img->xsize * xpage / xpages;
1248           x1    = img->xsize * (xpage + 1) / xpages - 1;
1249           y0    = img->ysize * ypage / ypages;
1250           y1    = img->ysize * (ypage + 1) / ypages - 1;
1251
1252           xtemp = header.HWResolution[0] * xprint;
1253           ytemp = header.HWResolution[1] * yprint;
1254         }
1255
1256         cupsRasterWriteHeader2(ras, &header);
1257
1258         for (plane = 0; plane < num_planes; plane ++)
1259         {
1260          /*
1261           * Initialize the image "zoom" engine...
1262           */
1263
1264           if (Flip)
1265             z = cupsImageZoomNew(img, x0, y0, x1, y1, -xtemp, ytemp,
1266                                  Orientation & 1, zoom_type);
1267           else
1268             z = cupsImageZoomNew(img, x0, y0, x1, y1, xtemp, ytemp,
1269                                  Orientation & 1, zoom_type);
1270
1271          /*
1272           * Write leading blank space as needed...
1273           */
1274
1275           if (header.cupsHeight > z->ysize && YPosition <= 0)
1276           {
1277             memset(row, blank, header.cupsBytesPerLine);
1278
1279             y = header.cupsHeight - z->ysize;
1280             if (YPosition == 0)
1281               y /= 2;
1282
1283             for (; y > 0; y --)
1284             {
1285               if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1286                       header.cupsBytesPerLine)
1287               {
1288                 fputs("ERROR: Unable to write raster data to driver!\n", stderr);
1289                 cupsImageClose(img);
1290                 exit(1);
1291               }
1292             }
1293           }
1294
1295          /*
1296           * Then write image data...
1297           */
1298
1299           for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
1300                y > 0;
1301                y --)
1302           {
1303             if (iy != last_iy)
1304             {
1305               if (zoom_type != CUPS_IZOOM_FAST && (iy - last_iy) > 1)
1306                 cupsImageZoomFill(z, iy);
1307
1308               cupsImageZoomFill(z, iy + z->yincr);
1309
1310               last_iy = iy;
1311             }
1312
1313            /*
1314             * Format this line of raster data for the printer...
1315             */
1316
1317             memset(row, blank, header.cupsBytesPerLine);
1318
1319             r0 = z->rows[z->row];
1320             r1 = z->rows[1 - z->row];
1321
1322             switch (header.cupsColorSpace)
1323             {
1324               case CUPS_CSPACE_W :
1325                   format_W(&header, row, y, plane, z->xsize, z->ysize,
1326                            yerr0, yerr1, r0, r1);
1327                   break;
1328               default :
1329               case CUPS_CSPACE_RGB :
1330                   format_RGB(&header, row, y, plane, z->xsize, z->ysize,
1331                              yerr0, yerr1, r0, r1);
1332                   break;
1333               case CUPS_CSPACE_RGBA :
1334               case CUPS_CSPACE_RGBW :
1335                   format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
1336                               yerr0, yerr1, r0, r1);
1337                   break;
1338               case CUPS_CSPACE_K :
1339               case CUPS_CSPACE_WHITE :
1340               case CUPS_CSPACE_GOLD :
1341               case CUPS_CSPACE_SILVER :
1342                   format_K(&header, row, y, plane, z->xsize, z->ysize,
1343                            yerr0, yerr1, r0, r1);
1344                   break;
1345               case CUPS_CSPACE_CMY :
1346                   format_CMY(&header, row, y, plane, z->xsize, z->ysize,
1347                              yerr0, yerr1, r0, r1);
1348                   break;
1349               case CUPS_CSPACE_YMC :
1350                   format_YMC(&header, row, y, plane, z->xsize, z->ysize,
1351                              yerr0, yerr1, r0, r1);
1352                   break;
1353               case CUPS_CSPACE_CMYK :
1354                   format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
1355                               yerr0, yerr1, r0, r1);
1356                   break;
1357               case CUPS_CSPACE_YMCK :
1358               case CUPS_CSPACE_GMCK :
1359               case CUPS_CSPACE_GMCS :
1360                   format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
1361                               yerr0, yerr1, r0, r1);
1362                   break;
1363               case CUPS_CSPACE_KCMY :
1364                   format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
1365                               yerr0, yerr1, r0, r1);
1366                   break;
1367               case CUPS_CSPACE_KCMYcm :
1368                   format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
1369                                 yerr0, yerr1, r0, r1);
1370                   break;
1371             }
1372
1373            /*
1374             * Write the raster data to the driver...
1375             */
1376
1377             if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1378                                       header.cupsBytesPerLine)
1379             {
1380               fputs("ERROR: Unable to write raster data to driver!\n", stderr);
1381               cupsImageClose(img);
1382               exit(1);
1383             }
1384
1385            /*
1386             * Compute the next scanline in the image...
1387             */
1388
1389             iy    += z->ystep;
1390             yerr0 += z->ymod;
1391             yerr1 -= z->ymod;
1392             if (yerr1 <= 0)
1393             {
1394               yerr0 -= z->ysize;
1395               yerr1 += z->ysize;
1396               iy    += z->yincr;
1397             }
1398           }
1399
1400          /*
1401           * Write trailing blank space as needed...
1402           */
1403
1404           if (header.cupsHeight > z->ysize && YPosition >= 0)
1405           {
1406             memset(row, blank, header.cupsBytesPerLine);
1407
1408             y = header.cupsHeight - z->ysize;
1409             if (YPosition == 0)
1410               y = y - y / 2;
1411
1412             for (; y > 0; y --)
1413             {
1414               if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
1415                       header.cupsBytesPerLine)
1416               {
1417                 fputs("ERROR: Unable to write raster data to driver!\n", stderr);
1418                 cupsImageClose(img);
1419                 exit(1);
1420               }
1421             }
1422           }
1423
1424          /*
1425           * Free memory used for the "zoom" engine...
1426           */
1427
1428           cupsImageZoomDelete(z);
1429         }
1430       }
1431
1432  /*
1433   * Close files...
1434   */
1435
1436   free(row);
1437   cupsRasterClose(ras);
1438   cupsImageClose(img);
1439   ppdClose(ppd);
1440
1441   return (0);
1442 }
1443
1444
1445 /*
1446  * 'exec_code()' - Execute PostScript setpagedevice commands as appropriate.
1447  */
1448
1449 static void
1450 exec_code(cups_page_header2_t *header,  /* I - Page header */
1451           const char          *code)    /* I - Option choice to execute */
1452 {
1453   char  *ptr,                           /* Pointer into name/value string */
1454         name[255],                      /* Name of pagedevice entry */
1455         value[1024];                    /* Value of pagedevice entry */
1456
1457
1458   for (; *code != '\0';)
1459   {
1460    /*
1461     * Search for the start of a dictionary name...
1462     */
1463
1464     while (*code != '/' && *code != '\0')
1465       code ++;
1466
1467     if (*code == '\0')
1468       break;
1469
1470    /*
1471     * Get the name...
1472     */
1473
1474     code ++;
1475     for (ptr = name; isalnum(*code & 255) && (ptr - name) < (sizeof(name) - 1);)
1476       *ptr++ = *code++;
1477     *ptr = '\0';
1478
1479    /*
1480     * The parse the value as needed...
1481     */
1482
1483     while (isspace(*code & 255))
1484       code ++;
1485
1486     if (*code == '\0')
1487       break;
1488
1489     if (*code == '[')
1490     {
1491      /*
1492       * Read array of values...
1493       */
1494
1495       code ++;
1496       for (ptr = value;
1497            *code != ']' && *code != '\0' &&
1498                (ptr - value) < (sizeof(value) - 1);)
1499         *ptr++ = *code++;
1500       *ptr = '\0';
1501     }
1502     else if (*code == '(')
1503     {
1504      /*
1505       * Read string value...
1506       */
1507
1508       code ++;
1509       for (ptr = value;
1510            *code != ')' && *code != '\0' &&
1511                (ptr - value) < (sizeof(value) - 1);)
1512         if (*code == '\\')
1513         {
1514           code ++;
1515           if (isdigit(*code & 255))
1516             *ptr++ = (char)strtol(code, (char **)&code, 8);
1517           else
1518             *ptr++ = *code++;
1519         }
1520         else
1521           *ptr++ = *code++;
1522
1523       *ptr = '\0';
1524     }
1525     else if (isdigit(*code & 255) || *code == '-')
1526     {
1527      /*
1528       * Read single number...
1529       */
1530
1531       for (ptr = value;
1532            (isdigit(*code & 255) || *code == '-') &&
1533                (ptr - value) < (sizeof(value) - 1);)
1534         *ptr++ = *code++;
1535       *ptr = '\0';
1536     }
1537     else
1538     {
1539      /*
1540       * Read a single name...
1541       */
1542
1543       for (ptr = value;
1544            (isalnum(*code & 255) || *code == '_') &&
1545                (ptr - value) < (sizeof(value) - 1);)
1546         *ptr++ = *code++;
1547       *ptr = '\0';
1548     }
1549
1550    /*
1551     * Assign the value as needed...
1552     */
1553
1554     if (!strcmp(name, "MediaClass"))
1555       strlcpy(header->MediaClass, value, sizeof(header->MediaClass));
1556     else if (!strcmp(name, "MediaColor"))
1557       strlcpy(header->MediaColor, value, sizeof(header->MediaColor));
1558     else if (!strcmp(name, "MediaType"))
1559       strlcpy(header->MediaType, value, sizeof(header->MediaType));
1560     else if (!strcmp(name, "OutputType"))
1561       strlcpy(header->OutputType, value, sizeof(header->OutputType));
1562     else if (!strcmp(name, "AdvanceDistance"))
1563       header->AdvanceDistance = atoi(value);
1564     else if (!strcmp(name, "AdvanceMedia"))
1565       header->AdvanceMedia = atoi(value);
1566     else if (!strcmp(name, "Collate"))
1567       header->Collate = !strcmp(value, "true");
1568     else if (!strcmp(name, "CutMedia"))
1569       header->CutMedia = (cups_cut_t)atoi(value);
1570     else if (!strcmp(name, "Duplex"))
1571       header->Duplex = !strcmp(value, "true");
1572     else if (!strcmp(name, "HWResolution"))
1573       sscanf(value, "%d%d", header->HWResolution + 0, header->HWResolution + 1);
1574     else if (!strcmp(name, "InsertSheet"))
1575       header->InsertSheet = !strcmp(value, "true");
1576     else if (!strcmp(name, "Jog"))
1577       header->Jog = atoi(value);
1578     else if (!strcmp(name, "LeadingEdge"))
1579       header->LeadingEdge = atoi(value);
1580     else if (!strcmp(name, "Margins"))
1581       sscanf(value, "%d%d", header->Margins + 0, header->Margins + 1);
1582     else if (!strcmp(name, "ManualFeed"))
1583       header->ManualFeed = !strcmp(value, "true");
1584     else if (!strcmp(name, "cupsMediaPosition") || /* Compatibility */
1585              !strcmp(name, "MediaPosition"))
1586       header->MediaPosition = atoi(value);
1587     else if (!strcmp(name, "MediaWeight"))
1588       header->MediaWeight = atoi(value);
1589     else if (!strcmp(name, "MirrorPrint"))
1590       header->MirrorPrint = !strcmp(value, "true");
1591     else if (!strcmp(name, "NegativePrint"))
1592       header->NegativePrint = !strcmp(value, "true");
1593     else if (!strcmp(name, "Orientation"))
1594       header->Orientation = atoi(value);
1595     else if (!strcmp(name, "OutputFaceUp"))
1596       header->OutputFaceUp = !strcmp(value, "true");
1597     else if (!strcmp(name, "Separations"))
1598       header->Separations = !strcmp(value, "true");
1599     else if (!strcmp(name, "TraySwitch"))
1600       header->TraySwitch = !strcmp(value, "true");
1601     else if (!strcmp(name, "Tumble"))
1602       header->Tumble = !strcmp(value, "true");
1603     else if (!strcmp(name, "cupsMediaType"))
1604       header->cupsMediaType = atoi(value);
1605     else if (!strcmp(name, "cupsBitsPerColor"))
1606       header->cupsBitsPerColor = atoi(value);
1607     else if (!strcmp(name, "cupsColorOrder"))
1608       header->cupsColorOrder = (cups_order_t)atoi(value);
1609     else if (!strcmp(name, "cupsColorSpace"))
1610       header->cupsColorSpace = (cups_cspace_t)atoi(value);
1611     else if (!strcmp(name, "cupsCompression"))
1612       header->cupsCompression = atoi(value);
1613     else if (!strcmp(name, "cupsRowCount"))
1614       header->cupsRowCount = atoi(value);
1615     else if (!strcmp(name, "cupsRowFeed"))
1616       header->cupsRowFeed = atoi(value);
1617     else if (!strcmp(name, "cupsRowStep"))
1618       header->cupsRowStep = atoi(value);
1619   }
1620 }
1621
1622
1623 /*
1624  * 'format_CMY()' - Convert image data to CMY.
1625  */
1626
1627 static void
1628 format_CMY(cups_page_header2_t *header, /* I - Page header */
1629             unsigned char      *row,    /* IO - Bitmap data for device */
1630             int                y,       /* I - Current row */
1631             int                z,       /* I - Current plane */
1632             int                xsize,   /* I - Width of image data */
1633             int                ysize,   /* I - Height of image data */
1634             int                yerr0,   /* I - Top Y error */
1635             int                yerr1,   /* I - Bottom Y error */
1636             cups_ib_t               *r0,        /* I - Primary image data */
1637             cups_ib_t               *r1)        /* I - Image data for interpolation */
1638 {
1639   cups_ib_t             *ptr,           /* Pointer into row */
1640                 *cptr,          /* Pointer into cyan */
1641                 *mptr,          /* Pointer into magenta */
1642                 *yptr,          /* Pointer into yellow */
1643                 bitmask;        /* Current mask for pixel */
1644   int           bitoffset;      /* Current offset in line */
1645   int           bandwidth;      /* Width of a color band */
1646   int           x,              /* Current X coordinate on page */
1647                 *dither;        /* Pointer into dither array */
1648
1649
1650   switch (XPosition)
1651   {
1652     case -1 :
1653         bitoffset = 0;
1654         break;
1655     default :
1656         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
1657         break;
1658     case 1 :
1659         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
1660         break;
1661   }
1662
1663   ptr       = row + bitoffset / 8;
1664   bandwidth = header->cupsBytesPerLine / 3;
1665
1666   switch (header->cupsColorOrder)
1667   {
1668     case CUPS_ORDER_CHUNKED :
1669         switch (header->cupsBitsPerColor)
1670         {
1671           case 1 :
1672               bitmask = 64 >> (bitoffset & 7);
1673               dither  = Floyd16x16[y & 15];
1674
1675               for (x = xsize ; x > 0; x --)
1676               {
1677                 if (*r0++ > dither[x & 15])
1678                   *ptr ^= bitmask;
1679                 bitmask >>= 1;
1680
1681                 if (*r0++ > dither[x & 15])
1682                   *ptr ^= bitmask;
1683                 bitmask >>= 1;
1684
1685                 if (*r0++ > dither[x & 15])
1686                   *ptr ^= bitmask;
1687
1688                 if (bitmask > 1)
1689                   bitmask >>= 2;
1690                 else
1691                 {
1692                   bitmask = 64;
1693                   ptr ++;
1694                 }
1695               }
1696               break;
1697
1698           case 2 :
1699               dither = Floyd8x8[y & 7];
1700
1701               for (x = xsize ; x > 0; x --, r0 += 3)
1702               {
1703                 if ((r0[0] & 63) > dither[x & 7])
1704                   *ptr ^= (0x30 & OnPixels[r0[0]]);
1705                 else
1706                   *ptr ^= (0x30 & OffPixels[r0[0]]);
1707
1708                 if ((r0[1] & 63) > dither[x & 7])
1709                   *ptr ^= (0x0c & OnPixels[r0[1]]);
1710                 else
1711                   *ptr ^= (0x0c & OffPixels[r0[1]]);
1712
1713                 if ((r0[2] & 63) > dither[x & 7])
1714                   *ptr++ ^= (0x03 & OnPixels[r0[2]]);
1715                 else
1716                   *ptr++ ^= (0x03 & OffPixels[r0[2]]);
1717               }
1718               break;
1719
1720           case 4 :
1721               dither = Floyd4x4[y & 3];
1722
1723               for (x = xsize ; x > 0; x --, r0 += 3)
1724               {
1725                 if ((r0[0] & 15) > dither[x & 3])
1726                   *ptr++ ^= (0x0f & OnPixels[r0[0]]);
1727                 else
1728                   *ptr++ ^= (0x0f & OffPixels[r0[0]]);
1729
1730                 if ((r0[1] & 15) > dither[x & 3])
1731                   *ptr ^= (0xf0 & OnPixels[r0[1]]);
1732                 else
1733                   *ptr ^= (0xf0 & OffPixels[r0[1]]);
1734
1735                 if ((r0[2] & 15) > dither[x & 3])
1736                   *ptr++ ^= (0x0f & OnPixels[r0[2]]);
1737                 else
1738                   *ptr++ ^= (0x0f & OffPixels[r0[2]]);
1739               }
1740               break;
1741
1742           case 8 :
1743               for (x = xsize  * 3; x > 0; x --, r0 ++, r1 ++)
1744                 if (*r0 == *r1)
1745                   *ptr++ = *r0;
1746                 else
1747                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1748               break;
1749         }
1750         break;
1751
1752     case CUPS_ORDER_BANDED :
1753         cptr = ptr;
1754         mptr = ptr + bandwidth;
1755         yptr = ptr + 2 * bandwidth;
1756
1757         switch (header->cupsBitsPerColor)
1758         {
1759           case 1 :
1760               bitmask = 0x80 >> (bitoffset & 7);
1761               dither  = Floyd16x16[y & 15];
1762
1763               for (x = xsize; x > 0; x --)
1764               {
1765                 if (*r0++ > dither[x & 15])
1766                   *cptr ^= bitmask;
1767                 if (*r0++ > dither[x & 15])
1768                   *mptr ^= bitmask;
1769                 if (*r0++ > dither[x & 15])
1770                   *yptr ^= bitmask;
1771
1772                 if (bitmask > 1)
1773                   bitmask >>= 1;
1774                 else
1775                 {
1776                   bitmask = 0x80;
1777                   cptr ++;
1778                   mptr ++;
1779                   yptr ++;
1780                 }
1781               }
1782               break;
1783
1784           case 2 :
1785               bitmask = 0xc0 >> (bitoffset & 7);
1786               dither  = Floyd8x8[y & 7];
1787
1788               for (x = xsize; x > 0; x --)
1789               {
1790                 if ((*r0 & 63) > dither[x & 7])
1791                   *cptr ^= (bitmask & OnPixels[*r0++]);
1792                 else
1793                   *cptr ^= (bitmask & OffPixels[*r0++]);
1794
1795                 if ((*r0 & 63) > dither[x & 7])
1796                   *mptr ^= (bitmask & OnPixels[*r0++]);
1797                 else
1798                   *mptr ^= (bitmask & OffPixels[*r0++]);
1799
1800                 if ((*r0 & 63) > dither[x & 7])
1801                   *yptr ^= (bitmask & OnPixels[*r0++]);
1802                 else
1803                   *yptr ^= (bitmask & OffPixels[*r0++]);
1804
1805                 if (bitmask > 3)
1806                   bitmask >>= 2;
1807                 else
1808                 {
1809                   bitmask = 0xc0;
1810
1811                   cptr ++;
1812                   mptr ++;
1813                   yptr ++;
1814                 }
1815               }
1816               break;
1817
1818           case 4 :
1819               bitmask = 0xf0 >> (bitoffset & 7);
1820               dither  = Floyd4x4[y & 3];
1821
1822               for (x = xsize; x > 0; x --)
1823               {
1824                 if ((*r0 & 15) > dither[x & 3])
1825                   *cptr ^= (bitmask & OnPixels[*r0++]);
1826                 else
1827                   *cptr ^= (bitmask & OffPixels[*r0++]);
1828
1829                 if ((*r0 & 15) > dither[x & 3])
1830                   *mptr ^= (bitmask & OnPixels[*r0++]);
1831                 else
1832                   *mptr ^= (bitmask & OffPixels[*r0++]);
1833
1834                 if ((*r0 & 15) > dither[x & 3])
1835                   *yptr ^= (bitmask & OnPixels[*r0++]);
1836                 else
1837                   *yptr ^= (bitmask & OffPixels[*r0++]);
1838
1839                 if (bitmask == 0xf0)
1840                   bitmask = 0x0f;
1841                 else
1842                 {
1843                   bitmask = 0xf0;
1844
1845                   cptr ++;
1846                   mptr ++;
1847                   yptr ++;
1848                 }
1849               }
1850               break;
1851
1852           case 8 :
1853               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
1854               {
1855                 if (r0[0] == r1[0])
1856                   *cptr++ = r0[0];
1857                 else
1858                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
1859
1860                 if (r0[1] == r1[1])
1861                   *mptr++ = r0[1];
1862                 else
1863                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
1864
1865                 if (r0[2] == r1[2])
1866                   *yptr++ = r0[2];
1867                 else
1868                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
1869               }
1870               break;
1871         }
1872         break;
1873
1874     case CUPS_ORDER_PLANAR :
1875         switch (header->cupsBitsPerColor)
1876         {
1877           case 1 :
1878               bitmask = 0x80 >> (bitoffset & 7);
1879               dither  = Floyd16x16[y & 15];
1880
1881               switch (z)
1882               {
1883                 case 0 :
1884                     for (x = xsize; x > 0; x --, r0 += 3)
1885                     {
1886                       if (r0[0] > dither[x & 15])
1887                         *ptr ^= bitmask;
1888
1889                       if (bitmask > 1)
1890                         bitmask >>= 1;
1891                       else
1892                       {
1893                         bitmask = 0x80;
1894                         ptr ++;
1895                       }
1896                     }
1897                     break;
1898
1899                 case 1 :
1900                     for (x = xsize; x > 0; x --, r0 += 3)
1901                     {
1902                       if (r0[1] > dither[x & 15])
1903                         *ptr ^= bitmask;
1904
1905                       if (bitmask > 1)
1906                         bitmask >>= 1;
1907                       else
1908                       {
1909                         bitmask = 0x80;
1910                         ptr ++;
1911                       }
1912                     }
1913                     break;
1914
1915                 case 2 :
1916                     for (x = xsize; x > 0; x --, r0 += 3)
1917                     {
1918                       if (r0[2] > dither[x & 15])
1919                         *ptr ^= bitmask;
1920
1921                       if (bitmask > 1)
1922                         bitmask >>= 1;
1923                       else
1924                       {
1925                         bitmask = 0x80;
1926                         ptr ++;
1927                       }
1928                     }
1929                     break;
1930               }
1931               break;
1932
1933           case 2 :
1934               bitmask = 0xc0 >> (bitoffset & 7);
1935               dither  = Floyd8x8[y & 7];
1936               r0 += z;
1937
1938               for (x = xsize; x > 0; x --, r0 += 3)
1939               {
1940                 if ((*r0 & 63) > dither[x & 7])
1941                   *ptr ^= (bitmask & OnPixels[*r0]);
1942                 else
1943                   *ptr ^= (bitmask & OffPixels[*r0]);
1944
1945                 if (bitmask > 3)
1946                   bitmask >>= 2;
1947                 else
1948                 {
1949                   bitmask = 0xc0;
1950
1951                   ptr ++;
1952                 }
1953               }
1954               break;
1955
1956           case 4 :
1957               bitmask = 0xf0 >> (bitoffset & 7);
1958               dither  = Floyd4x4[y & 3];
1959               r0 += z;
1960
1961               for (x = xsize; x > 0; x --, r0 += 3)
1962               {
1963                 if ((*r0 & 15) > dither[x & 3])
1964                   *ptr ^= (bitmask & OnPixels[*r0]);
1965                 else
1966                   *ptr ^= (bitmask & OffPixels[*r0]);
1967
1968                 if (bitmask == 0xf0)
1969                   bitmask = 0x0f;
1970                 else
1971                 {
1972                   bitmask = 0xf0;
1973
1974                   ptr ++;
1975                 }
1976               }
1977               break;
1978
1979           case 8 :
1980               r0 += z;
1981               r1 += z;
1982
1983               for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
1984               {
1985                 if (*r0 == *r1)
1986                   *ptr++ = *r0;
1987                 else
1988                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
1989               }
1990               break;
1991         }
1992         break;
1993   }
1994 }
1995
1996
1997 /*
1998  * 'format_CMYK()' - Convert image data to CMYK.
1999  */
2000
2001 static void
2002 format_CMYK(cups_page_header2_t *header,        /* I - Page header */
2003             unsigned char       *row,   /* IO - Bitmap data for device */
2004             int                 y,      /* I - Current row */
2005             int                 z,      /* I - Current plane */
2006             int                 xsize,  /* I - Width of image data */
2007             int                 ysize,  /* I - Height of image data */
2008             int                 yerr0,  /* I - Top Y error */
2009             int                 yerr1,  /* I - Bottom Y error */
2010             cups_ib_t                *r0,       /* I - Primary image data */
2011             cups_ib_t                *r1)       /* I - Image data for interpolation */
2012 {
2013   cups_ib_t             *ptr,           /* Pointer into row */
2014                 *cptr,          /* Pointer into cyan */
2015                 *mptr,          /* Pointer into magenta */
2016                 *yptr,          /* Pointer into yellow */
2017                 *kptr,          /* Pointer into black */
2018                 bitmask;        /* Current mask for pixel */
2019   int           bitoffset;      /* Current offset in line */
2020   int           bandwidth;      /* Width of a color band */
2021   int           x,              /* Current X coordinate on page */
2022                 *dither;        /* Pointer into dither array */
2023
2024
2025   switch (XPosition)
2026   {
2027     case -1 :
2028         bitoffset = 0;
2029         break;
2030     default :
2031         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2032         break;
2033     case 1 :
2034         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2035         break;
2036   }
2037
2038   ptr       = row + bitoffset / 8;
2039   bandwidth = header->cupsBytesPerLine / 4;
2040
2041   switch (header->cupsColorOrder)
2042   {
2043     case CUPS_ORDER_CHUNKED :
2044         switch (header->cupsBitsPerColor)
2045         {
2046           case 1 :
2047               bitmask = 128 >> (bitoffset & 7);
2048               dither  = Floyd16x16[y & 15];
2049
2050               for (x = xsize ; x > 0; x --)
2051               {
2052                 if (*r0++ > dither[x & 15])
2053                   *ptr ^= bitmask;
2054                 bitmask >>= 1;
2055
2056                 if (*r0++ > dither[x & 15])
2057                   *ptr ^= bitmask;
2058                 bitmask >>= 1;
2059
2060                 if (*r0++ > dither[x & 15])
2061                   *ptr ^= bitmask;
2062                 bitmask >>= 1;
2063
2064                 if (*r0++ > dither[x & 15])
2065                   *ptr ^= bitmask;
2066
2067                 if (bitmask > 1)
2068                   bitmask >>= 1;
2069                 else
2070                 {
2071                   bitmask = 128;
2072                   ptr ++;
2073                 }
2074               }
2075               break;
2076
2077           case 2 :
2078               dither = Floyd8x8[y & 7];
2079
2080               for (x = xsize ; x > 0; x --, r0 += 4)
2081               {
2082                 if ((r0[0] & 63) > dither[x & 7])
2083                   *ptr ^= (0xc0 & OnPixels[r0[0]]);
2084                 else
2085                   *ptr ^= (0xc0 & OffPixels[r0[0]]);
2086
2087                 if ((r0[1] & 63) > dither[x & 7])
2088                   *ptr ^= (0x30 & OnPixels[r0[1]]);
2089                 else
2090                   *ptr ^= (0x30 & OffPixels[r0[1]]);
2091
2092                 if ((r0[2] & 63) > dither[x & 7])
2093                   *ptr ^= (0x0c & OnPixels[r0[2]]);
2094                 else
2095                   *ptr ^= (0x0c & OffPixels[r0[2]]);
2096
2097                 if ((r0[3] & 63) > dither[x & 7])
2098                   *ptr++ ^= (0x03 & OnPixels[r0[3]]);
2099                 else
2100                   *ptr++ ^= (0x03 & OffPixels[r0[3]]);
2101               }
2102               break;
2103
2104           case 4 :
2105               dither = Floyd4x4[y & 3];
2106
2107               for (x = xsize ; x > 0; x --, r0 += 4)
2108               {
2109                 if ((r0[0] & 15) > dither[x & 3])
2110                   *ptr ^= (0xf0 & OnPixels[r0[0]]);
2111                 else
2112                   *ptr ^= (0xf0 & OffPixels[r0[0]]);
2113
2114                 if ((r0[1] & 15) > dither[x & 3])
2115                   *ptr++ ^= (0x0f & OnPixels[r0[1]]);
2116                 else
2117                   *ptr++ ^= (0x0f & OffPixels[r0[1]]);
2118
2119                 if ((r0[2] & 15) > dither[x & 3])
2120                   *ptr ^= (0xf0 & OnPixels[r0[2]]);
2121                 else
2122                   *ptr ^= (0xf0 & OffPixels[r0[2]]);
2123
2124                 if ((r0[3] & 15) > dither[x & 3])
2125                   *ptr++ ^= (0x0f & OnPixels[r0[3]]);
2126                 else
2127                   *ptr++ ^= (0x0f & OffPixels[r0[3]]);
2128               }
2129               break;
2130
2131           case 8 :
2132               for (x = xsize  * 4; x > 0; x --, r0 ++, r1 ++)
2133                 if (*r0 == *r1)
2134                   *ptr++ = *r0;
2135                 else
2136                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2137               break;
2138         }
2139         break;
2140
2141     case CUPS_ORDER_BANDED :
2142         cptr = ptr;
2143         mptr = ptr + bandwidth;
2144         yptr = ptr + 2 * bandwidth;
2145         kptr = ptr + 3 * bandwidth;
2146
2147         switch (header->cupsBitsPerColor)
2148         {
2149           case 1 :
2150               bitmask = 0x80 >> (bitoffset & 7);
2151               dither  = Floyd16x16[y & 15];
2152
2153               for (x = xsize; x > 0; x --)
2154               {
2155                 if (*r0++ > dither[x & 15])
2156                   *cptr ^= bitmask;
2157                 if (*r0++ > dither[x & 15])
2158                   *mptr ^= bitmask;
2159                 if (*r0++ > dither[x & 15])
2160                   *yptr ^= bitmask;
2161                 if (*r0++ > dither[x & 15])
2162                   *kptr ^= bitmask;
2163
2164                 if (bitmask > 1)
2165                   bitmask >>= 1;
2166                 else
2167                 {
2168                   bitmask = 0x80;
2169                   cptr ++;
2170                   mptr ++;
2171                   yptr ++;
2172                   kptr ++;
2173                 }
2174               }
2175               break;
2176
2177           case 2 :
2178               bitmask = 0xc0 >> (bitoffset & 7);
2179               dither  = Floyd8x8[y & 7];
2180
2181               for (x = xsize; x > 0; x --)
2182               {
2183                 if ((*r0 & 63) > dither[x & 7])
2184                   *cptr ^= (bitmask & OnPixels[*r0++]);
2185                 else
2186                   *cptr ^= (bitmask & OffPixels[*r0++]);
2187
2188                 if ((*r0 & 63) > dither[x & 7])
2189                   *mptr ^= (bitmask & OnPixels[*r0++]);
2190                 else
2191                   *mptr ^= (bitmask & OffPixels[*r0++]);
2192
2193                 if ((*r0 & 63) > dither[x & 7])
2194                   *yptr ^= (bitmask & OnPixels[*r0++]);
2195                 else
2196                   *yptr ^= (bitmask & OffPixels[*r0++]);
2197
2198                 if ((*r0 & 63) > dither[x & 7])
2199                   *kptr ^= (bitmask & OnPixels[*r0++]);
2200                 else
2201                   *kptr ^= (bitmask & OffPixels[*r0++]);
2202
2203                 if (bitmask > 3)
2204                   bitmask >>= 2;
2205                 else
2206                 {
2207                   bitmask = 0xc0;
2208
2209                   cptr ++;
2210                   mptr ++;
2211                   yptr ++;
2212                   kptr ++;
2213                 }
2214               }
2215               break;
2216
2217           case 4 :
2218               bitmask = 0xf0 >> (bitoffset & 7);
2219               dither  = Floyd4x4[y & 3];
2220
2221               for (x = xsize; x > 0; x --)
2222               {
2223                 if ((*r0 & 15) > dither[x & 3])
2224                   *cptr ^= (bitmask & OnPixels[*r0++]);
2225                 else
2226                   *cptr ^= (bitmask & OffPixels[*r0++]);
2227
2228                 if ((*r0 & 15) > dither[x & 3])
2229                   *mptr ^= (bitmask & OnPixels[*r0++]);
2230                 else
2231                   *mptr ^= (bitmask & OffPixels[*r0++]);
2232
2233                 if ((*r0 & 15) > dither[x & 3])
2234                   *yptr ^= (bitmask & OnPixels[*r0++]);
2235                 else
2236                   *yptr ^= (bitmask & OffPixels[*r0++]);
2237
2238                 if ((*r0 & 15) > dither[x & 3])
2239                   *kptr ^= (bitmask & OnPixels[*r0++]);
2240                 else
2241                   *kptr ^= (bitmask & OffPixels[*r0++]);
2242
2243                 if (bitmask == 0xf0)
2244                   bitmask = 0x0f;
2245                 else
2246                 {
2247                   bitmask = 0xf0;
2248
2249                   cptr ++;
2250                   mptr ++;
2251                   yptr ++;
2252                   kptr ++;
2253                 }
2254               }
2255               break;
2256
2257           case 8 :
2258               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2259               {
2260                 if (r0[0] == r1[0])
2261                   *cptr++ = r0[0];
2262                 else
2263                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2264
2265                 if (r0[1] == r1[1])
2266                   *mptr++ = r0[1];
2267                 else
2268                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2269
2270                 if (r0[2] == r1[2])
2271                   *yptr++ = r0[2];
2272                 else
2273                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2274
2275                 if (r0[3] == r1[3])
2276                   *kptr++ = r0[3];
2277                 else
2278                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2279               }
2280               break;
2281         }
2282         break;
2283
2284     case CUPS_ORDER_PLANAR :
2285         switch (header->cupsBitsPerColor)
2286         {
2287           case 1 :
2288               bitmask = 0x80 >> (bitoffset & 7);
2289               dither  = Floyd16x16[y & 15];
2290               r0      += z;
2291
2292               for (x = xsize; x > 0; x --, r0 += 4)
2293               {
2294                 if (*r0 > dither[x & 15])
2295                   *ptr ^= bitmask;
2296
2297                 if (bitmask > 1)
2298                   bitmask >>= 1;
2299                 else
2300                 {
2301                   bitmask = 0x80;
2302                   ptr ++;
2303                 }
2304               }
2305               break;
2306
2307           case 2 :
2308               bitmask = 0xc0 >> (bitoffset & 7);
2309               dither  = Floyd8x8[y & 7];
2310               r0      += z;
2311
2312               for (x = xsize; x > 0; x --, r0 += 4)
2313               {
2314                 if ((*r0 & 63) > dither[x & 7])
2315                   *ptr ^= (bitmask & OnPixels[*r0]);
2316                 else
2317                   *ptr ^= (bitmask & OffPixels[*r0]);
2318
2319                 if (bitmask > 3)
2320                   bitmask >>= 2;
2321                 else
2322                 {
2323                   bitmask = 0xc0;
2324
2325                   ptr ++;
2326                 }
2327               }
2328               break;
2329
2330           case 4 :
2331               bitmask = 0xf0 >> (bitoffset & 7);
2332               dither  = Floyd4x4[y & 3];
2333               r0 += z;
2334
2335               for (x = xsize; x > 0; x --, r0 += 4)
2336               {
2337                 if ((*r0 & 15) > dither[x & 3])
2338                   *ptr ^= (bitmask & OnPixels[*r0]);
2339                 else
2340                   *ptr ^= (bitmask & OffPixels[*r0]);
2341
2342                 if (bitmask == 0xf0)
2343                   bitmask = 0x0f;
2344                 else
2345                 {
2346                   bitmask = 0xf0;
2347
2348                   ptr ++;
2349                 }
2350               }
2351               break;
2352
2353           case 8 :
2354               r0 += z;
2355               r1 += z;
2356
2357               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2358               {
2359                 if (*r0 == *r1)
2360                   *ptr++ = *r0;
2361                 else
2362                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2363               }
2364               break;
2365         }
2366         break;
2367   }
2368 }
2369
2370
2371 /*
2372  * 'format_K()' - Convert image data to black.
2373  */
2374
2375 static void
2376 format_K(cups_page_header2_t *header,   /* I - Page header */
2377          unsigned char       *row,      /* IO - Bitmap data for device */
2378          int                 y,         /* I - Current row */
2379          int                 z,         /* I - Current plane */
2380          int                 xsize,     /* I - Width of image data */
2381          int                 ysize,     /* I - Height of image data */
2382          int                 yerr0,     /* I - Top Y error */
2383          int                 yerr1,     /* I - Bottom Y error */
2384          cups_ib_t                *r0,  /* I - Primary image data */
2385          cups_ib_t                *r1)  /* I - Image data for interpolation */
2386 {
2387   cups_ib_t             *ptr,           /* Pointer into row */
2388                 bitmask;        /* Current mask for pixel */
2389   int           bitoffset;      /* Current offset in line */
2390   int           x,              /* Current X coordinate on page */
2391                 *dither;        /* Pointer into dither array */
2392
2393
2394   (void)z;
2395
2396   switch (XPosition)
2397   {
2398     case -1 :
2399         bitoffset = 0;
2400         break;
2401     default :
2402         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2403         break;
2404     case 1 :
2405         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2406         break;
2407   }
2408
2409   ptr = row + bitoffset / 8;
2410
2411   switch (header->cupsBitsPerColor)
2412   {
2413     case 1 :
2414         bitmask = 0x80 >> (bitoffset & 7);
2415         dither  = Floyd16x16[y & 15];
2416
2417         for (x = xsize; x > 0; x --)
2418         {
2419           if (*r0++ > dither[x & 15])
2420             *ptr ^= bitmask;
2421
2422           if (bitmask > 1)
2423             bitmask >>= 1;
2424           else
2425           {
2426             bitmask = 0x80;
2427             ptr ++;
2428           }
2429         }
2430         break;
2431
2432     case 2 :
2433         bitmask = 0xc0 >> (bitoffset & 7);
2434         dither  = Floyd8x8[y & 7];
2435
2436         for (x = xsize; x > 0; x --)
2437         {
2438           if ((*r0 & 63) > dither[x & 7])
2439             *ptr ^= (bitmask & OnPixels[*r0++]);
2440           else
2441             *ptr ^= (bitmask & OffPixels[*r0++]);
2442
2443           if (bitmask > 3)
2444             bitmask >>= 2;
2445           else
2446           {
2447             bitmask = 0xc0;
2448
2449             ptr ++;
2450           }
2451         }
2452         break;
2453
2454     case 4 :
2455         bitmask = 0xf0 >> (bitoffset & 7);
2456         dither  = Floyd4x4[y & 3];
2457
2458         for (x = xsize; x > 0; x --)
2459         {
2460           if ((*r0 & 15) > dither[x & 3])
2461             *ptr ^= (bitmask & OnPixels[*r0++]);
2462           else
2463             *ptr ^= (bitmask & OffPixels[*r0++]);
2464
2465           if (bitmask == 0xf0)
2466             bitmask = 0x0f;
2467           else
2468           {
2469             bitmask = 0xf0;
2470
2471             ptr ++;
2472           }
2473         }
2474         break;
2475
2476     case 8 :
2477         for (x = xsize; x > 0; x --, r0 ++, r1 ++)
2478         {
2479           if (*r0 == *r1)
2480             *ptr++ = *r0;
2481           else
2482             *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2483         }
2484         break;
2485   }
2486 }
2487
2488
2489 /*
2490  * 'format_KCMY()' - Convert image data to KCMY.
2491  */
2492
2493 static void
2494 format_KCMY(cups_page_header2_t *header,        /* I - Page header */
2495             unsigned char       *row,   /* IO - Bitmap data for device */
2496             int                 y,      /* I - Current row */
2497             int                 z,      /* I - Current plane */
2498             int                 xsize,  /* I - Width of image data */
2499             int                 ysize,  /* I - Height of image data */
2500             int                 yerr0,  /* I - Top Y error */
2501             int                 yerr1,  /* I - Bottom Y error */
2502             cups_ib_t                *r0,       /* I - Primary image data */
2503             cups_ib_t                *r1)       /* I - Image data for interpolation */
2504 {
2505   cups_ib_t             *ptr,           /* Pointer into row */
2506                 *cptr,          /* Pointer into cyan */
2507                 *mptr,          /* Pointer into magenta */
2508                 *yptr,          /* Pointer into yellow */
2509                 *kptr,          /* Pointer into black */
2510                 bitmask;        /* Current mask for pixel */
2511   int           bitoffset;      /* Current offset in line */
2512   int           bandwidth;      /* Width of a color band */
2513   int           x,              /* Current X coordinate on page */
2514                 *dither;        /* Pointer into dither array */
2515
2516
2517   switch (XPosition)
2518   {
2519     case -1 :
2520         bitoffset = 0;
2521         break;
2522     default :
2523         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2524         break;
2525     case 1 :
2526         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2527         break;
2528   }
2529
2530   ptr       = row + bitoffset / 8;
2531   bandwidth = header->cupsBytesPerLine / 4;
2532
2533   switch (header->cupsColorOrder)
2534   {
2535     case CUPS_ORDER_CHUNKED :
2536         switch (header->cupsBitsPerColor)
2537         {
2538           case 1 :
2539               bitmask = 128 >> (bitoffset & 7);
2540               dither  = Floyd16x16[y & 15];
2541
2542               for (x = xsize ; x > 0; x --, r0 += 4)
2543               {
2544                 if (r0[3] > dither[x & 15])
2545                   *ptr ^= bitmask;
2546                 bitmask >>= 1;
2547
2548                 if (r0[0] > dither[x & 15])
2549                   *ptr ^= bitmask;
2550                 bitmask >>= 1;
2551
2552                 if (r0[1] > dither[x & 15])
2553                   *ptr ^= bitmask;
2554                 bitmask >>= 1;
2555
2556                 if (r0[2] > dither[x & 15])
2557                   *ptr ^= bitmask;
2558
2559                 if (bitmask > 1)
2560                   bitmask >>= 1;
2561                 else
2562                 {
2563                   bitmask = 128;
2564                   ptr ++;
2565                 }
2566               }
2567               break;
2568
2569           case 2 :
2570               dither = Floyd8x8[y & 7];
2571
2572               for (x = xsize ; x > 0; x --, r0 += 4)
2573               {
2574                 if ((r0[3] & 63) > dither[x & 7])
2575                   *ptr ^= (0xc0 & OnPixels[r0[3]]);
2576                 else
2577                   *ptr ^= (0xc0 & OffPixels[r0[3]]);
2578
2579                 if ((r0[0] & 63) > dither[x & 7])
2580                   *ptr ^= (0x30 & OnPixels[r0[0]]);
2581                 else
2582                   *ptr ^= (0x30 & OffPixels[r0[0]]);
2583
2584                 if ((r0[1] & 63) > dither[x & 7])
2585                   *ptr ^= (0x0c & OnPixels[r0[1]]);
2586                 else
2587                   *ptr ^= (0x0c & OffPixels[r0[1]]);
2588
2589                 if ((r0[2] & 63) > dither[x & 7])
2590                   *ptr++ ^= (0x03 & OnPixels[r0[2]]);
2591                 else
2592                   *ptr++ ^= (0x03 & OffPixels[r0[2]]);
2593               }
2594               break;
2595
2596           case 4 :
2597               dither = Floyd4x4[y & 3];
2598
2599               for (x = xsize ; x > 0; x --, r0 += 4)
2600               {
2601                 if ((r0[3] & 15) > dither[x & 3])
2602                   *ptr ^= (0xf0 & OnPixels[r0[3]]);
2603                 else
2604                   *ptr ^= (0xf0 & OffPixels[r0[3]]);
2605
2606                 if ((r0[0] & 15) > dither[x & 3])
2607                   *ptr++ ^= (0x0f & OnPixels[r0[0]]);
2608                 else
2609                   *ptr++ ^= (0x0f & OffPixels[r0[0]]);
2610
2611                 if ((r0[1] & 15) > dither[x & 3])
2612                   *ptr ^= (0xf0 & OnPixels[r0[1]]);
2613                 else
2614                   *ptr ^= (0xf0 & OffPixels[r0[1]]);
2615
2616                 if ((r0[2] & 15) > dither[x & 3])
2617                   *ptr++ ^= (0x0f & OnPixels[r0[2]]);
2618                 else
2619                   *ptr++ ^= (0x0f & OffPixels[r0[2]]);
2620               }
2621               break;
2622
2623           case 8 :
2624               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2625               {
2626                 if (r0[3] == r1[3])
2627                   *ptr++ = r0[3];
2628                 else
2629                   *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2630
2631                 if (r0[0] == r1[0])
2632                   *ptr++ = r0[0];
2633                 else
2634                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2635
2636                 if (r0[1] == r1[1])
2637                   *ptr++ = r0[1];
2638                 else
2639                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2640
2641                 if (r0[2] == r1[2])
2642                   *ptr++ = r0[2];
2643                 else
2644                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2645               }
2646               break;
2647         }
2648         break;
2649
2650     case CUPS_ORDER_BANDED :
2651         kptr = ptr;
2652         cptr = ptr + bandwidth;
2653         mptr = ptr + 2 * bandwidth;
2654         yptr = ptr + 3 * bandwidth;
2655
2656         switch (header->cupsBitsPerColor)
2657         {
2658           case 1 :
2659               bitmask = 0x80 >> (bitoffset & 7);
2660               dither  = Floyd16x16[y & 15];
2661
2662               for (x = xsize; x > 0; x --)
2663               {
2664                 if (*r0++ > dither[x & 15])
2665                   *cptr ^= bitmask;
2666                 if (*r0++ > dither[x & 15])
2667                   *mptr ^= bitmask;
2668                 if (*r0++ > dither[x & 15])
2669                   *yptr ^= bitmask;
2670                 if (*r0++ > dither[x & 15])
2671                   *kptr ^= bitmask;
2672
2673                 if (bitmask > 1)
2674                   bitmask >>= 1;
2675                 else
2676                 {
2677                   bitmask = 0x80;
2678                   cptr ++;
2679                   mptr ++;
2680                   yptr ++;
2681                   kptr ++;
2682                 }
2683               }
2684               break;
2685
2686           case 2 :
2687               bitmask = 0xc0 >> (bitoffset & 7);
2688               dither  = Floyd8x8[y & 7];
2689
2690               for (x = xsize; x > 0; x --)
2691               {
2692                 if ((*r0 & 63) > dither[x & 7])
2693                   *cptr ^= (bitmask & OnPixels[*r0++]);
2694                 else
2695                   *cptr ^= (bitmask & OffPixels[*r0++]);
2696
2697                 if ((*r0 & 63) > dither[x & 7])
2698                   *mptr ^= (bitmask & OnPixels[*r0++]);
2699                 else
2700                   *mptr ^= (bitmask & OffPixels[*r0++]);
2701
2702                 if ((*r0 & 63) > dither[x & 7])
2703                   *yptr ^= (bitmask & OnPixels[*r0++]);
2704                 else
2705                   *yptr ^= (bitmask & OffPixels[*r0++]);
2706
2707                 if ((*r0 & 63) > dither[x & 7])
2708                   *kptr ^= (bitmask & OnPixels[*r0++]);
2709                 else
2710                   *kptr ^= (bitmask & OffPixels[*r0++]);
2711
2712                 if (bitmask > 3)
2713                   bitmask >>= 2;
2714                 else
2715                 {
2716                   bitmask = 0xc0;
2717
2718                   cptr ++;
2719                   mptr ++;
2720                   yptr ++;
2721                   kptr ++;
2722                 }
2723               }
2724               break;
2725
2726           case 4 :
2727               bitmask = 0xf0 >> (bitoffset & 7);
2728               dither  = Floyd4x4[y & 3];
2729
2730               for (x = xsize; x > 0; x --)
2731               {
2732                 if ((*r0 & 15) > dither[x & 3])
2733                   *cptr ^= (bitmask & OnPixels[*r0++]);
2734                 else
2735                   *cptr ^= (bitmask & OffPixels[*r0++]);
2736
2737                 if ((*r0 & 15) > dither[x & 3])
2738                   *mptr ^= (bitmask & OnPixels[*r0++]);
2739                 else
2740                   *mptr ^= (bitmask & OffPixels[*r0++]);
2741
2742                 if ((*r0 & 15) > dither[x & 3])
2743                   *yptr ^= (bitmask & OnPixels[*r0++]);
2744                 else
2745                   *yptr ^= (bitmask & OffPixels[*r0++]);
2746
2747                 if ((*r0 & 15) > dither[x & 3])
2748                   *kptr ^= (bitmask & OnPixels[*r0++]);
2749                 else
2750                   *kptr ^= (bitmask & OffPixels[*r0++]);
2751
2752                 if (bitmask == 0xf0)
2753                   bitmask = 0x0f;
2754                 else
2755                 {
2756                   bitmask = 0xf0;
2757
2758                   cptr ++;
2759                   mptr ++;
2760                   yptr ++;
2761                   kptr ++;
2762                 }
2763               }
2764               break;
2765
2766           case 8 :
2767               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2768               {
2769                 if (r0[0] == r1[0])
2770                   *cptr++ = r0[0];
2771                 else
2772                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2773
2774                 if (r0[1] == r1[1])
2775                   *mptr++ = r0[1];
2776                 else
2777                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2778
2779                 if (r0[2] == r1[2])
2780                   *yptr++ = r0[2];
2781                 else
2782                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
2783
2784                 if (r0[3] == r1[3])
2785                   *kptr++ = r0[3];
2786                 else
2787                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2788               }
2789               break;
2790         }
2791         break;
2792
2793     case CUPS_ORDER_PLANAR :
2794         switch (header->cupsBitsPerColor)
2795         {
2796           case 1 :
2797               bitmask = 0x80 >> (bitoffset & 7);
2798               dither  = Floyd16x16[y & 15];
2799               if (z == 0)
2800                 r0 += 3;
2801               else
2802                 r0 += z - 1;
2803
2804               for (x = xsize; x > 0; x --, r0 += 4)
2805               {
2806                 if (*r0 > dither[x & 15])
2807                   *ptr ^= bitmask;
2808
2809                 if (bitmask > 1)
2810                   bitmask >>= 1;
2811                 else
2812                 {
2813                   bitmask = 0x80;
2814                   ptr ++;
2815                 }
2816               }
2817               break;
2818
2819           case 2 :
2820               bitmask = 0xc0 >> (bitoffset & 7);
2821               dither  = Floyd8x8[y & 7];
2822               if (z == 0)
2823                 r0 += 3;
2824               else
2825                 r0 += z - 1;
2826
2827               for (x = xsize; x > 0; x --, r0 += 4)
2828               {
2829                 if ((*r0 & 63) > dither[x & 7])
2830                   *ptr ^= (bitmask & OnPixels[*r0]);
2831                 else
2832                   *ptr ^= (bitmask & OffPixels[*r0]);
2833
2834                 if (bitmask > 3)
2835                   bitmask >>= 2;
2836                 else
2837                 {
2838                   bitmask = 0xc0;
2839
2840                   ptr ++;
2841                 }
2842               }
2843               break;
2844
2845           case 4 :
2846               bitmask = 0xf0 >> (bitoffset & 7);
2847               dither  = Floyd4x4[y & 3];
2848               if (z == 0)
2849                 r0 += 3;
2850               else
2851                 r0 += z - 1;
2852
2853               for (x = xsize; x > 0; x --, r0 += 4)
2854               {
2855                 if ((*r0 & 15) > dither[x & 3])
2856                   *ptr ^= (bitmask & OnPixels[*r0]);
2857                 else
2858                   *ptr ^= (bitmask & OffPixels[*r0]);
2859
2860                 if (bitmask == 0xf0)
2861                   bitmask = 0x0f;
2862                 else
2863                 {
2864                   bitmask = 0xf0;
2865
2866                   ptr ++;
2867                 }
2868               }
2869               break;
2870
2871           case 8 :
2872               if (z == 0)
2873               {
2874                 r0 += 3;
2875                 r1 += 3;
2876               }
2877               else
2878               {
2879                 r0 += z - 1;
2880                 r1 += z - 1;
2881               }
2882
2883               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2884               {
2885                 if (*r0 == *r1)
2886                   *ptr++ = *r0;
2887                 else
2888                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
2889               }
2890               break;
2891         }
2892         break;
2893   }
2894 }
2895
2896
2897 /*
2898  * 'format_KCMYcm()' - Convert image data to KCMYcm.
2899  */
2900
2901 static void
2902 format_KCMYcm(cups_page_header2_t *header,/* I - Page header */
2903               unsigned char       *row, /* IO - Bitmap data for device */
2904               int                 y,    /* I - Current row */
2905               int                 z,    /* I - Current plane */
2906               int                 xsize,/* I - Width of image data */
2907               int                 ysize,/* I - Height of image data */
2908               int                 yerr0,/* I - Top Y error */
2909               int                 yerr1,/* I - Bottom Y error */
2910               cups_ib_t                *r0,     /* I - Primary image data */
2911               cups_ib_t                *r1)     /* I - Image data for interpolation */
2912 {
2913   int           pc, pm, py, pk; /* Cyan, magenta, yellow, and black values */
2914   cups_ib_t             *ptr,           /* Pointer into row */
2915                 *cptr,          /* Pointer into cyan */
2916                 *mptr,          /* Pointer into magenta */
2917                 *yptr,          /* Pointer into yellow */
2918                 *kptr,          /* Pointer into black */
2919                 *lcptr,         /* Pointer into light cyan */
2920                 *lmptr,         /* Pointer into light magenta */
2921                 bitmask;        /* Current mask for pixel */
2922   int           bitoffset;      /* Current offset in line */
2923   int           bandwidth;      /* Width of a color band */
2924   int           x,              /* Current X coordinate on page */
2925                 *dither;        /* Pointer into dither array */
2926
2927
2928   switch (XPosition)
2929   {
2930     case -1 :
2931         bitoffset = 0;
2932         break;
2933     default :
2934         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
2935         break;
2936     case 1 :
2937         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
2938         break;
2939   }
2940
2941   ptr = row + bitoffset / 8;
2942   if (header->cupsBitsPerColor == 1)
2943     bandwidth = header->cupsBytesPerLine / 6;
2944   else
2945     bandwidth = header->cupsBytesPerLine / 4;
2946
2947   switch (header->cupsColorOrder)
2948   {
2949     case CUPS_ORDER_CHUNKED :
2950         switch (header->cupsBitsPerColor)
2951         {
2952           case 1 :
2953               dither  = Floyd16x16[y & 15];
2954
2955               for (x = xsize ; x > 0; x --)
2956               {
2957                 pc = *r0++ > dither[x & 15];
2958                 pm = *r0++ > dither[x & 15];
2959                 py = *r0++ > dither[x & 15];
2960                 pk = *r0++ > dither[x & 15];
2961
2962                 if (pk)
2963                   *ptr++ ^= 32; /* Black */
2964                 else if (pc && pm)
2965                   *ptr++ ^= 17; /* Blue (cyan + light magenta) */
2966                 else if (pc && py)
2967                   *ptr++ ^= 6;  /* Green (light cyan + yellow) */
2968                 else if (pm && py)
2969                   *ptr++ ^= 12; /* Red (magenta + yellow) */
2970                 else if (pc)
2971                   *ptr++ ^= 16;
2972                 else if (pm)
2973                   *ptr++ ^= 8;
2974                 else if (py)
2975                   *ptr++ ^= 4;
2976               }
2977               break;
2978
2979           case 8 :
2980               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
2981               {
2982                 if (r0[3] == r1[3])
2983                   *ptr++ = r0[3];
2984                 else
2985                   *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
2986
2987                 if (r0[0] == r1[0])
2988                   *ptr++ = r0[0];
2989                 else
2990                   *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
2991
2992                 if (r0[1] == r1[1])
2993                   *ptr++ = r0[1];
2994                 else
2995                   *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
2996
2997                 if (r0[2] == r1[2])
2998                   *ptr++ = r0[2];
2999                 else
3000                   *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3001               }
3002               break;
3003         }
3004         break;
3005
3006     case CUPS_ORDER_BANDED :
3007         kptr  = ptr;
3008         cptr  = ptr + bandwidth;
3009         mptr  = ptr + 2 * bandwidth;
3010         yptr  = ptr + 3 * bandwidth;
3011         lcptr = ptr + 4 * bandwidth;
3012         lmptr = ptr + 5 * bandwidth;
3013
3014         switch (header->cupsBitsPerColor)
3015         {
3016           case 1 :
3017               bitmask = 0x80 >> (bitoffset & 7);
3018               dither  = Floyd16x16[y & 15];
3019
3020               for (x = xsize; x > 0; x --)
3021               {
3022                 pc = *r0++ > dither[x & 15];
3023                 pm = *r0++ > dither[x & 15];
3024                 py = *r0++ > dither[x & 15];
3025                 pk = *r0++ > dither[x & 15];
3026
3027                 if (pk)
3028                   *kptr ^= bitmask;     /* Black */
3029                 else if (pc && pm)
3030                 {
3031                   *cptr ^= bitmask;     /* Blue (cyan + light magenta) */
3032                   *lmptr ^= bitmask;
3033                 }
3034                 else if (pc && py)
3035                 {
3036                   *lcptr ^= bitmask;    /* Green (light cyan + yellow) */
3037                   *yptr  ^= bitmask;
3038                 }
3039                 else if (pm && py)
3040                 {
3041                   *mptr ^= bitmask;     /* Red (magenta + yellow) */
3042                   *yptr ^= bitmask;
3043                 }
3044                 else if (pc)
3045                   *cptr ^= bitmask;
3046                 else if (pm)
3047                   *mptr ^= bitmask;
3048                 else if (py)
3049                   *yptr ^= bitmask;
3050
3051                 if (bitmask > 1)
3052                   bitmask >>= 1;
3053                 else
3054                 {
3055                   bitmask = 0x80;
3056                   cptr ++;
3057                   mptr ++;
3058                   yptr ++;
3059                   kptr ++;
3060                   lcptr ++;
3061                   lmptr ++;
3062                 }
3063               }
3064               break;
3065
3066           case 8 :
3067               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
3068               {
3069                 if (r0[0] == r1[0])
3070                   *cptr++ = r0[0];
3071                 else
3072                   *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
3073
3074                 if (r0[1] == r1[1])
3075                   *mptr++ = r0[1];
3076                 else
3077                   *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
3078
3079                 if (r0[2] == r1[2])
3080                   *yptr++ = r0[2];
3081                 else
3082                   *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
3083
3084                 if (r0[3] == r1[3])
3085                   *kptr++ = r0[3];
3086                 else
3087                   *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
3088               }
3089               break;
3090         }
3091         break;
3092
3093     case CUPS_ORDER_PLANAR :
3094         switch (header->cupsBitsPerColor)
3095         {
3096           case 1 :
3097               bitmask = 0x80 >> (bitoffset & 7);
3098               dither  = Floyd16x16[y & 15];
3099
3100               switch (z)
3101               {
3102                 case 0 :
3103                     for (x = xsize; x > 0; x --, r0 += 4)
3104                     {
3105                       if (r0[3] > dither[x & 15])
3106                         *ptr ^= bitmask;
3107
3108                       if (bitmask > 1)
3109                         bitmask >>= 1;
3110                       else
3111                       {
3112                         bitmask = 0x80;
3113                         ptr ++;
3114                       }
3115                     }
3116                     break;
3117
3118                 case 1 :
3119                     for (x = xsize; x > 0; x --, r0 += 4)
3120                     {
3121                       if (r0[0] > dither[x & 15] &&
3122                           r0[2] < dither[x & 15])
3123                         *ptr ^= bitmask;
3124
3125                       if (bitmask > 1)
3126                         bitmask >>= 1;
3127                       else
3128                       {
3129                         bitmask = 0x80;
3130                         ptr ++;
3131                       }
3132                     }
3133                     break;
3134
3135                 case 2 :
3136                     for (x = xsize; x > 0; x --, r0 += 4)
3137                     {
3138                       if (r0[1] > dither[x & 15] &&
3139                           (r0[0] < dither[x & 15] ||
3140                            r0[2] > dither[x & 15]))
3141                         *ptr ^= bitmask;
3142
3143                       if (bitmask > 1)
3144                         bitmask >>= 1;
3145                       else
3146                       {
3147                         bitmask = 0x80;
3148                         ptr ++;
3149                       }
3150                     }
3151                     break;
3152
3153                 case 3 :
3154                     for (x = xsize; x > 0; x --, r0 += 4)
3155                     {
3156                       if (r0[2] > dither[x & 15] &&
3157                           (r0[0] < dither[x & 15] ||
3158                            r0[1] < dither[x & 15]))
3159                         *ptr ^= bitmask;
3160
3161                       if (bitmask > 1)
3162                         bitmask >>= 1;
3163                       else
3164                       {
3165                         bitmask = 0x80;
3166                         ptr ++;
3167                       }
3168                     }
3169                     break;
3170
3171                 case 4 :
3172                     for (x = xsize; x > 0; x --, r0 += 4)
3173                     {
3174                       if (r0[0] > dither[x & 15] &&
3175                           r0[2] > dither[x & 15])
3176                         *ptr ^= bitmask;
3177
3178                       if (bitmask > 1)
3179                         bitmask >>= 1;
3180                       else
3181                       {
3182                         bitmask = 0x80;
3183                         ptr ++;
3184                       }
3185                     }
3186                     break;
3187
3188                 case 5 :
3189                     for (x = xsize; x > 0; x --, r0 += 4)
3190                     {
3191                       if (r0[0] > dither[x & 15] &&
3192                           r0[1] > dither[x & 15] &&
3193                           r0[2] < dither[x & 15])
3194                         *ptr ^= bitmask;
3195
3196                       if (bitmask > 1)
3197                         bitmask >>= 1;
3198                       else
3199                       {
3200                         bitmask = 0x80;
3201                         ptr ++;
3202                       }
3203                     }
3204                     break;
3205               }
3206               break;
3207
3208           case 8 :
3209               if (z == 0)
3210               {
3211                 r0 += 3;
3212                 r1 += 3;
3213               }
3214               else
3215               {
3216                 r0 += z - 1;
3217                 r1 += z - 1;
3218               }
3219
3220               for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
3221               {
3222                 if (*r0 == *r1)
3223                   *ptr++ = *r0;
3224                 else
3225                   *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
3226               }
3227               break;
3228         }
3229         break;
3230   }
3231 }
3232
3233
3234 /*
3235  * 'format_RGBA()' - Convert image data to RGBA/RGBW.
3236  */
3237
3238 static void
3239 format_RGBA(cups_page_header2_t *header,        /* I - Page header */
3240             unsigned char       *row,   /* IO - Bitmap data for device */
3241             int                 y,      /* I - Current row */
3242             int                 z,      /* I - Current plane */
3243             int                 xsize,  /* I - Width of image data */
3244             int                 ysize,  /* I - Height of image data */
3245             int                 yerr0,  /* I - Top Y error */
3246             int                 yerr1,  /* I - Bottom Y error */
3247             cups_ib_t                *r0,       /* I - Primary image data */
3248             cups_ib_t                *r1)       /* I - Image data for interpolation */
3249 {
3250   cups_ib_t             *ptr,           /* Pointer into row */
3251                 *cptr,          /* Pointer into cyan */
3252                 *mptr,          /* Pointer into magenta */
3253                 *yptr,          /* Pointer into yellow */
3254                 bitmask;        /* Current mask for pixel */
3255   int           bitoffset;      /* Current offset in line */
3256   int           bandwidth;      /* Width of a color band */
3257   int           x,              /* Current X coordinate on page */
3258                 *dither;        /* Pointer into dither array */
3259
3260
3261   switch (XPosition)
3262   {
3263     case -1 :
3264         bitoffset = 0;
3265         break;
3266     default :
3267         bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
3268         break;
3269     case 1 :
3270         bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
3271         break;
3272   }
3273
3274   ptr       = row + bitoffset / 8;
3275   bandwidth = header->cupsBytesPerLine / 4;
3276
3277   switch (header->cupsColorOrder)
3278   {
3279     case CUPS_ORDER_CHUNKED :
3280         switch (header->cupsBitsPerColor)
3281         {
3282           case 1 :
3283               bitmask = 128 >> (bitoffset & 7);
3284               dither  = Floyd16x16[y & 15];
3285
3286               for (x = xsize ; x > 0; x --)
3287               {
3288                 if (*r0++ > dither[x & 15])
3289                   *ptr ^= bitmask;
3290                 bitmask >>= 1;
3291
3292                 if (*r0++ > dither[x & 15])
3293                   *ptr ^= bitmask;
3294                 bitmask >>= 1;
3295
3296                 if (*r0++ > dither[x & 15])
3297                   *ptr ^= bitmask;
3298
3299                 if (bitmask > 2)
3300                 {
3301                   *ptr ^= 16;
3302                   bitmask >>= 2;
3303                 }
3304                 else
3305                 {
3306                   bitmask = 128;
3307                   *ptr++ ^= 1;
3308                 }
3309               }
3310               break;
3311
3312           case 2 :
3313               dither = Floyd8x8[y & 7];
3314
3315               for (x = xsize ; x > 0; x --, r0 += 3)
3316               {
3317                 if ((r0[0] & 63) > dither[x & 7])
3318                   *ptr ^= (0xc0 & OnPixels