]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/imagetops.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / imagetops.c
1 /*
2 * "$Id: imagetops.c 4741 2005-10-02 04:25:52Z mike $"
3 *
4 * Image file to PostScript 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 * ps_hex() - Print binary data as a series of hexadecimal numbers.
30 * ps_ascii85() - Print binary data as a series of base-85 numbers.
31 */
32
33 /*
34 * Include necessary headers...
35 */
36
37 #include "common.h"
38 #include "image.h"
39 #include <math.h>
40
41
42 /*
43 * Globals...
44 */
45
46 int Flip = 0, /* Flip/mirror pages */
47 XPosition = 0, /* Horizontal position on page */
48 YPosition = 0, /* Vertical position on page */
49 Collate = 0, /* Collate copies? */
50 Copies = 1; /* Number of copies */
51
52
53 /*
54 * Local functions...
55 */
56
57 static void ps_hex(cups_ib_t *, int, int);
58 static void ps_ascii85(cups_ib_t *, int, int);
59
60
61 /*
62 * 'main()' - Main entry...
63 */
64
65 int /* O - Exit status */
66 main(int argc, /* I - Number of command-line arguments */
67 char *argv[]) /* I - Command-line arguments */
68 {
69 cups_image_t *img; /* Image to print */
70 float xprint, /* Printable area */
71 yprint,
72 xinches, /* Total size in inches */
73 yinches;
74 float xsize, /* Total size in points */
75 ysize,
76 xsize2,
77 ysize2;
78 float aspect; /* Aspect ratio */
79 int xpages, /* # x pages */
80 ypages, /* # y pages */
81 xpage, /* Current x page */
82 ypage, /* Current y page */
83 page; /* Current page number */
84 int x0, y0, /* Corners of the page in image coords */
85 x1, y1;
86 cups_ib_t *row; /* Current row */
87 int y; /* Current Y coordinate in image */
88 int colorspace; /* Output colorspace */
89 int out_offset, /* Offset into output buffer */
90 out_length; /* Length of output buffer */
91 ppd_file_t *ppd; /* PPD file */
92 ppd_choice_t *choice; /* PPD option choice */
93 int num_options; /* Number of print options */
94 cups_option_t *options; /* Print options */
95 const char *val; /* Option value */
96 int slowcollate; /* Collate copies the slow way */
97 float g; /* Gamma correction value */
98 float b; /* Brightness factor */
99 float zoom; /* Zoom facter */
100 int xppi, yppi; /* Pixels-per-inch */
101 int hue, sat; /* Hue and saturation adjustment */
102 int realcopies; /* Real copies being printed */
103 float left, top; /* Left and top of image */
104 char filename[1024]; /* Name of file to print */
105 time_t curtime; /* Current time */
106 struct tm *curtm; /* Current date */
107 char curdate[255]; /* Current date string */
108
109
110 /*
111 * Make sure status messages are not buffered...
112 */
113
114 setbuf(stderr, NULL);
115
116 /*
117 * Check command-line...
118 */
119
120 if (argc < 6 || argc > 7)
121 {
122 fputs("ERROR: imagetops job-id user title copies options [file]\n", stderr);
123 return (1);
124 }
125
126 fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
127 argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
128
129 /*
130 * Copy stdin as needed...
131 */
132
133 if (argc == 6)
134 {
135 int fd; /* File to write to */
136 char buffer[8192]; /* Buffer to read into */
137 int bytes; /* # of bytes to read */
138
139
140 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
141 {
142 perror("ERROR: Unable to copy image file");
143 return (1);
144 }
145
146 fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
147 filename);
148
149 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
150 write(fd, buffer, bytes);
151
152 close(fd);
153 }
154 else
155 strlcpy(filename, argv[6], sizeof(filename));
156
157 /*
158 * Process command-line options and write the prolog...
159 */
160
161 zoom = 0.0;
162 xppi = 0;
163 yppi = 0;
164 hue = 0;
165 sat = 100;
166 g = 1.0;
167 b = 1.0;
168
169 Copies = atoi(argv[4]);
170
171 options = NULL;
172 num_options = cupsParseOptions(argv[5], 0, &options);
173
174 ppd = SetCommonOptions(num_options, options, 0);
175
176 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
177 {
178 /*
179 * This IPP attribute is unnecessarily complicated...
180 *
181 * single-document, separate-documents-collated-copies, and
182 * single-document-new-sheet all require collated copies.
183 *
184 * separate-documents-uncollated-copies allows for uncollated copies.
185 */
186
187 Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
188 }
189
190 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
191 strcasecmp(val, "True") == 0)
192 Collate = 1;
193
194 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
195 g = atoi(val) * 0.001f;
196
197 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
198 b = atoi(val) * 0.01f;
199
200 if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
201 zoom = atoi(val) * 0.01;
202
203 if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
204 if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
205 yppi = xppi;
206
207 if ((val = cupsGetOption("position", num_options, options)) != NULL)
208 {
209 if (strcasecmp(val, "center") == 0)
210 {
211 XPosition = 0;
212 YPosition = 0;
213 }
214 else if (strcasecmp(val, "top") == 0)
215 {
216 XPosition = 0;
217 YPosition = 1;
218 }
219 else if (strcasecmp(val, "left") == 0)
220 {
221 XPosition = -1;
222 YPosition = 0;
223 }
224 else if (strcasecmp(val, "right") == 0)
225 {
226 XPosition = 1;
227 YPosition = 0;
228 }
229 else if (strcasecmp(val, "top-left") == 0)
230 {
231 XPosition = -1;
232 YPosition = 1;
233 }
234 else if (strcasecmp(val, "top-right") == 0)
235 {
236 XPosition = 1;
237 YPosition = 1;
238 }
239 else if (strcasecmp(val, "bottom") == 0)
240 {
241 XPosition = 0;
242 YPosition = -1;
243 }
244 else if (strcasecmp(val, "bottom-left") == 0)
245 {
246 XPosition = -1;
247 YPosition = -1;
248 }
249 else if (strcasecmp(val, "bottom-right") == 0)
250 {
251 XPosition = 1;
252 YPosition = -1;
253 }
254 }
255
256 if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
257 sat = atoi(val);
258
259 if ((val = cupsGetOption("hue", num_options, options)) != NULL)
260 hue = atoi(val);
261
262 if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
263 strcasecmp(val, "True") == 0)
264 Flip = 1;
265
266 /*
267 * Open the input image to print...
268 */
269
270 colorspace = ColorDevice ? CUPS_IMAGE_RGB_CMYK : CUPS_IMAGE_WHITE;
271
272 img = cupsImageOpen(filename, colorspace, CUPS_IMAGE_WHITE, sat, hue, NULL);
273
274 if (argc == 6)
275 unlink(filename);
276
277 if (img == NULL)
278 {
279 fputs("ERROR: Unable to open image file for printing!\n", stderr);
280 ppdClose(ppd);
281 return (1);
282 }
283
284 colorspace = cupsImageGetColorSpace(img);
285
286 /*
287 * Scale as necessary...
288 */
289
290 if (zoom == 0.0 && xppi == 0)
291 {
292 xppi = cupsImageGetXPPI(img);
293 yppi = cupsImageGetYPPI(img);
294 }
295
296 if (yppi == 0)
297 yppi = xppi;
298
299 fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
300 xppi, yppi, zoom);
301
302 if (xppi > 0)
303 {
304 /*
305 * Scale the image as neccesary to match the desired pixels-per-inch.
306 */
307
308 if (Orientation & 1)
309 {
310 xprint = (PageTop - PageBottom) / 72.0;
311 yprint = (PageRight - PageLeft) / 72.0;
312 }
313 else
314 {
315 xprint = (PageRight - PageLeft) / 72.0;
316 yprint = (PageTop - PageBottom) / 72.0;
317 }
318
319 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
320 xprint, yprint);
321
322 xinches = (float)cupsImageGetWidth(img) / (float)xppi;
323 yinches = (float)cupsImageGetHeight(img) / (float)yppi;
324
325 fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
326 xinches, yinches);
327
328 if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
329 {
330 xinches = xinches * atoi(val) / 100;
331 yinches = yinches * atoi(val) / 100;
332 }
333
334 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
335 cupsGetOption("landscape", num_options, options) == NULL)
336 {
337 /*
338 * Rotate the image if it will fit landscape but not portrait...
339 */
340
341 fputs("DEBUG: Auto orientation...\n", stderr);
342
343 if ((xinches > xprint || yinches > yprint) &&
344 xinches <= yprint && yinches <= xprint)
345 {
346 /*
347 * Rotate the image as needed...
348 */
349
350 fputs("DEBUG: Using landscape orientation...\n", stderr);
351
352 Orientation = (Orientation + 1) & 3;
353 xsize = yprint;
354 yprint = xprint;
355 xprint = xsize;
356 }
357 }
358 }
359 else
360 {
361 /*
362 * Scale percentage of page size...
363 */
364
365 xprint = (PageRight - PageLeft) / 72.0;
366 yprint = (PageTop - PageBottom) / 72.0;
367 aspect = (float)cupsImageGetYPPI(img) / (float)cupsImageGetXPPI(img);
368
369 fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
370 xprint, yprint);
371
372 fprintf(stderr, "DEBUG: cupsImageGetXPPI(img) = %d, cupsImageGetYPPI(img) = %d, aspect = %f\n",
373 cupsImageGetXPPI(img), cupsImageGetYPPI(img), aspect);
374
375 xsize = xprint * zoom;
376 ysize = xsize * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;
377
378 if (ysize > (yprint * zoom))
379 {
380 ysize = yprint * zoom;
381 xsize = ysize * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
382 }
383
384 xsize2 = yprint * zoom;
385 ysize2 = xsize2 * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;
386
387 if (ysize2 > (xprint * zoom))
388 {
389 ysize2 = xprint * zoom;
390 xsize2 = ysize2 * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
391 }
392
393 fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
394 fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
395
396 if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
397 cupsGetOption("landscape", num_options, options) == NULL)
398 {
399 /*
400 * Choose the rotation with the largest area, but prefer
401 * portrait if they are equal...
402 */
403
404 fputs("DEBUG: Auto orientation...\n", stderr);
405
406 if ((xsize * ysize) < (xsize2 * xsize2))
407 {
408 /*
409 * Do landscape orientation...
410 */
411
412 fputs("DEBUG: Using landscape orientation...\n", stderr);
413
414 Orientation = 1;
415 xinches = xsize2;
416 yinches = ysize2;
417 xprint = (PageTop - PageBottom) / 72.0;
418 yprint = (PageRight - PageLeft) / 72.0;
419 }
420 else
421 {
422 /*
423 * Do portrait orientation...
424 */
425
426 fputs("DEBUG: Using portrait orientation...\n", stderr);
427
428 Orientation = 0;
429 xinches = xsize;
430 yinches = ysize;
431 }
432 }
433 else if (Orientation & 1)
434 {
435 fputs("DEBUG: Using landscape orientation...\n", stderr);
436
437 xinches = xsize2;
438 yinches = ysize2;
439 xprint = (PageTop - PageBottom) / 72.0;
440 yprint = (PageRight - PageLeft) / 72.0;
441 }
442 else
443 {
444 fputs("DEBUG: Using portrait orientation...\n", stderr);
445
446 xinches = xsize;
447 yinches = ysize;
448 xprint = (PageRight - PageLeft) / 72.0;
449 yprint = (PageTop - PageBottom) / 72.0;
450 }
451 }
452
453 /*
454 * Compute the number of pages to print and the size of the image on each
455 * page...
456 */
457
458 xpages = ceil(xinches / xprint);
459 ypages = ceil(yinches / yprint);
460
461 xprint = xinches / xpages;
462 yprint = yinches / ypages;
463
464 fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
465 xpages, xprint, ypages, yprint);
466
467 /*
468 * Update the page size for custom sizes...
469 */
470
471 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
472 strcasecmp(choice->choice, "Custom") == 0)
473 {
474 float width, /* New width in points */
475 length; /* New length in points */
476 char s[255]; /* New custom page size... */
477
478
479 /*
480 * Use the correct width and length for the current orientation...
481 */
482
483 if (Orientation & 1)
484 {
485 width = yprint * 72.0;
486 length = xprint * 72.0;
487 }
488 else
489 {
490 width = xprint * 72.0;
491 length = yprint * 72.0;
492 }
493
494 /*
495 * Add margins to page size...
496 */
497
498 width += ppd->custom_margins[0] + ppd->custom_margins[2];
499 length += ppd->custom_margins[1] + ppd->custom_margins[3];
500
501 /*
502 * Enforce minimums...
503 */
504
505 if (width < ppd->custom_min[0])
506 width = ppd->custom_min[0];
507
508 if (length < ppd->custom_min[1])
509 length = ppd->custom_min[1];
510
511 fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
512 width / 72.0, length / 72.0);
513
514 /*
515 * Set the new custom size...
516 */
517
518 sprintf(s, "Custom.%.0fx%.0f", width, length);
519 ppdMarkOption(ppd, "PageSize", s);
520
521 /*
522 * Update page variables...
523 */
524
525 PageWidth = width;
526 PageLength = length;
527 PageLeft = ppd->custom_margins[0];
528 PageRight = width - ppd->custom_margins[2];
529 PageBottom = ppd->custom_margins[1];
530 PageTop = length - ppd->custom_margins[3];
531 }
532
533 /*
534 * See if we need to collate, and if so how we need to do it...
535 */
536
537 if (xpages == 1 && ypages == 1)
538 Collate = 0;
539
540 slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
541
542 if (Copies > 1 && !slowcollate)
543 {
544 realcopies = Copies;
545 Copies = 1;
546 }
547 else
548 realcopies = 1;
549
550 /*
551 * Write any "exit server" options that have been selected...
552 */
553
554 ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
555
556 /*
557 * Write any JCL commands that are needed to print PostScript code...
558 */
559
560 ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
561
562 /*
563 * Start sending the document with any commands needed...
564 */
565
566 curtime = time(NULL);
567 curtm = localtime(&curtime);
568
569 puts("%!PS-Adobe-3.0");
570 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
571 PageRight, PageTop);
572 printf("%%%%LanguageLevel: %d\n", LanguageLevel);
573 printf("%%%%Pages: %d\n", xpages * ypages * Copies);
574 puts("%%DocumentData: Clean7Bit");
575 puts("%%DocumentNeededResources: font Helvetica-Bold");
576 puts("%%Creator: imagetops/" CUPS_SVERSION);
577 strftime(curdate, sizeof(curdate), "%c", curtm);
578 printf("%%%%CreationDate: %s\n", curdate);
579 printf("%%%%Title: %s\n", argv[3]);
580 printf("%%%%For: %s\n", argv[2]);
581 if (Orientation & 1)
582 puts("%%Orientation: Landscape");
583 else
584 puts("%%Orientation: Portrait");
585 puts("%%EndComments");
586 puts("%%BeginProlog");
587
588 if (ppd != NULL && ppd->patches != NULL)
589 puts(ppd->patches);
590
591 ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
592 ppdEmit(ppd, stdout, PPD_ORDER_ANY);
593 ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
594
595 if (g != 1.0 || b != 1.0)
596 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
597 "ifelse %.3f mul } bind settransfer\n", g, b);
598
599 WriteCommon();
600 switch (Orientation)
601 {
602 case 0 :
603 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
604 PageBottom, PageTop, PageWidth);
605 break;
606
607 case 1 :
608 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
609 PageLeft, PageRight, PageLength);
610 break;
611
612 case 2 :
613 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
614 PageLength - PageTop, PageLength - PageBottom,
615 PageWidth);
616 break;
617
618 case 3 :
619 WriteLabelProlog(cupsGetOption("page-label", num_options, options),
620 PageWidth - PageRight, PageWidth - PageLeft,
621 PageLength);
622 break;
623 }
624
625 if (realcopies > 1)
626 {
627 if (ppd == NULL || ppd->language_level == 1)
628 printf("/#copies %d def\n", realcopies);
629 else
630 printf("<</NumCopies %d>>setpagedevice\n", realcopies);
631 }
632
633 puts("%%EndProlog");
634
635 /*
636 * Output the pages...
637 */
638
639 row = malloc(cupsImageGetWidth(img) * abs(colorspace) + 3);
640
641 fprintf(stderr, "DEBUG: XPosition=%d, YPosition=%d, Orientation=%d\n",
642 XPosition, YPosition, Orientation);
643 fprintf(stderr, "DEBUG: xprint=%.0f, yprint=%.0f\n", xprint, yprint);
644 fprintf(stderr, "DEBUG: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f\n",
645 PageLeft, PageRight, PageWidth);
646 fprintf(stderr, "DEBUG: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f\n",
647 PageBottom, PageTop, PageLength);
648
649 switch (Orientation)
650 {
651 default :
652 switch (XPosition)
653 {
654 case -1 :
655 left = PageLeft;
656 break;
657 default :
658 left = (PageRight + PageLeft - xprint * 72) / 2;
659 break;
660 case 1 :
661 left = PageRight - xprint * 72;
662 break;
663 }
664
665 switch (YPosition)
666 {
667 case -1 :
668 top = PageBottom + yprint * 72;
669 break;
670 default :
671 top = (PageTop + PageBottom + yprint * 72) / 2;
672 break;
673 case 1 :
674 top = PageTop;
675 break;
676 }
677 break;
678
679 case 1 :
680 switch (XPosition)
681 {
682 case -1 :
683 left = PageBottom;
684 break;
685 default :
686 left = (PageTop + PageBottom - xprint * 72) / 2;
687 break;
688 case 1 :
689 left = PageTop - xprint * 72;
690 break;
691 }
692
693 switch (YPosition)
694 {
695 case -1 :
696 top = PageLeft + yprint * 72;
697 break;
698 default :
699 top = (PageRight + PageLeft + yprint * 72) / 2;
700 break;
701 case 1 :
702 top = PageRight;
703 break;
704 }
705 break;
706
707 case 2 :
708 switch (XPosition)
709 {
710 case 1 :
711 left = PageLeft;
712 break;
713 default :
714 left = (PageRight + PageLeft - xprint * 72) / 2;
715 break;
716 case -1 :
717 left = PageRight - xprint * 72;
718 break;
719 }
720
721 switch (YPosition)
722 {
723 case 1 :
724 top = PageBottom + yprint * 72;
725 break;
726 default :
727 top = (PageTop + PageBottom + yprint * 72) / 2;
728 break;
729 case -1 :
730 top = PageTop;
731 break;
732 }
733 break;
734
735 case 3 :
736 switch (XPosition)
737 {
738 case 1 :
739 left = PageBottom;
740 break;
741 default :
742 left = (PageTop + PageBottom - xprint * 72) / 2;
743 break;
744 case -1 :
745 left = PageTop - xprint * 72;
746 break;
747 }
748
749 switch (YPosition)
750 {
751 case 1 :
752 top = PageLeft + yprint * 72;
753 break;
754 default :
755 top = (PageRight + PageLeft + yprint * 72) / 2;
756 break;
757 case -1 :
758 top = PageRight;
759 break;
760 }
761 break;
762 }
763
764 fprintf(stderr, "DEBUG: left=%.2f, top=%.2f\n", left, top);
765
766 for (page = 1; Copies > 0; Copies --)
767 for (xpage = 0; xpage < xpages; xpage ++)
768 for (ypage = 0; ypage < ypages; ypage ++, page ++)
769 {
770 if (ppd && ppd->num_filters == 0)
771 fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
772
773 fprintf(stderr, "INFO: Printing page %d...\n", page);
774
775 printf("%%%%Page: %d %d\n", page, page);
776
777 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
778
779 puts("gsave");
780
781 if (Flip)
782 printf("%.0f 0 translate -1 1 scale\n", PageWidth);
783
784 switch (Orientation)
785 {
786 case 1 : /* Landscape */
787 printf("%.0f 0 translate 90 rotate\n", PageWidth);
788 break;
789 case 2 : /* Reverse Portrait */
790 printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
791 break;
792 case 3 : /* Reverse Landscape */
793 printf("0 %.0f translate -90 rotate\n", PageLength);
794 break;
795 }
796
797 puts("gsave");
798
799 x0 = cupsImageGetWidth(img) * xpage / xpages;
800 x1 = cupsImageGetWidth(img) * (xpage + 1) / xpages - 1;
801 y0 = cupsImageGetHeight(img) * ypage / ypages;
802 y1 = cupsImageGetHeight(img) * (ypage + 1) / ypages - 1;
803
804 printf("%.1f %.1f translate\n", left, top);
805
806 printf("%.3f %.3f scale\n\n",
807 xprint * 72.0 / (x1 - x0 + 1),
808 yprint * 72.0 / (y1 - y0 + 1));
809
810 if (LanguageLevel == 1)
811 {
812 printf("/picture %d string def\n", (x1 - x0 + 1) * abs(colorspace));
813 printf("%d %d 8[1 0 0 -1 0 1]", (x1 - x0 + 1), (y1 - y0 + 1));
814
815 if (colorspace == CUPS_IMAGE_WHITE)
816 puts("{currentfile picture readhexstring pop} image");
817 else
818 printf("{currentfile picture readhexstring pop} false %d colorimage\n",
819 abs(colorspace));
820
821 for (y = y0; y <= y1; y ++)
822 {
823 cupsImageGetRow(img, x0, y, x1 - x0 + 1, row);
824 ps_hex(row, (x1 - x0 + 1) * abs(colorspace), y == y1);
825 }
826 }
827 else
828 {
829 switch (colorspace)
830 {
831 case CUPS_IMAGE_WHITE :
832 puts("/DeviceGray setcolorspace");
833 break;
834 case CUPS_IMAGE_RGB :
835 puts("/DeviceRGB setcolorspace");
836 break;
837 case CUPS_IMAGE_CMYK :
838 puts("/DeviceCMYK setcolorspace");
839 break;
840 }
841
842 printf("<<"
843 "/cupsImageType 1"
844 "/Width %d"
845 "/Height %d"
846 "/BitsPerComponent 8",
847 x1 - x0 + 1, y1 - y0 + 1);
848
849 switch (colorspace)
850 {
851 case CUPS_IMAGE_WHITE :
852 fputs("/Decode[0 1]", stdout);
853 break;
854 case CUPS_IMAGE_RGB :
855 fputs("/Decode[0 1 0 1 0 1]", stdout);
856 break;
857 case CUPS_IMAGE_CMYK :
858 fputs("/Decode[0 1 0 1 0 1 0 1]", stdout);
859 break;
860 }
861
862 fputs("/DataSource currentfile /ASCII85Decode filter", stdout);
863
864 if (((x1 - x0 + 1) / xprint) < 100.0)
865 fputs("/Interpolate true", stdout);
866
867 puts("/cupsImageMatrix[1 0 0 -1 0 1]>>image");
868
869 for (y = y0, out_offset = 0; y <= y1; y ++)
870 {
871 cupsImageGetRow(img, x0, y, x1 - x0 + 1, row + out_offset);
872
873 out_length = (x1 - x0 + 1) * abs(colorspace) + out_offset;
874 out_offset = out_length & 3;
875
876 ps_ascii85(row, out_length, y == y1);
877
878 if (out_offset > 0)
879 memcpy(row, row + out_length - out_offset, out_offset);
880 }
881 }
882
883 puts("grestore");
884 WriteLabels(0);
885 puts("grestore");
886 puts("showpage");
887 }
888
889 puts("%%EOF");
890
891 /*
892 * End the job with the appropriate JCL command or CTRL-D otherwise.
893 */
894
895 ppdEmitJCLEnd(ppd, stdout);
896
897 /*
898 * Close files...
899 */
900
901 cupsImageClose(img);
902 ppdClose(ppd);
903
904 return (0);
905 }
906
907
908 /*
909 * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
910 */
911
912 static void
913 ps_hex(cups_ib_t *data, /* I - Data to print */
914 int length, /* I - Number of bytes to print */
915 int last_line) /* I - Last line of raster data? */
916 {
917 static int col = 0; /* Current column */
918 static char *hex = "0123456789ABCDEF";
919 /* Hex digits */
920
921
922 while (length > 0)
923 {
924 /*
925 * Put the hex chars out to the file; note that we don't use printf()
926 * for speed reasons...
927 */
928
929 putchar(hex[*data >> 4]);
930 putchar(hex[*data & 15]);
931
932 data ++;
933 length --;
934
935 col += 2;
936 if (col > 78)
937 {
938 putchar('\n');
939 col = 0;
940 }
941 }
942
943 if (last_line && col)
944 {
945 putchar('\n');
946 col = 0;
947 }
948 }
949
950
951 /*
952 * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
953 */
954
955 static void
956 ps_ascii85(cups_ib_t *data, /* I - Data to print */
957 int length, /* I - Number of bytes to print */
958 int last_line) /* I - Last line of raster data? */
959 {
960 unsigned b; /* Binary data word */
961 unsigned char c[5]; /* ASCII85 encoded chars */
962 static int col = 0; /* Current column */
963
964
965 while (length > 3)
966 {
967 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
968
969 if (b == 0)
970 {
971 putchar('z');
972 col ++;
973 }
974 else
975 {
976 c[4] = (b % 85) + '!';
977 b /= 85;
978 c[3] = (b % 85) + '!';
979 b /= 85;
980 c[2] = (b % 85) + '!';
981 b /= 85;
982 c[1] = (b % 85) + '!';
983 b /= 85;
984 c[0] = b + '!';
985
986 fwrite(c, 5, 1, stdout);
987 col += 5;
988 }
989
990 data += 4;
991 length -= 4;
992
993 if (col >= 75)
994 {
995 putchar('\n');
996 col = 0;
997 }
998 }
999
1000 if (last_line)
1001 {
1002 if (length > 0)
1003 {
1004 memset(data + length, 0, 4 - length);
1005 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
1006
1007 c[4] = (b % 85) + '!';
1008 b /= 85;
1009 c[3] = (b % 85) + '!';
1010 b /= 85;
1011 c[2] = (b % 85) + '!';
1012 b /= 85;
1013 c[1] = (b % 85) + '!';
1014 b /= 85;
1015 c[0] = b + '!';
1016
1017 fwrite(c, length + 1, 1, stdout);
1018 }
1019
1020 puts("~>");
1021 col = 0;
1022 }
1023 }
1024
1025
1026 /*
1027 * End of "$Id: imagetops.c 4741 2005-10-02 04:25:52Z mike $".
1028 */