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