/[MITgcm]/manual/pstoimg
ViewVC logotype

Annotation of /manual/pstoimg

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


Revision 1.3 - (hide annotations) (download)
Fri Jul 15 13:29:25 2005 UTC (18 years, 9 months ago) by cnh
Branch: MAIN
Changes since 1.2: +18 -20 lines
Tidying paths to make it work elsewhere - maybe?

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

  ViewVC Help
Powered by ViewVC 1.1.22