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