#! /bin/sh # pstoany --- convert PostScript images to gif, jpeg, etc. # Copyright (C) 1994, 1995, 1998 Noah S. Friedman # Author: Noah Friedman # Created: 1994-10-17 # $Id: pstoany,v 1.8 1998/05/19 15:58:18 friedman Exp $ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, you can either send email to this # program's maintainer or write to: The Free Software Foundation, # Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. # Commentary: # This program uses Ghostscript to convert postscript files to gif, jpeg, # png, etc. Because of patent problems, modern versions of Ghostscript do # not have support for writing gif-format files directly. If support is # missing, ghostscript is used to convert the image to ppm format and the # external `ppmtogif' program is used to finish the conversion. The # ppmtogif program can be found in the `pbmplus' or `netpbm' packages. # Code: # This string is expanded by RCS automatically when this file is checked out. rcs_revision='$Revision: 1.8 $' # Name by which this script was invoked. progname=`echo "$0" | sed -e 's/[^\/]*\///g'` # To prevent hairy quoting and escaping later. bq='`' eq="'" # normal font resolution in dots per inch defres=72 xres= yres= # Magnification step xmag=1 ymag=1 # Image size xsize= ysize= ppmtogifp= format=gif8 aliasbits=0 GS="${GS-gs}" revision=`set fnord $rcs_revision; echo $3` usage="Usage: $progname {options} file1.ps {file2.ps {...}} (Version $revision) Diagnostic options: -D, --debug Turn on shell debugging ($bq${bq}set -x$eq$eq). Implies --verbose. -h, --help You're looking at it. -q, --quiet Do not report progress during conversion. -v, --verbose Report progress. This is the default. -V, --version Show version number of this program & exit. File options: -F, --force Overwrite existing .gif or other intermediary format files without notification. By default, this program refuses to overwrite any existing files. -f, --format FMT Specify FMT as the ${bq}device$eq (i.e. output format) for Ghostscript. Default is $bq$format$eq. -o, --output-file FILE Use FILE as the output file name. This is only appropriate when used with a single input file to convert. Image scaling and dithering options: -a, --antialias BITS Use BITS bits of alpha antialiasing. Valid values are 1 (no aliasing), 2, or 4. Argument is optional and defaults to 4. See ${bq}language.txt$eq in ghostscript sources. -m, --magnify STEP Magnify x and y sizes by a factor of STEP. Default is xmag=$xmag, ymag=$ymag -x, --x-magnification XSTEP Like $bq--magnify$eq, but only change x factor. -y, --y-magnification YSTEP Like $bq--magnify$eq, but only change y factor. -s, --size WxH Resize image to W by H pixels. To preserve aspect ratio automatically, use $bq--x-size$eq or $bq--y-size$eq to specify the size of just one axis. -X, --x-size XSIZE Resize image to XSIZE pixels horizontal. Aspect ratio is preserved unless $bq--y-size$eq is also specified. -Y, --y-size YSIZE Resize image to YSIZE pixels veritcal. Aspect ratio is preserved unless $bq--x-size$eq is also specified. -r, --resolution RES Input image resolution for both x and y coordinates, in dots per inch. You probably never need to adjust this manually. Default is xres=$defres, yres=$defres --x-resolution XRES Like $bq--resolution$eq, but only change x value. --y-resolution YRES Like $bq--resolution$eq, but only change y value. " # Usage: eval "$getopt"; value=$optarg # or optarg_optional=t; eval "$getopt"; value=$optarg # # This function automatically shifts the positional args as appropriate. # The argument to an option is optional if the variable `optarg_optional' # is non-empty. Otherwise, the argument is required and getopt will cause # the program to exit on an error. optarg_optional is reset to be empty # after every call to getopt. The argument (if any) is stored in the # variable `optarg'. # # Long option syntax is `--foo=bar' or `--foo bar'. # For optional args, you must use the `--foo=bar' long option syntax # if the argument starts with `-', otherwise the argument will be ignored # and treated as the next option. # # Note: because of broken bourne shells, using --foo=bar syntax can # actually screw the quoting of args that end with trailing newlines. # Specifically, most shells strip trailing newlines from substituted # output, regardless of quoting. getopt=' { optarg= case "$1" in --*=* ) optarg=`echo "$1" | sed -e "1s/^[^=]*=//"` ; shift ;; -* ) case "${2+set}:$optarg_optional" in set: ) optarg="$2" ; shift ; shift ;; set:?* ) case "$2" in -* ) shift ;; * ) optarg="$2"; shift; shift ;; esac ;; : ) option="$1" case "$option" in --*=* ) option=`echo "$option" | sed -e "1s/=.*//;q"` ;; esac echo "$progname: option $bq$option$eq requires argument." 1>&2 echo "$progname: use $bq--help$eq to list option syntax." 1>&2 exit 1 ;; * ) shift ;; esac ;; esac optarg_optional= }' # Initialize variables. # Don't use `unset' since old bourne shells don't have this command. # Instead, assign them an empty value. debug= force= verbose=t gs_quiet= outfile= # Parse command line arguments. # Make sure that all wildcarded options are long enough to be unambiguous. # It's a good idea to document the full long option name in each case. # Long options which take arguments will need a `*' appended to the # canonical name to match the value appended after the `=' character. while : ; do case $# in 0) break ;; esac case "$1" in -a | --antialias* | --a* ) optarg_optional=t eval "$getopt" aliasbits="$optarg" case "$aliasbits" in '' ) aliasbits=4 ;; esac ;; -D | --debug | --d* ) debug=t verbose=t gs_quiet= shift ;; -F | --force | --forc ) force=t shift ;; -f | --format* | --form* ) eval "$getopt" format="$optarg" ;; -h | --help | --h* ) echo "$usage" 1>&2 exit 0 ;; -m | --magnification* | --magnify* | --magstep* | --m* ) eval "$getopt" xmag="$optarg" ymag="$optarg" ;; -o | --output-file* | --o* ) eval "$getopt" outfile="$optarg" ;; -q | --quiet | --q* ) verbose= gs_quiet=-q shift ;; -r | --resolution* | --re* ) eval "$getopt" xres="$optarg" yres="$optarg" ;; -s | --size* | --s* ) eval "$getopt" case "$optarg" in *x* ) xsize=`echo "$optarg" | sed 's/x.*//'` ysize=`echo "$optarg" | sed 's/.*x//'` ;; * ) xsize="$optarg" ysize="$optarg" ;; esac ;; -V | --version | --vers* ) echo "$progname version $revision" exit 0 ;; -v | --verbose | --verb* ) verbose=t gs_quiet= shift ;; --x-resolution* | --x-r* ) eval "$getopt" xres="$optarg" ;; --y-resolution* | --y-r* ) eval "$getopt" yres="$optarg" ;; -X | --x-size* | --x-s* ) eval "$getopt" xsize="$optarg" ;; -Y | --y-size* | --y-s* ) eval "$getopt" ysize="$optarg" ;; -x | --x-magnification* | --x-magnify* | --x-magstep* | --x-m* ) eval "$getopt" xmag="$optarg" ;; -y | --y-magnification* | --y-magnify* | --y-magstep* | --y-m* ) eval "$getopt" ymag="$optarg" ;; -- ) # Stop option processing shift break ;; -? | --* ) case "$1" in --*=* ) arg=`echo "$1" | sed -e 's/=.*//'` ;; * ) arg="$1" ;; esac exec 1>&2 echo "$progname: unknown or ambiguous option $bq$arg$eq" echo "$progname: Use $bq--help$eq for a list of options." exit 1 ;; -??* ) # Split grouped single options into separate args and try again optarg="$1" shift set fnord `echo "x$optarg" | sed -e 's/^x-//;s/\(.\)/-\1 /g'` ${1+"$@"} shift ;; * ) break ;; esac done case "$debug" in t ) set -x ;; esac case "$verbose" in '' ) exec 1> /dev/null ;; esac case "$#:$outfile" in [01]:* ) : ;; *:?* ) echo "$progname: Can't specify output file name when multiple input files given." 1>&2 exit 1 ;; esac # Build a list of supported output formats. gs_devices_raw=`$GS -h | sed -ne ' /^Available devices:/{ :l n /^[^ ]/q p b l }'` gs_devices=" "`echo $gs_devices_raw`" " # Determine whether requested output format is supported. case "$gs_devices" in *" $format "* ) : ;; * ) case "$format" in jpg ) format=jpeg ;; # If desired image format is gif, see if ppmraw or ppm (in that order) # is supported by gs, and use that instead. gif | gif8 | gifmono ) case "$gs_devices" in *" ppmraw "* ) ppmtogifp=t; format=ppmraw ;; *" ppm "* ) ppmtogifp=t; format=ppm ;; * ) echo "$progname: $GS does not have gif or ppm drivers installed." 1>&2 ;; esac ;; esac # Try again to see if modified format name is supported as a gs device. case "$gs_devices" in *" $format "* ) : ;; * ) exec 1>&2 echo "$progname: $format: unsupported format." echo "Supported formats include:" echo "$gs_devices_raw" exit 1 ;; esac ;; esac file_exists_hint_given_p= for file in ${1+"$@"}; do case "$file" in - ) tmpfile="/tmp/$progname$$.ps" trap 'rm -f "$tmpfile"' 0 1 2 3 15 cat > "$tmpfile" file="$tmpfile" ;; esac case "$outfile" in '' ) outputfile= ;; * ) outputfile="$outfile" ;; esac basename=`echo "$file" \ | sed -e 's/\/*$// s/.*\/// s/\..*//'` case "$force" in t ) : ;; * ) set fnord case "$ppmtogifp" in t ) set ${1+"$@"} `ls -1d "$basename"*.gif "" 2> /dev/null` ;; esac set ${1+"$@"} `ls -1d "$basename"*".$format" "$outputfile" 2> /dev/null` shift case $# in 0 ) : ;; * ) echo "$progname: skipping conversion of $bq$file$eq" 1>&2 case "$file_exists_hint_given_p" in t ) : ;; * ) file_exists_hint_given_p=t sed -e "s/^/$progname: /" 1>&2 <<__EOF__ The following files in the current directory may get overwritten as a result of running this program. If desired, rename or remove them, or use the $bq-f$eq ($bq--force$eq) option. __EOF__ ;; esac echo ls -lsd ${1+"$@"} 2> /dev/null echo continue ;; esac ;; esac echo "$progname: converting $file" # Get the bounding box coordinates. # If the first bounding box instructions say "(atend)", then search to # the end of the file for the last occurrence of a bounding box. set fnord `sed -ne ' /^%%BoundingBox:/{ /(atend)/!{ p q } b l } d :l /^%%BoundingBox:/h $b e n b l :e x p q ' "$file"` bcinit='scale=4 ' case $# in 1 ) echo "$progname: warning: no BoundingBox found in $bq$arg$eq" 1>&2 # Guess. Assume image area fits in a 8.5x11 sheet. llx=0 lly=0 urx=`echo "$bcinit ($defres * 8.5)" | bc` ury=`echo "$bcinit ($defres * 11)" | bc` echo "$progname: warning: guessing %%BoundingBox $llx $lly $urx $ury" 1>&2 ;; * ) # Args hopefully now: fnord %%BoundingBox llx lly urx ury llx=$3; urx=$5 lly=$4; ury=$6 ;; esac case "$xsize:$ysize" in : ) # Dividing by 1 when scale=0 insures bc result is an integer xsize=`echo "($urx - $llx) * $xmag / 1" | bc` ysize=`echo "($ury - $lly) * $ymag / 1" | bc` ;; [0-9]*: ) xmag=`echo "$bcinit $xsize / ($urx - $llx)" | bc` ymag=$xmag ysize=`echo "($ury - $lly) * $ymag / 1" | bc` ;; :[0-9]* ) ymag=`echo "$bcinit $ysize / ($ury - $lly)" | bc` xmag=$ymag xsize=`echo "($urx - $llx) * $ymag / 1" | bc` ;; ?*:?* ) xmag=`echo "$bcinit $xsize / ($urx - $llx)" | bc` ymag=`echo "$bcinit $ysize / ($ury - $lly)" | bc` ;; esac case "$xres" in '' ) xres=`echo "$bcinit ($defres * $xmag)" | bc` ;; esac case "$yres" in '' ) yres=`echo "$bcinit ($defres * $ymag)" | bc` ;; esac case "$aliasbits" in 0 ) alias= ;; * ) alias="-dGraphicsAlphaBits=$aliasbits -dTextAlphaBits=$aliasbits" ;; esac set fnord "$GS" -sDEVICE=$format \ -sOutputFile="$basename%03d.$format" \ -g${xsize}x${ysize} \ -r${xres}x${yres} \ $alias $gs_quiet - "$file" shift echo $progname: ${1+"$@"} echo "$llx neg $lly neg translate" | ${1+"$@"} exitstat=$? case $exitstat in 0 ) : ;; * ) exit $exitstat ;; esac case "$ppmtogifp" in t ) for f in `ls -1d "$basename"*".$format" 2>/dev/null` ; do g=`echo "$f" | sed -e "s/\.$format\$/.gif/"` echo "$progname: running ppmtogif on $bq$f$eq" ppmtogif "$f" > "$g" \ && rm -f "$f" \ && echo "$progname: created $g" done format=gif ;; esac set fnord `ls -1d "$basename"[0-9]*".$format" 2> /dev/null` shift case $# in 1 ) case "$outputfile" in '' ) newname=`echo "$1" | sed -e "s/001\.$format\$/.$format/"` ;; * ) newname=$outputfile ;; esac echo $progname: mv "$1" "$newname" mv "$1" "$newname" ;; esac done # pstoany ends here