/[MITgcm]/manual/pstoimg
ViewVC logotype

Annotation of /manual/pstoimg

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


Revision 1.1 - (hide annotations) (download)
Fri Jul 15 13:07:23 2005 UTC (18 years, 9 months ago) by cnh
Branch: MAIN
More cunning tricks to get rid of black lines
 pnmcrop is junk!

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

  ViewVC Help
Powered by ViewVC 1.1.22