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