/[MITgcm]/manual/pstoimg
ViewVC logotype

Annotation of /manual/pstoimg

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


Revision 1.4 - (hide annotations) (download)
Fri Jul 15 13:37:56 2005 UTC (17 years, 4 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 cnh 1.1 #! /usr/bin/perl -w
2     ##############################################################################
3 cnh 1.4 # $Id: pstoimg,v 1.3 2005/07/15 13:29:25 cnh Exp $
4 cnh 1.1 #
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 cnh 1.2 # $Log: pstoimg,v $
18 cnh 1.4 # Revision 1.3 2005/07/15 13:29:25 cnh
19     # Tidying paths to make it work elsewhere - maybe?
20     #
21 cnh 1.3 # Revision 1.2 2005/07/15 13:20:56 cnh
22     # Slight change to the fix - plus relative path in .latex2html-init
23     #
24 cnh 1.2 # 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 cnh 1.1 # 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 cnh 1.4 my ($VERSION) = q$Revision: 1.3 $ =~ /:\s*(\S+)/;
261 cnh 1.1
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 cnh 1.3 my $PNMCROP = '/usr/bin/pnmcrop -verbose ';
278 cnh 1.1 my $PNMCROPOPT = '';
279 cnh 1.3 $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 cnh 1.1 # GIF support
286 cnh 1.3 my $PPMTOGIF = '/usr/bin/ppmtogif';
287 cnh 1.1 # PNG support
288 cnh 1.3 my $PNMTOPNG = '/usr/bin/pnmtopng';
289 cnh 1.1 # 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 cnh 1.3 my $trans_color = '#ffffff';
302 cnh 1.1
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 cnh 1.3 my $croparg = '';
1116 cnh 1.1 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 1.2 ### 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 cnh 1.1 &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 cnh 1.3 if($type && ($height - $height2) < 3 ) {
1134 cnh 1.1 # 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
1553    

  ViewVC Help
Powered by ViewVC 1.1.22