/[MITgcm]/manual/pstoimg
ViewVC logotype

Contents of /manual/pstoimg

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.4 - (show annotations) (download)
Fri Jul 15 13:37:56 2005 UTC (18 years, 8 months ago) by cnh
Branch: MAIN
CVS Tags: checkpoint01, HEAD
Changes since 1.3: +5 -4 lines
Seems to work on faulks as well now - yeah (I hope).
Only took staying up all night and some 5000+ attempts.
Not sure why nobody fixed this before :-)!
For my next trick ---- protex!!!

1 #! /usr/bin/perl -w
2 ##############################################################################
3 # $Id: pstoimg,v 1.3 2005/07/15 13:29:25 cnh Exp $
4 #
5 # pstoimg
6 #
7 # Accompanies LaTeX2HTML
8 #
9 # Script to convert an arbitrary PostScript image to a cropped GIF or PNG
10 # image suitable for incorporation into HTML documents as inlined images
11 # to be viewed with WWW browsers.
12 #
13 # This software is provided as is without any guarantee.
14 #
15 ##############################################################################
16 #
17 # $Log: pstoimg,v $
18 # Revision 1.3 2005/07/15 13:29:25 cnh
19 # Tidying paths to make it work elsewhere - maybe?
20 #
21 # Revision 1.2 2005/07/15 13:20:56 cnh
22 # Slight change to the fix - plus relative path in .latex2html-init
23 #
24 # Revision 1.1 2005/07/15 13:07:23 cnh
25 # More cunning tricks to get rid of black lines
26 # pnmcrop is junk!
27 #
28 # Revision 1.16 2001/10/25 10:16:12 RRM
29 # -- make sure that $PNMCROPOPT is declared before -sides
30 #
31 # Revision 1.15 2001/08/21 10:48:59 RRM
32 # -- corrects errors in implementing $PNMCROPOPT
33 #
34 # Revision 1.14 2001/08/20 08:51:20 RRM
35 # -- implement -sides for the arguments to $PNMCROP
36 # This is needed for v9.12+ of pnmcrop .
37 # -- when shaving fails, don't try to copy or rename
38 #
39 # Revision 1.13 2001/03/27 09:27:38 RRM
40 # -- inserted missing '$' for $edge .
41 #
42 # Revision 1.12 2001/03/25 02:05:14 RRM
43 # -- implement the temporary hack to pnmcrop, using -black to help detect
44 # the correct color for cropping-bars; only workd with black bars.
45 # A complete fix will be available with Netpbm v9.12 .
46 #
47 # Revision 1.11 1999/10/25 21:18:22 MRO
48 #
49 # -- added more configure options (Jens' suggestions)
50 # -- fixed bug in regexp range reported by Achim Haertel
51 # -- fixed old references in documentation (related to mail list/archive)
52 #
53 # Revision 1.10 1999/10/06 22:04:13 MRO
54 #
55 # -- texexpand: latex2html calls texexpand with the -out option instead of
56 # output redirection: this is safer on non-UNIX platforms
57 # -- pstoimg: now there's no default cropping (useful for standalone
58 # conversions). latex2html was changes appropriately
59 # -- minor cleanups in latex2html script and documentation
60 #
61 # Revision 1.9 1999/09/14 22:02:02 MRO
62 #
63 # -- numerous cleanups, no new features
64 #
65 # Revision 1.8 1999/07/19 09:51:00 RRM
66 # -- added -aaliastext switch, for easier way to specify anti-aliased
67 # font characters, without also anti-aliasing other graphics objects.
68 #
69 # Revision 1.7 1999/06/24 07:28:59 MRO
70 #
71 #
72 # -- removed L2HMODULE
73 # -- fixed processing of -info switch
74 # -- changed option order for dvips on win32 (thanks JCL)
75 # -- bumped version to 99.2a8
76 #
77 # Revision 1.6 1999/06/06 14:24:50 MRO
78 #
79 #
80 # -- many cleanups wrt. to TeXlive
81 # -- changed $* to /m as far as possible. $* is deprecated in perl5, all
82 # occurrences should be removed.
83 #
84 # Revision 1.5 1999/06/04 20:14:25 MRO
85 #
86 #
87 # -- Reworked option parsing completely. Should behave much the same as before,
88 # options with -no_* work just like before.
89 # -- Changed $NOFORK to $CAN_FORK and inverted the logic.
90 # -- Small debugging enhancement in pstoimg
91 #
92 # Revision 1.4 1999/06/04 15:30:15 MRO
93 #
94 #
95 # -- fixed errors introduced by cleaning up TMP*
96 # -- made pstoimg -quiet really quiet
97 # -- pstoimg -debug now saves intermediate result files
98 # -- several fixes for OS/2
99 #
100 # Revision 1.3 1999/06/01 06:55:35 MRO
101 #
102 #
103 # - fixed small bug in L2hos/*
104 # - added some test_mode related output to latex2html
105 # - improved documentation
106 # - fixed small bug in pstoimg wrt. OS2
107 #
108 # Revision 1.2 1999/05/17 21:30:59 MRO
109 #
110 #
111 # -- make texexpand warning-free and start making it use strict
112 # compliant
113 #
114 # Revision 1.1 1999/05/11 06:10:00 MRO
115 #
116 #
117 # - merged config stuff, did first tries on Linux. Simple document
118 # passes! More test required, have to ger rid of Warnings in texexpand
119 #
120 # Revision 1.18 1999/05/05 19:47:03 MRO
121 #
122 #
123 # - many cosmetic changes
124 # - final backup before merge
125 #
126 # Revision 1.17 1999/03/15 23:00:53 MRO
127 #
128 #
129 # - moved L2hos modules to top level directory, so that no dir-
130 # delimiter is necessary in the @INC-statement.
131 # - changed strategy for "shave": Do not rely on STDERR redirection any
132 # more (caused problems on at least Win32)
133 #
134 # Revision 1.16 1999/02/14 23:44:34 MRO
135 #
136 #
137 # -- first attempt to fix Win32 problems
138 #
139 # Revision 1.15 1999/02/11 00:18:29 MRO
140 #
141 #
142 # -- cleaned up warppers, TeXlive stuff and Makefile
143 #
144 # Revision 1.14 1999/02/10 01:37:12 MRO
145 #
146 #
147 # -- changed os-dependency structure again - now neat OO modules are
148 # used: portable, extensible, neat!
149 # -- some minor cleanups and bugfixes
150 #
151 # Revision 1.13 1998/12/07 23:19:58 MRO
152 #
153 #
154 # -- added POD documentation to pstoimg and did a general cleanup
155 # -- some finetuning of config procedure and modules
156 #
157 # Revision 1.12 1998/10/31 14:13:05 MRO
158 # -- changed OS-dependent module loading strategy: Modules are now located in
159 # different (OS-specific) directories nut have the same name: Easier to
160 # maintain and cleaner code
161 # -- Cleaned up config procedure
162 # -- Extended makefile functionality
163 #
164 # Revision 1.11 1998/08/09 20:45:20 MRO
165 # -- some cleanup
166 #
167 # Revision 1.10 1998/06/14 14:10:38 latex2html
168 # -- Started to implement TeXlive configuration and better OS specific
169 # handling (Batch files) (Marek)
170 #
171 # Revision 1.9 1998/06/07 22:35:24 latex2html
172 # -- included things I learned from the Win95 port to config procedure:
173 # GS_LIB, Win32 module calls, directory separator stuff, ... (Marek)
174 #
175 # Revision 1.8 1998/06/01 12:57:56 latex2html
176 # -- Cleanup and cosmetics.
177 #
178 # Revision 1.7 1998/05/14 22:27:37 latex2html
179 # -- more work on config procedure (Makefile, GS_LIB)
180 # -- tested pstoimg in 98.1 environment successfully on Linux
181 #
182 # Revision 1.6 1998/05/06 22:31:09 latex2html
183 # -- Enhancements to the config procedure: Added a "generic" target
184 # in the Makefile for the TeXlive CD (not perfect yet)
185 # -- included test for kpsewhich / Web2C
186 # -- included latest stuff from Override.pm into os_*.pm
187 #
188 # Revision 1.5 1998/04/28 22:18:11 latex2html
189 # - The platform specific stuff is now kept in a separate perl module. This
190 # does not introduce significant overhead and enhances maintainability.
191 #
192 # Revision 1.4 1998/03/19 23:38:06 latex2html
193 # -- made pstoimg plug-in compatible with old one (touchwood!)
194 # -- cleaned up, added some comments
195 # -- inserted version information output
196 # -- incorporated patches to make OS/2 run better (thanks Uli)
197 # -- updated Makefile: make, make test, make install should work now
198 #
199 # Revision 1.3 1998/03/11 23:44:00 latex2html
200 # -- cleaned up config.pl and reworked dvips checks
201 # -- got pstoimg.pin up to par with the regular pstoimg
202 # -- cosmetic changes
203 # -- runs now under Win95 with Fabrice Popineau's Win32 tools (gs, TeX,...)
204 #
205 # Revision 1.2 1998/03/02 23:38:40 latex2html
206 # Reworked configuration procedure substantially. Fixed some killing bugs.
207 # Should now run on Win32, too.
208 # The file prefs.pm contains user-configurable stuff for DOS platforms.
209 # UNIX users can override the settings with the configure utility (preferred).
210 #
211 # Revision 1.1 1998/02/14 19:31:55 latex2html
212 # Preliminary checkin of configuration procedure
213 #
214 # (end CVS log)
215 ###############################################################################
216
217 # This file has been automatically generated by build.pl from pstoimg.pin
218 # Do not edit this file as your changes will be lost when reconfiguring.
219 # If you want to supply patches, please apply them to pstoimg.pin and send
220 # the diff relative to the original pstoimg.pin. Thank you.
221
222 =head1 NAME
223
224 pstoimg - Convert a PostScript file to a bitmap image using
225 Ghostscript and the Netpbm utilities
226
227 =cut
228
229 use 5.003;
230 use strict;
231 #use diagnostics;
232 use vars qw(*SAVEERR $LATEX2HTMLDIR $SCRIPT);
233
234 # This variable points to the DIRECTORY where the latex2html files
235 # can be found.
236
237 use Getopt::Long;
238
239
240 # see below for a description of the environment
241
242 BEGIN {
243 # print "scanning for l2hdir\n";
244 if($ENV{LATEX2HTMLDIR}) {
245 $LATEX2HTMLDIR = $ENV{LATEX2HTMLDIR};
246 } else {
247 $ENV{LATEX2HTMLDIR} = $LATEX2HTMLDIR = '/usr/share/latex2html';
248 }
249
250 if(-d $LATEX2HTMLDIR) {
251 push(@INC,$LATEX2HTMLDIR);
252 } else {
253 die qq{Fatal: Directory "$LATEX2HTMLDIR" does not exist.\n};
254 }
255 }
256
257 use L2hos; # load OS-specific stuff
258
259 my $RELEASE = '2002-2-1';
260 my ($VERSION) = q$Revision: 1.3 $ =~ /:\s*(\S+)/;
261
262 $| = 1; # unbuffer STDOUT
263
264 my $dd = L2hos->dd; # Directory delimiter
265 my $prompt;
266 ($prompt = $0) =~ s|^.*[/\\]||;
267
268 # Configuration as determined by "configure"
269 #
270 # Ghostscript
271 my $GS = '/usr/bin/gs';
272 my $GSDEVICE = 'pnmraw';
273 my $GSALIASDEVICE = 'ppmraw';
274 # Supported format(s)
275 my @IMAGE_TYPES = qw(png gif);
276 # Netpbm
277 my $PNMCROP = '/usr/bin/pnmcrop -verbose ';
278 my $PNMCROPOPT = '';
279 $PNMCROPOPT = '-sides';
280 my $PPMQUANT = '/usr/bin/ppmquant';
281 my $PNMFLIP = '/usr/bin/pnmflip';
282 my $PNMCAT = '/usr/bin/pnmcat';
283 my $PNMFILE = '/usr/bin/pnmfile';
284 my $PBMMAKE = '/usr/bin/pbmmake';
285 # GIF support
286 my $PPMTOGIF = '/usr/bin/ppmtogif';
287 # PNG support
288 my $PNMTOPNG = '/usr/bin/pnmtopng';
289 # Temporary diskspace
290 my $def_tmp = '/tmp'; # Space for temporary files
291
292 # Some lengths used by dvips
293 # MRO: Is this true for all runs of dvips?
294
295 my $PAGE_HEIGHT = 841.889; # dvips page height, in pts.
296 my $PAGE_WIDTH = 595.275; # dvips page width, in pts.
297 my $PAGE_HMARGIN = 72; # dvips margin: 1 inch = 72pt
298 my $PAGE_VMARGIN = 72; # dvips margin: 1 inch = 72pt
299
300 # The color to be made transparent
301 my $trans_color = '#ffffff';
302
303 ###############################################################################
304 # Default settings
305 # Environment overrides defaults, command line options override everything
306
307 unless(@ARGV) {
308 print_help();
309 exit 0;
310 }
311
312 =head1 SYNOPSIS
313
314 B<pstoimg> B<-help> | B<-version>
315
316 B<pstoimg>
317 S<[ B<-antialias> ]>
318 S<[ B<-aaliastext> ]>
319 S<[ B<-center> I<num> ]>
320 S<[ B<-color> I<num> ]>
321 S<[ B<-crop> I<code> ]>
322 S<[ B<-debug> ]>
323 S<[ B<-density> I<num>]>
324 S<[ B<-depth> I<num> ]>
325 S<[ B<-discard> ]>
326 S<[ B<-flip> I<code> ]>
327 S<[ B<-geometry> I<X>xI<Y> ]>
328 S<[ B<-interlaced> ]>
329 S<[ B<-margins> I<X>,I<Y> ]>
330 S<[ B<-multipage> ]>
331 S<[ B<-out> I<file> ]>
332 S<[ B<-quiet> ]>
333 S<[ B<-rightjustify> I<num> ]>
334 S<[ B<-scale> I<num> ]>
335 S<[ B<-tmp> I<path> ]>
336 S<[ B<-topjustify> [B<x>]I<num> ]>
337 S<[ B<-transparent> ]>
338 S<[ B<-type> I<type> ]>
339 S<[ B<-shoreup> I<num>[B<d>] ]>
340 S<[ B<-white> ]>
341 I<file>
342 S<[ I<file2> ... ]>
343
344 =cut
345
346 my %opt = ();
347 unless(&GetOptions(\%opt, qw(-help -version -debug -discard -antialias -aaliastext
348 -multipage -type=s -gif -png -out=s -depth=i -color=i -flip=s -density=i
349 -scale=f -geometry=s -margins=s -crop=s -transparent -interlaced
350 -rightjustify=i -center=i -topjustify=s -shoreup=s -tmp=s -white -quiet))) {
351 print_usage("$prompt: Error: Invalid option(s) specified.");
352 exit 1;
353 }
354
355 =head1 OPTIONS
356
357 The command line options may be abbreviated to the shortest unique
358 prefix.
359
360 =over 4
361
362 =item B<-help>
363
364 Show this help page and exit.
365
366 =cut
367
368 if($opt{help}) {
369 print_help();
370 exit 0;
371 }
372
373 =item B<-version>
374
375 Show the release and version of pstoimg and exit.
376
377 =cut
378
379 if($opt{version}) {
380 print_version();
381 exit 0;
382 }
383
384 banner() unless($opt{quiet});
385
386 =item B<-antialias>
387
388 Use Ghostscript's anti-aliasing feature for rendering "softer" images.
389 This applies to lines and edges of polygonal and oval or circular shapes.
390 Only valid if Ghostscipt 4.03 or higher is installed.
391
392 =item B<-aaliastext>
393
394 Use Ghostscript's anti-aliasing feature for "smoother" font characters,
395 without the jagged edges. Similar to B<-antialias> for graphic components.
396 Only valid if Ghostscipt 4.03 or higher is installed.
397
398 =item B<-center> I<num>
399
400 Add the appropriate amount of whitespace to the left of the image so
401 that the image appears to be centered in a total width of I<num> pixels.
402
403 =cut
404
405 my $CENTER = 0; # No centering by default
406 if($opt{center}) {
407 $CENTER = $opt{center};
408 die <<"EOF" unless ($CENTER =~ /^\d+$/ && $CENTER > 0);
409 $prompt: Error: Illegal width for -center specified: "$CENTER"
410 Value must be a positive integer.
411 EOF
412 }
413
414 =item B<-crop> I<code>
415
416 Crop the bitmap from the given directions. I<code> may be a string of
417 several cropping instructions, which are executed strictly in the given
418 order. Possible values are: B<h> (horizontal, i.e. crop top and
419 bottom), B<v> (vertical), B<tblr> (top, bottom, left, right) and B<a> (all
420 directions). A special case is B<s>: "shave" the image at the bottom, but only
421 if a single line of whitespace exists.
422
423 =cut
424
425 my $EXTRA_CROP = '';
426 if($opt{crop}) {
427 $EXTRA_CROP = lc($opt{crop});
428 die <<"EOF" unless ( $EXTRA_CROP =~ /^([vhtblras]+)$/i );
429 $prompt: Error: Illegal crop specified: "$EXTRA_CROP"
430 Crop must be h, v, t, b, l, r, a, s or combination
431 EOF
432 }
433
434 =item B<-debug>
435
436 Turn on debugging output. This can get rather verbose. Any intermediate
437 files generated are not removed to help debugging.
438
439 =cut
440
441 if($ENV{DEBUG}) {
442 $opt{debug} = 1;
443 }
444
445 =item B<-density> I<num>
446
447 The density (resolution) in DPI in which to render the bitmap. The default
448 is 72.
449
450 =cut
451
452 my $DENSITY = 72;
453 if($opt{density}) {
454 $DENSITY = $opt{density};
455 }
456 elsif($ENV{DENSITY}) {
457 $DENSITY = $ENV{DENSITY};
458 }
459 die <<"EOF" unless $DENSITY =~ /^\d+$/;
460 $prompt: Error: Illegal density specified: "$DENSITY"
461 Density must be an integer value. Default is 72.
462 EOF
463
464 =item B<-depth> I<num> or B<-color> I<num>
465
466 Specify the color depth of the bitmap. Legal values are 1 (black & white),
467 8 (256 colors) and 24 (true color).
468
469 =cut
470
471 unless($opt{depth}) {
472 if($opt{color}) {
473 $opt{depth} = $opt{color};
474 }
475 elsif($ENV{DEPTH}) {
476 $opt{depth} = $ENV{DEPTH};
477 }
478 else {
479 $opt{depth} = 8;
480 }
481 }
482 die <<"EOF" unless $opt{depth} =~ /^(1|8|24)$/;
483 $prompt: Error: Illegal color depth specified: "$opt{depth}"
484 Depth must be either 1, 8 or 24.
485 EOF
486
487 =item B<-discard>
488
489 Delete the input postscript file if the conversion was successful. Setting
490 the environment DISCARD to a true value (as perl sees it) has the same
491 effect.
492
493 =cut
494
495 if($ENV{DISCARD}) {
496 $opt{discard} = 1;
497 }
498
499 =item B<-flip> I<code>
500
501 Flip all generated output bitmaps. The following codes are recognized:
502 lr (flip left-right), tb (flip top-bottom), xy (flip bottom/left-top/right),
503 r90 and ccw (rotate by 90 degrees counterclockwise), r270 and cw (rotate
504 90 degrees clockwise) and r180 (rotate 180 degrees).
505
506 =cut
507
508 if($opt{flip}) {
509 $opt{flip} = lc($opt{flip});
510 die <<"EOF" unless $opt{flip} =~ /^(lr|tb|xy|r90|ccw|r270|cw|r180)$/;
511 $prompt: Error: Illegal flip option specified: "$opt{flip}"
512 Flip must be one of: lr tb xy r90 ccw r270 cw r180
513 EOF
514 }
515
516 =item B<-geometry> I<X>xI<Y>
517
518 Render only this "window" of the PostScript file. If given, this option
519 can dramatically reduce memory requirements and speed up conversion. The
520 geometry is automatically detected in case of EPS files (Encapsulated
521 PostScript).
522
523 =cut
524
525 my $GEOMETRY = '';
526 if($opt{geometry}) {
527 $GEOMETRY = $opt{geometry};
528 if($GEOMETRY =~ s/-//o ) {
529 $EXTRA_CROP .= 'bl';
530 }
531 die <<"EOF" unless ($GEOMETRY =~ /^\d+x\d+$/i);
532 $prompt: Error: Illegal geometry specified: "$GEOMETRY"
533 Geometry must be <width>x<height>
534 EOF
535 }
536
537 =item B<-interlaced>
538
539 Generate an interlaced bitmap. Interlaced images build up from coarse to
540 fine as they are loaded. This option may not work on every installation
541 and/or bitmap type, depending of the capabilities of external programs.
542
543 =cut
544
545 my $INTERLACE = 0; # Do not make interlaced images by default
546 if($opt{interlaced}) {
547 $INTERLACE=1;
548 }
549
550 =item B<-margins> I<X>,I<Y>
551
552 The offset of the rectangle in the postscript file that is going to be
553 rendered from top/left. Can be used together with B<-geometry> to further
554 reduce the size of the intermediate bitmap file generated by Ghostscript.
555
556 =cut
557
558 if($opt{margins}) {
559 die <<"EOF" unless (($opt{margins} =~ /^(\d+),(\d+)$/));
560 $prompt: Error: Illegal margins specified: "$opt{margins}"
561 Margins must be <hmargin>,<vmargin>
562 EOF
563 $PAGE_HMARGIN = $1;
564 $PAGE_VMARGIN = $2;
565 }
566
567 =item B<-multipage>
568
569 Process a multi-page PostScript file, i.e. create an individual bitmap
570 for every page. The resulting files are numbered: The decimal number
571 (starting with 1) is appended to the basename of the PostScript input
572 file (or the basename of the filename specified with B<-out>), while
573 keeping the extension.
574
575 =item B<-out> I<file>
576
577 The file where to write the bitmap. If multiple PostScript files are
578 supplied on the command line, this option is ignored. The bitmap type
579 extension is appended automatically if I<file> does not contain a dot.
580 In connection with B<-multipage> I<file> is extended by the page number
581 as shown in this example:
582
583 -outfile foo.gif --------E<gt> foo1.gif, foo2.gif, ...
584
585 =cut
586
587 if(!$opt{out} && $ENV{OUTFILE}) {
588 $opt{out} = $ENV{OUTFILE};
589 }
590
591 =item B<-quiet>
592
593 Do not print anything except error messages.
594
595 =item B<-rightjustify> I<num>
596
597 Add the appropriate amount of whitespace to the left of the image so that
598 it appears to be aligned to the right in a total width of I<num> pixels.
599
600 =cut
601
602 my $RIGHT_JUSTIFY = 0; # No right justifying by default
603 if($opt{rightjustify}) {
604 $RIGHT_JUSTIFY = $opt{rightjustify};
605 die <<"EOF" unless ($RIGHT_JUSTIFY =~ /^\d+$/ && $RIGHT_JUSTIFY > 0);
606 $prompt: Error: Illegal width for -rightjustify specified: "$RIGHT_JUSTIFY"
607 Value must be a positive integer.
608 EOF
609 }
610
611 =item B<-scale> I<factor>
612
613 Scale the image by I<factor>. Valid choices are any numbers greater than
614 zero. Useful choices are numbers between 0.1 - 5.
615 Large numbers may generate very large intermediate files and will take
616 longer to process. If this option is omitted, the environment SCALE is
617 considered.
618
619 =cut
620
621 unless($opt{scale}) {
622 if($ENV{SCALE}) {
623 $opt{scale} = $ENV{SCALE};
624 }
625 else {
626 $opt{scale} = 1;
627 }
628 }
629 die <<"EOF" unless ($opt{scale} =~ /^[\d.e]+$/i && $opt{scale} > 0);
630 $prompt: Error: Illegal scale specified: "$opt{scale}"
631 Scale must be nonnegative float value.
632 EOF
633
634 =item B<-shoreup> I<num>[B<d>]
635
636 Make height and width of the bitmap(s) an exact multiple of I<num>. If
637 I<num> is followed by a "d", then half the extra vertical space is placed
638 underneath. This option is useful, if you want to have "blown-up" images
639 of high quality for print, but downscale them in HTML using
640 C<E<lt>IMG WIDTH=x HEIGHT=yE<gt>>. If the actual image is is not an
641 integer multiple of x,y then browsers tend to display distorted images.
642
643 =cut
644
645 my $SHORE_UP = 0; # No pixel alignment by default
646 if($opt{shoreup}) {
647 $SHORE_UP = $opt{shoreup};
648 die <<"EOF" unless $SHORE_UP =~ /^\d+d?$/i;
649 $prompt: Error: Illegal shore-up specified: "$SHORE_UP"
650 Value must be a positive integer, optionally followed by d
651 EOF
652 }
653
654 =item B<-tmp> I<path>
655
656 Use I<path> to store temporary files. Defaults to /tmp on this
657 installation. This parameter can be set by the environment B<TMP> or
658 B<TEMP>, too.
659
660 =cut
661
662 my $TMP = '';
663 if($opt{tmp}) {
664 $opt{tmp} =~ s|\Q$dd\E+$||; # remove trailing directory separator(s)
665 if(-d $opt{tmp} && -r _ && -w _) {
666 $TMP = $opt{tmp};
667 } else {
668 print "$prompt: Warning: Cannot use $opt{tmp} as temporary directory.\n";
669 }
670 }
671 if(!$TMP && ($ENV{TMP} || $ENV{TEMP})) {
672 ($opt{tmp} = $ENV{TMP} || $ENV{TEMP}) =~ s|\Q$dd\E+$||;
673 if(-d $opt{tmp} && -r _ && -w _) {
674 $TMP = $opt{tmp};
675 } else {
676 print "$prompt: Warning: Cannot use $opt{tmp} as temporary directory.\n";
677 }
678 }
679 if(!$TMP && -d $def_tmp && -r _ && -w _) {
680 $TMP = $def_tmp;
681 }
682 print "$prompt: Temporary directory is $TMP\n" if($opt{debug});
683
684 =item B<-topjustify> [B<x>]I<num>
685
686 Add padding whitespace to the image so that it gets a defined height.
687 If an integer value is given, it defines the total height. The whitespace
688 is added at the bottom. If the number is preceded by "x", then this
689 multiple of the image height is added as whitespace at the bottom.
690
691 =cut
692
693 my $TOP_JUSTIFY = 0; # No top justifying by default
694 if($opt{topjustify}) {
695 $TOP_JUSTIFY = $opt{topjustify};
696 die <<"EOF" unless $TOP_JUSTIFY =~ /^x?\d+[.]?\d*$/i;
697 $prompt: Error: Illegal align specified: "$TOP_JUSTIFY"
698 Value must be positive numeric, optionally preceded by x
699 EOF
700 }
701
702 =item B<-transparent>
703
704 Generate transparent bitmaps, i.e. the background color (white) is
705 transparent if viewed with certain viewers (e.g. browsers). This option
706 may not be available due to missing capabilities of external
707 programs.
708
709 =cut
710
711 my $TRANSPARENT = 0; # Do not make make images transparent by default
712 if($opt{transparent}) {
713 $TRANSPARENT = 1;
714 }
715
716 =item B<-type> I<type>
717
718 Instruct pstoimg to render the bitmap in I<type> format. Depending on
719 the local installation, pstoimg is capable of generating either GIF or
720 PNG bitmaps. This site features the following types: png gif
721
722 If omitted, the first type in this list is taken.
723
724 =cut
725
726 if($opt{type}) {
727 $opt{type} = lc($opt{type});
728 die <<"EOF" unless grep($_ eq $opt{type},@IMAGE_TYPES);
729 $prompt: Error: This version of pstoimg does not support
730 "$opt{type}" image format.
731 EOF
732 }
733 else {
734 ($opt{type}) = @IMAGE_TYPES; # default image type
735 }
736 # Support -gif and -png for a transition period
737 if($opt{gif}) {
738 print qq{$prompt: Warning: The -gif switch is deprecated. Use "-type gif" instead.\n};
739 if(grep($_ eq 'gif',@IMAGE_TYPES)) {
740 $opt{type} = 'gif';
741 }
742 else {
743 die <<"EOF";
744 $prompt: Error: This version of pstoimg does not support "gif" format.
745 EOF
746 }
747 }
748 if($opt{png}) {
749 print qq{$prompt: Warning: The -png switch is deprecated. Use "-type png" instead.\n};
750 if(grep($_ eq 'png',@IMAGE_TYPES)) {
751 $opt{type} = 'png';
752 }
753 else {
754 die <<"EOF";
755 $prompt: Error: This version of pstoimg does not support "png" format.
756 EOF
757 }
758 }
759
760 =item B<-white>
761
762 Remove TeX's page color information from the PostScript file before
763 converting so that a white background is used.
764
765 =back
766
767 =cut
768
769 # do some consistency checks on the options
770
771
772 die <<"EOF" if($RIGHT_JUSTIFY && $CENTER);
773 $prompt: Error: Conflicting options -center and -rightjustify.
774 EOF
775
776 # now setup some parameters
777
778 # calculate dpi resolution from density and scale
779 $DENSITY = int($opt{scale} * $DENSITY + .5) if($opt{scale} != 1);
780
781 my $reduce_color = '';
782 if($opt{depth} == 1) {
783 $reduce_color = "$PPMQUANT 2";
784 }
785 elsif ($opt{depth} == 8) {
786 $reduce_color = "$PPMQUANT 256";
787 }
788
789 my $gs_aalias = '';
790 if($opt{antialias}) {
791 $GSDEVICE = $GSALIASDEVICE;
792 if($opt{depth} == 1) {
793 $gs_aalias = '-dTextAlphaBits=4 ';
794 $reduce_color = "$PPMQUANT -floyd 256";
795 }
796 else {
797 $gs_aalias = '-dTextAlphaBits=4 -dGraphicsAlphaBits=4 ';
798 }
799 }
800 elsif ($opt{aaliastext}) {
801 $GSDEVICE = $GSALIASDEVICE;
802 $gs_aalias = '-dTextAlphaBits=4 ';
803 $reduce_color = "$PPMQUANT -floyd 256";
804 }
805 my $PAPERSIZE = $ENV{PAPERSIZE} || '';
806 # This rx matches float values in Bounding Box expressions
807 my $Brx = '-?\d+(?:\.\d*|)';
808
809 ##############################################################################
810 # Main program
811
812 =head1 DESCRIPTION
813
814 B<pstoimg> iterates over the given input files and runs them through
815 Ghostscipt. The resulting pnm (portable anymap files) are processed
816 with different Netpbm tools (cropping, color mapping, aligning, ...)
817 and finally converted into (currently) either GIF or PNG format. The
818 bitmaps can now be included e.g. in WWW pages.
819
820 The PostScript file is converted as is. If a valid bounding box is
821 found (EPS format), then only this area is converted. The image is
822 I<not> cropped by default.
823
824 =cut
825
826 die "$prompt: Error: No input file(s) specified\n"
827 unless(@ARGV);
828
829 # suppress diagnostics messages if possible
830 my $NULLFILE = '/dev/null';
831 open(STDERR, ">$NULLFILE") unless($opt{debug});
832
833 my $exit = 0;
834
835 $opt{out} = '' if(@ARGV > 1); # disable -out if multiple ps files given
836
837 my $psfile;
838 foreach $psfile (@ARGV) {
839 unless (-f $psfile) {
840 print qq{$prompt: Error: Cannot find file "$psfile": $!\n};
841 exit 1;
842 }
843 $exit += (&pstoimg($psfile) ? 0 : 1);
844 }
845
846 =head1 RETURN VALUE
847
848 =over 4
849
850 =item 0
851
852 if everything went all right
853
854 =item x
855
856 (x != 0) something went wrong. See the message output.
857
858 =back
859
860 =cut
861
862 exit $exit ? 1 : 0;
863
864 ##############################################################################
865 # Subroutines
866
867 sub pstoimg {
868 my ($psfile) = @_;
869
870 print "$prompt: Processing $psfile\n" unless($opt{quiet});
871 # remove a trailing suffix the same way a shell would do it
872 my $base = $psfile;
873 $base =~ s|[.][^.$dd$dd]*$||;
874
875 my $outfile;
876 if($opt{out}) {
877 $outfile = $opt{out};
878 # append the type unless -outfile has a "." in it
879 $outfile .= ".$opt{type}" unless($outfile =~ /[.]/);
880 }
881 else {
882 $outfile = "$base.$opt{type}";
883 }
884
885 # Invoke Ghostscript
886 my $pnmdir = $TMP ? "$TMP$dd" : ".$dd";
887 my $pnmbase = "p$$"; # keep it short for dos
888 my $pnmfile = $pnmdir .
889 ($opt{multipage} ? "%d_${pnmbase}.pnm" : "$pnmbase.pnm");
890
891 ps2pnm($psfile,$pnmfile) || return 0;
892
893 my $ok = 1;
894 if (-f $pnmfile) {
895 if(crop_scale_etc($pnmfile, $outfile)) {
896 L2hos->Unlink($pnmfile) unless($opt{debug});
897 }
898 else {
899 return 0;
900 }
901 }
902 elsif($opt{multipage}) {
903 unless(opendir(DIR,$pnmdir)) {
904 print qq{$prompt: Error: Could not open directory "$pnmdir": $!\n};
905 return 0;
906 }
907 my @list = grep(/^\d+_\w*\./,readdir(DIR));
908 closedir(DIR);
909 if(@list) {
910 my $i;
911 foreach $i (@list) {
912 my ($n) = $i =~ /^(\d+)_/;
913 my $j = $outfile;
914 $j =~ s|(\.[^/.]*)$|$n$1|;
915 if(crop_scale_etc("$pnmdir$i", $j)) {
916 L2hos->Unlink("$pnmdir$i") unless($opt{debug});
917 }
918 else {
919 $ok = 0;
920 }
921 }
922 }
923 else {
924 goto not_found;
925 }
926 }
927 else {
928 not_found:
929 print "$prompt: Error: Couldn't find pnm output of $psfile\n";
930 }
931 L2hos->Unlink($psfile) if($opt{discard} && !$opt{debug});
932 $ok;
933 }
934
935 sub ps2pnm {
936 my ($psfile,$pnmfile) = @_;
937 my $gs_size = $PAPERSIZE ? "-sPAPERSIZE=$PAPERSIZE" : '';
938 my $gs_density = ($DENSITY != 72) ? "-r$DENSITY" : '';
939
940 my ($bbx, $bby, $bbw, $bbh) = (0,0,0,0);
941 my $max_lines = 100;
942 my ($epsf,$have_geometry) = (0,0);
943
944 # Parse postscript file for information
945 unless(open(PS, "<$psfile")) {
946 print qq{$prompt: Error: Cannot read "$psfile": $!};
947 return 0;
948 }
949 $_ = <PS>; # read one line
950 if( /^%!.*EPSF/ ) {
951 # we're in a EPSF file
952 $epsf = 1;
953 }
954 if($GEOMETRY || $epsf) {
955 while (defined ($_ = <PS>)) {
956 # Look for bounding box comment
957 # MRO: add support of precise bounding boxes
958 if ($epsf && (
959 /^%+(?:HiRes|Exact)BoundingBox:\s+($Brx)\s+($Brx)\s+($Brx)\s+($Brx)/o ||
960 /^\%\%BoundingBox:\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)/)) {
961 $bbx = 0 - $1; $bby = 0 - $2;
962 $bbw = $3 + $bbx; $bbh = $4 + $bby;
963 if(($bbw > 0) && ($bbh > 0)) { # we have a valid bounding box
964 print "$prompt: EPSF dimensions are ${bbw}x$bbh\n" if($opt{debug});
965 # this overrides the -geometry switch
966 if($DENSITY) { # scale the output
967 my $scale = $DENSITY / 72.0;
968 $bbw *= $scale;
969 $bbh *= $scale;
970 }
971 $bbw = int($bbw + 0.99);
972 $bbh = int($bbh + 0.99);
973 $GEOMETRY = "${bbw}x${bbh}";
974 $have_geometry = 1;
975 last;
976 }
977 }
978 # Look for page size information
979 elsif($GEOMETRY && /TeXDict\s+begin\s+(\d+)\s+(\d+)\s+/) {
980 $PAGE_WIDTH = int($1 / 65536 * 72 /72.27 +.5);
981 $PAGE_HEIGHT = int($2 / 65536 * 72 /72.27 +.5);
982 print "$prompt: Page dimensions are ${PAGE_WIDTH}x$PAGE_HEIGHT\n"
983 if($opt{debug});
984 # we don't have to look further for EPSF stuff at this point
985 last;
986 }
987 elsif(!$GEOMETRY && (/^\%\%EndComments/ || --$max_lines == 0)) {
988 # abort at a certain point to avoid scanning huge ps files
989 last;
990 }
991 }
992 }
993 close PS;
994 if($GEOMETRY && !$have_geometry) { # RRM: overrides $PAPERSIZE
995 # no geometry info found in the Postscript file
996 $bbx = $PAGE_HMARGIN;
997 $bby = $PAGE_HEIGHT - $PAGE_VMARGIN;
998 unless($GEOMETRY =~ /\s*(\d+)x(\d+)/i) {
999 print qq{$prompt: Illegal geometry "$GEOMETRY" specified.\n};
1000 return 0;
1001 }
1002 $bbw = $1 + 10; # allow for the side-bars
1003 $bbh = $2;
1004 $bby = int(-$bby + $bbh + 8); # allow small margin for error
1005 $bbx = int(-$bbx + 5); # allow small margin for error
1006 if($DENSITY) {
1007 my $scale = $DENSITY / 72.0;
1008 $bbw = int($scale * $bbw + .99);
1009 $bbh = int($scale * $bbh + .99);
1010 }
1011 $bbw += 10; # add a 5pt margin for safety
1012 $bbh += 40; # add a 20pt margin for safety
1013 $GEOMETRY = "${bbw}x$bbh";
1014 $have_geometry = 1;
1015 }
1016 if($have_geometry) {
1017 $gs_size = "-g$GEOMETRY ";
1018 }
1019
1020 my $ps_changed = 0;
1021 if($have_geometry || $opt{white}) {
1022 # Remove any Postscript commands concerning Papersize if -g switch is used
1023 # thanks to Axel Ramge for identifying the problem and for this code
1024 local($/) = undef;
1025 open(PS,"<$psfile");
1026 my $ps = <PS>;
1027 close(PS);
1028 my $had_papersize;
1029 if($have_geometry) {
1030 $had_papersize = ($ps =~ s/\n%%BeginPaperSize.*?%%EndPaperSize[^\n]*\n/\n/sg);
1031 }
1032 my $had_nonwhite;
1033 if($opt{white}) {
1034 $had_nonwhite = ($ps =~ s/(\n\d+ \d+ bop gsave) \d*\.\d+ (TeXcolorgray clippath fill grestore)/$1 1 $2/s);
1035 }
1036 $ps_changed = $had_papersize || $had_nonwhite;
1037 if($ps_changed) {
1038 my $tmppsfile = $pnmfile; # was "tmpps$$.ps"
1039 $tmppsfile =~ s/\.[^.]*$/.ps/;
1040 unless(open(PS,">$tmppsfile") && (print PS $ps) && (close PS)) {
1041 if($had_papersize) {
1042 print <<"EOF";
1043 $prompt: Warning: Could not write "$tmppsfile": $!
1044 "$psfile" contains %%Papersize comments.
1045 Any of these should be removed else GS will fail.
1046 EOF
1047 }
1048 if($had_nonwhite) {
1049 print <<"EOF";
1050 $prompt: Warning: Could not write "$tmppsfile": $!
1051 "$psfile" has a non-white background.
1052 This may cause ugly images.
1053 EOF
1054 }
1055 }
1056 $psfile = $tmppsfile;
1057 print qq{Debug: Papersize comment in "$psfile" deleted.\n}
1058 if($had_papersize && $opt{debug});
1059 print qq{Debug: Background switched to white in "$psfile".\n}
1060 if($had_nonwhite && $opt{debug});
1061 }
1062 }
1063
1064 my $gs_quiet = $opt{debug} ? '' : '-q -dNOPAUSE -dNO_PAUSE';
1065 my $out_redirect = $opt{debug} ? '' : "> $NULLFILE";
1066 my $gs_out = "-sOutputFile=$pnmfile";
1067 my $gsfile = $psfile;
1068 # Ghostscript understands only '/' as path delimiter!
1069 if($opt{debug}) {
1070 print "$prompt: Running $GS $gs_quiet -sDEVICE=$GSDEVICE $gs_size $gs_density $gs_aalias $gs_out $out_redirect\n";
1071 print "GS>$bbx $bby translate\n" if($have_geometry);
1072 print "GS>($gsfile) run\n";
1073 print "GS>showpage\n" if ($epsf);
1074 print "GS>quit\n";
1075 }
1076 open (GS, "|$GS $gs_quiet -sDEVICE=$GSDEVICE $gs_size $gs_density $gs_aalias $gs_out $out_redirect");
1077 print GS "$bbx $bby translate\n" if ($have_geometry);
1078 print GS "($gsfile) run\n";
1079 print GS "showpage\n" if ($epsf);
1080 print GS "quit\n";
1081 print "\n" if($opt{debug});
1082 unless(close(GS)) {
1083 print "$prompt: Error: Ghostscript returned error status ",$?>>8,"\n";
1084 }
1085 L2hos->Unlink($psfile) if($ps_changed && !$opt{debug});
1086 1;
1087 }
1088
1089
1090 # This sub post-processes the PNM images that come out of Ghostscript.
1091 # The image is cropped, flipped and finally converted to PNG or GIF.
1092
1093 sub crop_scale_etc {
1094 my ($in, $out) = @_;
1095
1096 # create temp filename; should be auto-incrementable
1097 my $tmp = $in;
1098 $tmp =~ s/(\.[^.]*)?$/.t00/;
1099 # save the original Ghostscript result
1100 if($opt{debug}) {
1101 L2hos->Copy($in,$tmp);
1102 &increment_name($tmp);
1103 }
1104 my ($cmd,$type,$width,$height,$just);
1105
1106 my $must_align = 0;
1107 #$EXTRA_CROP = "a$EXTRA_CROP" # hack to ensure first all-over cropping
1108 # unless($EXTRA_CROP =~ /^a/i);
1109
1110 # RRM: Remove justification bars
1111 $EXTRA_CROP =~ s/h/bt/gi; # crop horizontally
1112 $EXTRA_CROP =~ s/v/rl/gi; # crop vertically
1113 while ($EXTRA_CROP =~ /([atblrs])/gi) {
1114 my $edge = $1;
1115 my $croparg = '';
1116 if($edge =~ /b/i) {
1117 $croparg = "-bot $PNMCROPOPT ";
1118 } elsif($edge =~ /[tlr]/i) {
1119 $croparg = "-$edge $PNMCROPOPT ";
1120 } elsif($edge =~ /s/i) {
1121 #RRM: shave at most 1-2 rows of white from the bottom
1122 if($cmd) {
1123 # Terminate command pipe
1124 ### CNH trick to get rid of black lines at bottom of some equations
1125 $cmd .= "| pnmcrop -white -bot -verbose | pnmcrop -black -bot -verbose | pnmcrop -white -bot -verbose | pnmcrop -black -bot -verbose";
1126 &do_cmd($in,$tmp,$cmd) || return 0; # failure
1127 $cmd = '';
1128 }
1129 my ($type,$width,$height) = get_image_geometry($in);
1130 next unless($type); # skip if no geometry
1131 if(&do_cmd_norename("$PNMCROP $PNMCROPOPT -bot < $in",$tmp)) {
1132 my ($type,$width,$height2) = get_image_geometry($tmp);
1133 if($type && ($height - $height2) < 3 ) {
1134 # command succeeded and shaved less than 3 rows
1135 if($opt{debug}&&(-f $tmp)) {
1136 L2hos->Copy($tmp,$in);
1137 &increment_name($tmp);
1138 } elsif (-f $tmp) {
1139 L2hos->Rename($tmp,$in);
1140 }
1141 next;
1142 }
1143 }
1144 # MRO: this shouldn't be necessary: L2hos->Unlink($tmp);
1145 next; # go to next crop argument
1146 } # end switch on crop codes
1147 if($cmd) {
1148 # Continue command pipe
1149 $cmd .= "| $PNMCROP $croparg";
1150 } else {
1151 # start new pipe
1152 $cmd = "$PNMCROP $croparg< $in ";
1153 }
1154 } # end cropping
1155
1156
1157 if($opt{flip}) {
1158 unless($cmd) {
1159 $cmd = "$PNMFLIP -$opt{flip} < $in";
1160 } else {
1161 $cmd .= "| $PNMFLIP -$opt{flip} ";
1162 }
1163 }
1164
1165 if($RIGHT_JUSTIFY || $TOP_JUSTIFY || $CENTER || $SHORE_UP) {
1166 if($cmd) {
1167 # empty command pipe, we need the image's geometry
1168 &do_cmd($in,$tmp,$cmd);
1169 $cmd='';
1170 }
1171
1172 # Get bitmap type and dimensions
1173 ($type,$width,$height) = &get_image_geometry($in);
1174 return 0 unless($type);
1175
1176 my ($white_left,$white_right,$white_top,$white_bottom) = (0,0,0,0);
1177
1178 if($RIGHT_JUSTIFY || $CENTER) {
1179 if($RIGHT_JUSTIFY) {
1180 $white_left = int($RIGHT_JUSTIFY-$width);
1181 } else { # CENTER
1182 $white_left = int(($CENTER-$width) / 2);
1183 }
1184 $white_left = 0 unless($white_left > 0);
1185
1186 $width += $white_left;
1187 }
1188
1189 if($TOP_JUSTIFY) {
1190 if($TOP_JUSTIFY =~ /^x([0-9.]+)/io) {
1191 $white_bottom = $1 * $height;
1192 } else {
1193 $white_bottom = $TOP_JUSTIFY - $height;
1194 }
1195 if($white_bottom > 0) {
1196 $white_bottom = int($white_bottom + 0.99); # round up
1197 $height += $white_bottom;
1198 } else {
1199 $white_bottom = 0;
1200 }
1201 }
1202
1203 if($SHORE_UP =~ /(\d+)(d?)/ && $1) {
1204 # RRM: make height and width an exact multiple of $SHORE_UP
1205 my ($shoreup,$depth) = ($1,$2);
1206 my $extra = $height % $shoreup;
1207 if($depth) { # image needs depth, place half the extra space underneath
1208 my $bextra = int($extra/2);
1209 $white_bottom += $bextra;
1210 $white_top += $extra - $bextra;
1211 } else {
1212 $white_top += $extra;
1213 }
1214
1215 $extra = $width % $shoreup;
1216 my $rextra = int($extra/2);
1217 $white_right += $rextra;
1218 $white_left += $extra - $rextra;
1219 $cmd = '';
1220 }
1221
1222
1223 if($white_left) {
1224 if($cmd) {
1225 &do_cmd($in,$tmp,$cmd) || return 0;
1226 }
1227 # Start new command pipe
1228 $cmd = "$PBMMAKE -white $white_left 1 | $PNMCAT -white -lr - $in ";
1229 }
1230
1231 if($white_right) {
1232 if($cmd) {
1233 &do_cmd($in,$tmp,$cmd) || return 0;
1234 }
1235 # Start new command pipe
1236 $cmd = "$PBMMAKE -white $white_right 1 | $PNMCAT -white -lr $in - ";
1237 }
1238
1239 if($white_top) {
1240 if($cmd) {
1241 &do_cmd($in,$tmp,$cmd) || return 0;
1242 }
1243 # Start new command pipe
1244 $cmd = "$PBMMAKE -white 1 $white_top | $PNMCAT -white -tb - $in ";
1245 }
1246
1247 if($white_bottom) {
1248 if($cmd) {
1249 &do_cmd($in,$tmp,$cmd) || return 0;
1250 }
1251 # Start new command pipe
1252 $cmd = "$PBMMAKE -white 1 $white_bottom | $PNMCAT -white -tb $in - ";
1253 }
1254 } # endif must_align
1255
1256 my $pnmtoimg;
1257 if($opt{type} eq 'gif') {
1258 $pnmtoimg = $PPMTOGIF;
1259 if($INTERLACE) {
1260 $pnmtoimg .= ' -interlace';
1261 }
1262 if($TRANSPARENT) {
1263 $pnmtoimg .= ' -trans ' . L2hos->quote($trans_color);
1264 }
1265 }
1266 if($opt{type} eq 'png') {
1267 $pnmtoimg = $PNMTOPNG;
1268 if($INTERLACE) {
1269 $pnmtoimg .= ' -interlace';
1270 }
1271 if($TRANSPARENT) {
1272 $pnmtoimg .= ' -trans ' . L2hos->quote($trans_color);
1273 }
1274 }
1275 unless($pnmtoimg) {
1276 print qq($prompt: Error: unknown image type "$opt{type}".\n);
1277 exit 2;
1278 }
1279
1280 unless($type) {
1281 ($type,$width,$height) = &get_image_geometry($in);
1282 return 0 unless($type);
1283 }
1284 # run ppmquant only on color/gray images
1285 if(!$type || $type =~ /(ppm|pgm)/i) {
1286 if($cmd) {
1287 $cmd .= "| $reduce_color "
1288 } else {
1289 $cmd = "$reduce_color < $in ";
1290 }
1291 }
1292
1293 if($cmd) {
1294 $cmd .= "| $pnmtoimg "
1295 } else {
1296 $cmd = "$pnmtoimg < $in ";
1297 }
1298 &do_cmd_norename($cmd,$out) || return 0;
1299 print qq{$prompt: Written $out\n} unless($opt{quiet});
1300
1301 1;
1302 }
1303
1304 sub banner {
1305 print "$prompt V$RELEASE (Revision $VERSION, Perl $])\n";
1306 }
1307
1308 sub print_version {
1309 my $formats = join(',',@IMAGE_TYPES);
1310 print <<"EOM";
1311 $prompt (Revision $VERSION, perl $]),
1312 part of LaTeX2HTML Release V$RELEASE.
1313
1314 Supported output image format(s): $formats
1315 EOM
1316 1;
1317 }
1318
1319 sub print_help {
1320 L2hos->perldoc($SCRIPT);
1321 1;
1322 }
1323
1324 sub print_usage {
1325 my $start = 0;
1326 my $usage = 'Usage: ';
1327 my $indent = '';
1328
1329 print (@_, "\n") if @_;
1330
1331 my $perldoc = '/usr/bin'.$dd."perldoc";
1332 my $script = $SCRIPT || $0;
1333 open(PIPE, "$perldoc -t $script |")
1334 || die "Fatal: can't open pipe: $!";
1335 while (<PIPE>)
1336 {
1337 if (/^\s*$/) {
1338 next;
1339 } elsif (/^SYNOPSIS/) {
1340 $start = 1;
1341 } elsif (/^\w/) {
1342 $start = 0;
1343 } elsif ($start == 1) {
1344 ($indent) = /^(\s*)/;
1345 s/^$indent/$usage/;
1346 $usage =~ s/./ /g;
1347 $start = 2;
1348 print $_;
1349 } elsif ($start == 2) {
1350 s/^$indent/$usage/;
1351 print $_;
1352 }
1353 }
1354 close PIPE;
1355 1;
1356 }
1357
1358 sub do_cmd {
1359 my ($in,$tmp,$cmd) = @_;
1360
1361 print qq{Running "$cmd > $tmp"\n} if($opt{debug});
1362 my $stat = system("$cmd > $tmp");
1363 if($stat) { # error
1364 print qq{$prompt: Error: "$cmd > $tmp" failed: $!\n};
1365 return 0; # failure
1366 }
1367 elsif(!-s $tmp) { # does not exist or zero size
1368 print qq{$prompt: Error: "$cmd > $tmp" produced empty file\n};
1369 L2hos->Unlink($tmp) if(-e $tmp);
1370 return 0; # failure
1371 }
1372 if($opt{debug}) {
1373 # increase the temporary filename by 1
1374 # this uses perl's magic autoincrement
1375 &increment_name($_[1]);
1376 return L2hos->Copy($tmp,$in);
1377 } elsif(!L2hos->Rename($tmp,$in)) {
1378 print qq{$prompt: Error: rename of "$tmp" to "$in" failed: $!\n};
1379 return 0; # failure
1380 }
1381 1;
1382 }
1383
1384 sub do_cmd_norename {
1385 my ($cmd,$out) = @_;
1386
1387 print qq{Running "$cmd > $out"\n} if($opt{debug});
1388 my $stat = system("$cmd > $out");
1389 if($stat) { # error
1390 print qq{$prompt: Error: "$cmd > $out" failed: $!\n};
1391 return 0; # failure
1392 }
1393 elsif(!-s $out) { # does not exist or zero size
1394 print qq{$prompt: Error: "$cmd > $out" produced empty file\n};
1395 L2hos->Unlink($out) if(-e $out);
1396 return 0; # failure
1397 }
1398 1;
1399 }
1400
1401 sub do_cmd_plain {
1402 my ($cmd) = @_;
1403
1404 print qq{Running "$cmd"\n} if($opt{debug});
1405 my $stat = system($cmd);
1406 if($stat) { # error
1407 print qq{$prompt: Error: "$cmd" failed: $!\n};
1408 return 0; # failure
1409 }
1410 1;
1411 }
1412
1413 sub get_image_geometry {
1414 my ($pnmfile) = @_;
1415
1416 my ($type,$width,$height);
1417 my $out = `$PNMFILE $pnmfile`;
1418 if($? || $out =~ /(P[BGP]M)[^0-9]*(\d+)\s*by\s*(\d+)/i) {
1419 $type = $1;
1420 $width = $2;
1421 $height = $3;
1422 print qq{Image "$pnmfile" is $type, ${width}x$height\n} if($opt{debug});
1423 } else {
1424 print "$prompt: Error: Could not determine image size: $out\n";
1425 return undef;
1426 }
1427 ($type,$width,$height);
1428 }
1429
1430 # push the number in the suffix up one notch
1431 sub increment_name {
1432 $_[0] =~ s/(\d+)$/$a=$1;++$a/e;
1433 }
1434
1435 __DATA__
1436
1437 =head1 EXAMPLES
1438
1439 =over 4
1440
1441 =item C<pstoimg foo.ps>
1442
1443 Convert the first page of foo.ps to the default bitmap type.
1444
1445 =item C<pstoimg -type png -crop a -trans -interlace foo.ps>
1446
1447 Same as above, but force png output and crop all the whitespace
1448 around the image and make the color white transparent and
1449 generate an interlaced bitmap.
1450
1451 =item C<pstoimg -multi -out bar -type gif -crop a foo.ps>
1452
1453 Consider foo.ps a multiple page PostScript file and create output
1454 files bar1.gif, bar2.gif, etc.
1455
1456 =back
1457
1458 =head1 ENVIRONMENT
1459
1460 =over 4
1461
1462 =item DENSITY, DEPTH, DEBUG, DISCARD
1463
1464 See B<-density>, B<-depth>, B<-debug>, B<-discard>, respectively.
1465
1466 =item GS_LIB
1467
1468 This variable is set to the path(s) where Ghostscript libraries have
1469 been found on this system during configuration, but only if the built-in
1470 paths are not correct. This fixes the problem of relocation that is quite
1471 common on Win32 installations. This behavior can be overridden by
1472 setting GS_LIB manually before starting pstoimg.
1473
1474 =item LATEX2HTMLDIR
1475
1476 The directory where the LaTeX2HTML library and perl modules are found.
1477 Defaults to "/usr/share/latex2html" on this installation.
1478
1479 =item OUTFILE
1480
1481 Setting this has the same effect as specifying B<-out>. Please do not rely
1482 on this feature any more, it will disappear from the next releases!
1483
1484 =item PAPERSIZE
1485
1486 The papersize to use by Ghostscript to render the image. pstoimg tries
1487 hard to optimize for rendering on the smallest possible bitmap size.
1488 Still this option is there to enable tuning by hand, although it is
1489 deprecated. If pstoimg finds a better setting, this parameter is ignored.
1490
1491 =item SCALE
1492
1493 See the discussion of B<-scale>.
1494
1495 =item TMP and TEMP
1496
1497 Unless overridden by B<-tmp>, these variables denote a directory where
1498 to store temporary files. TMP is considered first, then TEMP.
1499
1500 =back
1501
1502 =head1 SEE ALSO
1503
1504 gs, pnmcrop, pnmquant, pbmmake, pnmcat, pnmfile, pnmflip, ppmtogif,
1505 pnmtopng, giftool, giftrans.
1506
1507 =head1 NOTES
1508
1509 Several people have suggested to use ImageMagick's convert instead of
1510 pstoimg. A few comments on this: convert uses (of course) Ghostscript
1511 for conversion of PostScript to bitmap, so one still needs gs. And
1512 for the special requirements of LaTeX2HTML convert's features are not
1513 sufficient. The ImageMagick toolset has everything in place, but it
1514 has some overhead that can prove killing when processing some 100
1515 images. pstoimg only does what it really has to, so it should be
1516 quite efficient. Don't get me wrong - I like ImageMagick, but not in
1517 the context of LaTeX2HTML.
1518
1519 =head1 CAVEATS
1520
1521 This utility is automatically configured and built to work on the
1522 local setup. If this setup changes (e.g. some of the external commands
1523 are moved), the script has be be reconfigured.
1524
1525 Despite the portability of perl, a pstoimg configured on UNIX will
1526 probably not work on Win32 and vice versa.
1527
1528 =head1 BUGS
1529
1530 This is a major enhancement release, so there may be a few bugs. As
1531 the user inteface changed a bit, some of your tools that were using
1532 pstoimg may not work any more.
1533
1534 Please report bugs to latex2html@tug.org, stating the (debug) output
1535 of pstoimg, your perl version and the versions of the external tools.
1536 Best is to include the cfgcache.pm file from the configuration procedure.
1537
1538 =head1 AUTHOR
1539
1540 Marek Rouchal E<lt>marek@saftsack.fs.uni-bayreuth.deE<gt>
1541
1542 =head1 HISTORY
1543
1544 This script went through a long evolution, beginning with a modification
1545 of Doug Crabill's E<lt>dgc@cs.purdue.eduE<gt> ps2epsi script.
1546 The first perl version was done by Nikos Drakos <nikos@cbl.leeds.ac.uk>.
1547 It was gradually improved by numerous LaTeX2HTML developers:
1548 Ross Moore <ross@mpce.mq.edu.au>, Jens Lippmann
1549 <lippmann@rbg.informatik.tu-darmstadt.de> and others (sorry for not
1550 mentioning everyone and thanks for your contributions).
1551
1552 =cut

  ViewVC Help
Powered by ViewVC 1.1.22