/[MITgcm]/manual/pstoimg
ViewVC logotype

Annotation of /manual/pstoimg

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


Revision 1.2 - (hide annotations) (download)
Fri Jul 15 13:20:56 2005 UTC (18 years, 8 months ago) by cnh
Branch: MAIN
Changes since 1.1: +9 -4 lines
Slight change to the fix - plus relative path in .latex2html-init

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

  ViewVC Help
Powered by ViewVC 1.1.22