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