/[MITgcm]/manual/pstoimg
ViewVC logotype

Contents of /manual/pstoimg

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


Revision 1.3 - (show 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 #! /usr/bin/perl -w
2 ##############################################################################
3 # $Id: pstoimg,v 1.2 2005/07/15 13:20:56 cnh Exp $
4 #
5 # pstoimg
6 #
7 # Accompanies LaTeX2HTML
8 #
9 # Script to convert an arbitrary PostScript image to a cropped GIF or PNG
10 # image suitable for incorporation into HTML documents as inlined images
11 # to be viewed with WWW browsers.
12 #
13 # This software is provided as is without any guarantee.
14 #
15 ##############################################################################
16 #
17 # $Log: pstoimg,v $
18 # Revision 1.2 2005/07/15 13:20:56 cnh
19 # Slight change to the fix - plus relative path in .latex2html-init
20 #
21 # 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 # 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 my ($VERSION) = q$Revision: 1.2 $ =~ /:\s*(\S+)/;
258
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 my $PNMCROP = '/usr/bin/pnmcrop -verbose ';
275 my $PNMCROPOPT = '';
276 $PNMCROPOPT = '-sides';
277 # $PNMCROPOPT = '-white';
278 # $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 # GIF support
285 my $PPMTOGIF = '/usr/bin/ppmtogif';
286 # PNG support
287 my $PNMTOPNG = '/usr/bin/pnmtopng';
288 # 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 my $trans_color = '#ffffff';
301
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 my $croparg = '';
1115 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 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 &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 if($type && ($height - $height2) < 3 ) {
1133 # 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

  ViewVC Help
Powered by ViewVC 1.1.22