]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/imagetops.c
2 * "$Id: imagetops.c,v 1.22 2000/01/04 13:45:46 mike Exp $"
4 * Image file to PostScript filter for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2000 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Main entry...
27 * ps_hex() - Print binary data as a series of hexadecimal numbers.
28 * ps_ascii85() - Print binary data as a series of base-85 numbers.
32 * Include necessary headers...
44 int Flip
= 0, /* Flip/mirror pages */
45 Collate
= 0, /* Collate copies? */
46 Copies
= 1; /* Number of copies */
53 static void ps_hex(ib_t
*, int);
54 static void ps_ascii85(ib_t
*, int, int);
58 * 'main()' - Main entry...
61 int /* O - Exit status */
62 main(int argc
, /* I - Number of command-line arguments */
63 char *argv
[]) /* I - Command-line arguments */
65 image_t
*img
; /* Image to print */
66 float xprint
, /* Printable area */
68 xinches
, /* Total size in inches */
70 float xsize
, /* Total size in points */
74 int xpages
, /* # x pages */
75 ypages
, /* # y pages */
76 xpage
, /* Current x page */
77 ypage
, /* Current y page */
78 page
; /* Current page number */
79 int x0
, y0
, /* Corners of the page in image coords */
81 ib_t
*row
; /* Current row */
82 int y
; /* Current Y coordinate in image */
83 int colorspace
; /* Output colorspace */
84 int out_offset
, /* Offset into output buffer */
85 out_length
; /* Length of output buffer */
86 ppd_file_t
*ppd
; /* PPD file */
87 int num_options
; /* Number of print options */
88 cups_option_t
*options
; /* Print options */
89 const char *val
; /* Option value */
90 int slowcollate
; /* Collate copies the slow way */
91 float g
; /* Gamma correction value */
92 float b
; /* Brightness factor */
93 float zoom
; /* Zoom facter */
94 int ppi
; /* Pixels-per-inch */
95 int hue
, sat
; /* Hue and saturation adjustment */
96 int realcopies
; /* Real copies being printed */
101 fputs("ERROR: imagetops job-id user title copies options file\n", stderr
);
106 * Process command-line options and write the prolog...
116 Copies
= atoi(argv
[4]);
119 num_options
= cupsParseOptions(argv
[5], 0, &options
);
121 ppd
= SetCommonOptions(num_options
, options
, 1);
123 ppdMarkDefaults(ppd
);
124 cupsMarkOptions(ppd
, num_options
, options
);
126 if ((val
= cupsGetOption("multiple-document-handling", num_options
, options
)) != NULL
)
129 * This IPP attribute is unnecessarily complicated...
131 * single-document, separate-documents-collated-copies, and
132 * single-document-new-sheet all require collated copies.
134 * separate-documents-collated-copies allows for uncollated copies.
137 Collate
= strcasecmp(val
, "separate-documents-collated-copies") != 0;
140 if ((val
= cupsGetOption("Collate", num_options
, options
)) != NULL
&&
141 strcasecmp(val
, "True") == 0)
144 if ((val
= cupsGetOption("gamma", num_options
, options
)) != NULL
)
145 g
= atoi(val
) * 0.001f
;
147 if ((val
= cupsGetOption("brightness", num_options
, options
)) != NULL
)
148 b
= atoi(val
) * 0.01f
;
150 if ((val
= cupsGetOption("scaling", num_options
, options
)) != NULL
)
151 zoom
= atoi(val
) * 0.01;
153 if ((val
= cupsGetOption("ppi", num_options
, options
)) != NULL
)
156 if ((val
= cupsGetOption("saturation", num_options
, options
)) != NULL
)
159 if ((val
= cupsGetOption("hue", num_options
, options
)) != NULL
)
163 * Open the input image to print...
166 colorspace
= ColorDevice
? IMAGE_RGB
: IMAGE_WHITE
;
168 if ((img
= ImageOpen(argv
[6], colorspace
, IMAGE_WHITE
, sat
, hue
, NULL
)) == NULL
)
170 fputs("ERROR: Unable to open image file for printing!\n", stderr
);
175 colorspace
= img
->colorspace
;
178 * Scale as necessary...
181 if (zoom
== 0.0 && ppi
== 0)
184 xprint
= (PageRight
- PageLeft
) / 72.0;
185 yprint
= (PageTop
- PageBottom
) / 72.0;
190 * Scale the image as neccesary to match the desired pixels-per-inch.
193 xinches
= (float)img
->xsize
/ (float)ppi
;
194 yinches
= (float)img
->ysize
/ (float)ppi
;
197 * Rotate the image if it will fit landscape but not portrait...
200 if ((xinches
> xprint
|| yinches
> yprint
) &&
201 xinches
<= yprint
&& yinches
<= xprint
)
204 * Rotate the image as needed...
207 Orientation
= (Orientation
+ 1) & 3;
213 PageLeft
= PageBottom
;
214 PageBottom
= PageWidth
- PageRight
;
216 PageTop
= PageLength
- xsize
;
219 PageWidth
= PageLength
;
226 * Scale percentage of page size...
229 xsize
= xprint
* zoom
;
230 ysize
= xsize
* img
->ysize
/ img
->xsize
;
232 if (ysize
> (yprint
* zoom
))
234 ysize
= yprint
* zoom
;
235 xsize
= ysize
* img
->xsize
/ img
->ysize
;
238 xsize2
= yprint
* zoom
;
239 ysize2
= xsize2
* img
->ysize
/ img
->xsize
;
241 if (ysize2
> (xprint
* zoom
))
243 ysize2
= xprint
* zoom
;
244 xsize2
= ysize2
* img
->xsize
/ img
->ysize
;
248 * Choose the rotation with the largest area, but prefer
249 * portrait if they are equal...
252 if ((xsize
* ysize
) < (xsize2
* xsize2
))
255 * Do landscape orientation...
261 xprint
= (PageTop
- PageBottom
) / 72.0;
262 yprint
= (PageRight
- PageLeft
) / 72.0;
265 PageLeft
= PageBottom
;
266 PageBottom
= PageWidth
- PageRight
;
268 PageTop
= PageLength
- xsize
;
271 PageWidth
= PageLength
;
277 * Do portrait orientation...
286 xpages
= ceil(xinches
/ xprint
);
287 ypages
= ceil(yinches
/ yprint
);
290 * See if we need to collate, and if so how we need to do it...
293 if (xpages
== 1 && ypages
== 1)
296 slowcollate
= Collate
&& ppdFindOption(ppd
, "Collate") == NULL
;
299 * Write any "exit server" options that have been selected...
302 ppdEmit(ppd
, stdout
, PPD_ORDER_EXIT
);
305 * Write any JCL commands that are needed to print PostScript code...
308 if (ppd
!= NULL
&& ppd
->jcl_begin
&& ppd
->jcl_ps
)
310 fputs(ppd
->jcl_begin
, stdout
);
311 ppdEmit(ppd
, stdout
, PPD_ORDER_JCL
);
312 fputs(ppd
->jcl_ps
, stdout
);
316 * Start sending the document with any commands needed...
321 if (ppd
!= NULL
&& ppd
->patches
!= NULL
)
324 ppdEmit(ppd
, stdout
, PPD_ORDER_DOCUMENT
);
325 ppdEmit(ppd
, stdout
, PPD_ORDER_ANY
);
326 ppdEmit(ppd
, stdout
, PPD_ORDER_PROLOG
);
328 if (g
!= 1.0 || b
!= 1.0)
329 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
330 "ifelse %.3f mul } bind settransfer\n", g
, b
);
332 if (Copies
> 1 && !slowcollate
)
334 printf("/#copies %d def\n", Copies
);
342 * Output the pages...
345 xprint
= xinches
/ xpages
;
346 yprint
= yinches
/ ypages
;
347 row
= malloc(img
->xsize
* abs(colorspace
) + 3);
349 for (page
= 1; Copies
> 0; Copies
--)
350 for (xpage
= 0; xpage
< xpages
; xpage
++)
351 for (ypage
= 0; ypage
< ypages
; ypage
++, page
++)
353 fprintf(stderr
, "PAGE: %d %d\n", page
, realcopies
);
354 fprintf(stderr
, "INFO: Printing page %d...\n", page
);
356 ppdEmit(ppd
, stdout
, PPD_ORDER_PAGE
);
361 printf("%.0f 0 translate -1 1 scale\n", PageWidth
);
365 case 1 : /* Landscape */
366 printf("%.0f 0 translate 90 rotate\n", PageLength
);
368 case 2 : /* Reverse Portrait */
369 printf("%.0f %.0f translate 180 rotate\n", PageWidth
, PageLength
);
371 case 3 : /* Reverse Landscape */
372 printf("0 %.0f translate -90 rotate\n", PageWidth
);
376 x0
= img
->xsize
* xpage
/ xpages
;
377 x1
= img
->xsize
* (xpage
+ 1) / xpages
- 1;
378 y0
= img
->ysize
* ypage
/ ypages
;
379 y1
= img
->ysize
* (ypage
+ 1) / ypages
- 1;
381 printf("%.1f %.1f translate\n", PageLeft
, PageBottom
+ 72.0 * yprint
);
382 printf("%.3f %.3f scale\n\n",
383 xprint
* 72.0 / (x1
- x0
+ 1),
384 yprint
* 72.0 / (y1
- y0
+ 1));
386 if (LanguageLevel
== 1)
388 printf("/picture %d string def\n", (x1
- x0
+ 1) * abs(colorspace
));
389 printf("%d %d 8[1 0 0 -1 0 1]", (x1
- x0
+ 1), (y1
- y0
+ 1));
391 if (colorspace
== IMAGE_WHITE
)
392 puts("{currentfile picture readhexstring pop} image");
394 puts("{currentfile picture readhexstring pop} false 3 colorimage");
396 for (y
= y0
; y
<= y1
; y
++)
398 ImageGetRow(img
, x0
, y
, x1
- x0
+ 1, row
);
399 ps_hex(row
, (x1
- x0
+ 1) * abs(colorspace
));
404 if (colorspace
== IMAGE_WHITE
)
405 puts("/DeviceGray setcolorspace");
407 puts("/DeviceRGB setcolorspace");
413 "/BitsPerComponent 8",
414 x1
- x0
+ 1, y1
- y0
+ 1);
416 if (colorspace
== IMAGE_WHITE
)
417 fputs("/Decode[0 1]", stdout
);
419 fputs("/Decode[0 1 0 1 0 1]", stdout
);
421 fputs("/DataSource currentfile /ASCII85Decode filter", stdout
);
423 if (((x1
- x0
+ 1) / xprint
) < 100.0)
424 fputs("/Interpolate true", stdout
);
426 puts("/ImageMatrix[1 0 0 -1 0 1]>>image");
428 for (y
= y0
, out_offset
= 0; y
<= y1
; y
++)
430 ImageGetRow(img
, x0
, y
, x1
- x0
+ 1, row
+ out_offset
);
432 out_length
= (x1
- x0
+ 1) * abs(colorspace
) + out_offset
;
433 out_offset
= out_length
& 3;
435 ps_ascii85(row
, out_length
, y
== y1
);
438 memcpy(row
, row
+ out_length
- out_offset
, out_offset
);
447 * End the job with the appropriate JCL command or CTRL-D otherwise.
450 if (ppd
!= NULL
&& ppd
->jcl_end
)
451 fputs(ppd
->jcl_end
, stdout
);
467 * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
471 ps_hex(ib_t
*data
, /* I - Data to print */
472 int length
) /* I - Number of bytes to print */
475 static char *hex
= "0123456789ABCDEF";
483 * Put the hex chars out to the file; note that we don't use printf()
484 * for speed reasons...
487 putchar(hex
[*data
>> 4]);
488 putchar(hex
[*data
& 15]);
493 col
= (col
+ 1) & 31;
494 if (col
== 0 && length
> 0)
503 * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
507 ps_ascii85(ib_t
*data
, /* I - Data to print */
508 int length
, /* I - Number of bytes to print */
509 int last_line
) /* I - Last line of raster data? */
511 int i
; /* Looping var */
512 unsigned b
; /* Binary data word */
513 unsigned char c
[5]; /* ASCII85 encoded chars */
518 b
= (((((data
[0] << 8) | data
[1]) << 8) | data
[2]) << 8) | data
[3];
524 c
[4] = (b
% 85) + '!';
526 c
[3] = (b
% 85) + '!';
528 c
[2] = (b
% 85) + '!';
530 c
[1] = (b
% 85) + '!';
534 fwrite(c
, 5, 1, stdout
);
545 memset(data
+ length
, 0, 4 - length
);
546 b
= (((((data
[0] << 8) | data
[1]) << 8) | data
[2]) << 8) | data
[3];
548 c
[4] = (b
% 85) + '!';
550 c
[3] = (b
% 85) + '!';
552 c
[2] = (b
% 85) + '!';
554 c
[1] = (b
% 85) + '!';
558 fwrite(c
, length
+ 1, 1, stdout
);
567 * End of "$Id: imagetops.c,v 1.22 2000/01/04 13:45:46 mike Exp $".