summaryrefslogtreecommitdiff
path: root/support/psfixbb
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/psfixbb
Initial commit
Diffstat (limited to 'support/psfixbb')
-rwxr-xr-xsupport/psfixbb/psfixbb426
-rw-r--r--support/psfixbb/psfixbb.html125
2 files changed, 551 insertions, 0 deletions
diff --git a/support/psfixbb/psfixbb b/support/psfixbb/psfixbb
new file mode 100755
index 0000000000..57432962f9
--- /dev/null
+++ b/support/psfixbb/psfixbb
@@ -0,0 +1,426 @@
+#!/usr/local/bin/perl
+#
+# psfixbb - Program to create or adjust BoundingBox in postscript(R) files.
+# Copyright (C) 1997 Carsten Dominik
+
+# Version: 3.0
+
+# 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.
+
+# To obtain a copy of the GNU General Public License write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+# TODO
+# ====
+# - larger files
+# - avoid rotation
+
+# Libraries
+# ---------
+use Getopt::Std;
+use File::Copy;
+
+# Who am I anyway
+($me = $0) =~ s/.*\///;
+
+# Catch a few signals
+# -------------------
+$SIG{INT} = 'handler';
+$SIG{QUIT} = 'handler';
+
+# External programs needed
+# ------------------------
+$gs = "gs";
+$tmpdir = ".";
+$tmpppmfile = "$tmpdir/pstoeps$$.ppm";
+$tmppsfile = "$tmpdir/pstoeps$$.ps";
+$gsargs = "-q -sDEVICE=ppmraw -r72 -dNOPAUSE -dSAFER -sOutputFile=$tmpppmfile -f";
+$pnmfile = "pnmfile";
+$pnmcrop = "pnmcrop";
+
+# Some constants
+# --------------
+$bbfmt = "$me: %-40s (%s)\n";
+
+# Default Parameters
+# ------------------
+# It is sometimes useful to make the BoundingBox a little larger than the
+# exact limit. Here we set the default (in Postscript points).
+$extra = 0;
+# Which line is to become the bounding box comment, if there is none?
+# Should be larger than 1, less than the typical header size.
+$bbline = 2;
+
+# Check for command line options
+$opt_status = getopts('ceflrx:o:');
+
+if (!$opt_status || !@ARGV) {
+ print STDERR <<"EOF";
+usage: $me [-ceflr] [-x N] [-o outfile] filename [filename...]
+EOF
+ exit;
+}
+
+$extra = 0+$opt_x if (defined($opt_x) && $opt_x >= 0);
+$opt_c = 0 if $opt_l;
+$pipe = $opt_c || $opt_o;
+
+# Get the files from the command line
+@files = @ARGV;
+if ($pipe && @files>1) {
+ warn "$me: processing only $files[0] because of -c or -o switch\n";
+ $#files = 0;
+}
+
+FILE:
+while (@files) {
+ # Get the file name.
+ $file = shift @files;
+ if ($pipe) {
+ $infile = $file;
+ $outfile = $opt_o || '-';
+ } else {
+ $infile = $file;
+ $outfile = "$tmppsfile";
+ }
+
+ &cont("No such file $infile",1) unless $infile ne "" && -e $infile;
+
+ # Open the file and read a chunk of it.
+ open OLD,$infile or die "$me: Can't open file $infile: $!\n";
+ sysread OLD,$header,1024; #
+ unless (substr($header,0,2) eq "%!") {
+ &cont("$infile is not a Postscript file",1);
+ }
+
+ print STDERR "$me: Processing $file\n" unless $opt_l;
+
+ # Should we rotate the file before computing bounding box?
+ if ($opt_r) {
+ # print the prefix to $tmppsfile
+ write_landscape_prefix ($tmppsfile);
+
+ # add the $infile
+ $cmd = "cat $infile >> $tmppsfile";
+ system ($cmd) == 0 or
+ &cont("Couldn't append $infile to temporary file $tmppsfile for rotation.");
+
+ # the actual gs command now operates on $tmppsfile
+ $cmd = "$gs $gsargs $tmppsfile -c showpage quit";
+ } else {
+ # normally, just run gs on $infile:
+ $cmd = "$gs $gsargs $infile -c showpage quit";
+ }
+
+ # Run gs to convert to a portable bitmap.
+ system($cmd) == 0 or
+ &cont("Ghostscript failed on file $infile: $?");
+
+ # Run pnmfile to get size information.
+ $pnmfile_out = `$pnmfile $tmpppmfile`;
+ &cont("pnmfile failed.") if $? && $opt_s;
+ &cont("pnmfile failed. Try running psfixbb with -s switch") if $?;
+ ($xsize,$ysize) = ($pnmfile_out =~ /(\d+)\s+by\s+(\d+)/);
+ &cont("pnmfile failed to give the image size")
+ unless defined($xsize) && defined($ysize);
+
+ # Run pnmcrop to get information about empty space.
+ # We need to capture stderr for that. It requires a shell, so this may
+ # fail on systems which don't have one.
+ $cmd = "$pnmcrop 3>&1 2>&3 1>/dev/null $tmpppmfile";
+ $cropinfo = `$cmd`;
+ &cont("pnmcrop failed") if $?;
+ $top = $bottom = $left = $right = 0;
+ foreach (split(/\n/,$cropinfo)) {
+ $top = $1 if (/\brows\b/ && /\btop/ && /\bcropping\s+(\d+)/);
+ $bottom = $1 if (/\brows\b/ && /\bbottom/ && /\bcropping\s+(\d+)/);
+ $left = $1 if (/\bcols\b/ && /\bleft/ && /\bcropping\s+(\d+)/);
+ $right = $1 if (/\bcols\b/ && /\bright/ && /\bcropping\s+(\d+)/);
+ }
+
+ # Remove the temporary files.
+ unlink $tmpppmfile;
+ unlink $tmppsfile if $opt_r;
+
+ # Define the new BoundingBox.
+ if ($opt_r) {
+ # landscape
+ $bb{x1} = $bottom-$extra;
+ $bb{x2} = $ysize-$top+$extra;
+ $bb{y1} = $right-$extra;
+ $bb{y2} = $xsize-$left+$extra;
+ } else {
+ # portrait
+ $bb{x1} = $left-$extra;
+ $bb{x2} = $xsize-$right+$extra;
+ $bb{y1} = $bottom-$extra;
+ $bb{y2} = $ysize-$top+$extra;
+ }
+ $bb = sprintf("%%%%BoundingBox: %d %d %d %d",
+ $bb{x1},$bb{y1},$bb{x2},$bb{y2});
+
+ # See if the file already has a bounding box
+ undef $oldbb;
+ if ($header =~
+ /[\n\r]%%BoundingBox:[ \t]+(\d+)[ \t]+(\d+)[ \t]+(\d+)[ \t]+(\d+)/) {
+ $oldbb = substr($&,1);
+ @oldbb{('x1','y1','x2','y2')} = ($1,$2,$3,$4);
+ if ($bb{x1} == $oldbb{x1} && $bb{x2} == $oldbb{x2} &&
+ $bb{y1} == $oldbb{y1} && $bb{y2} == $oldbb{y2}) {
+ printf STDERR $bbfmt,$oldbb,"unchanged" unless $opt_l;
+ unless ($pipe || $opt_f || $opt_e) {
+ # We are done
+ &cleanup;
+ print "$file: $bb\r\n" if $opt_l;
+ next FILE;
+ }
+ } else {
+ printf STDERR $bbfmt,$bb,"adjusted" unless $opt_l;
+ }
+
+ # Change BB
+ $header = "$`\n$bb$'";
+ } else {
+ # Insert a BoundingBox as line number $bbline
+ @headerlines = split(/[\n\r]+/,$header);
+ &cont("Less than $bbline lines in the header. Can't insert.")
+ if @headerlines < $bbline;
+ splice @headerlines,$bbline-1,0,$bb;
+ $header = join "\r\n",@headerlines;
+ printf STDERR $bbfmt,$bb,"added" unless $opt_l;
+ }
+
+ if ($opt_l) {
+ print "$file: $bb\n";
+ next FILE;
+ }
+
+ # Write a new version of the file
+ open NEW,">$outfile" or &cont("Can't write to $outfile: $!");
+ unless (length($header) == syswrite NEW,$header,length($header)) {
+ &cont("Failed to write new header: $!");
+ }
+ copy(\*OLD,\*NEW);
+ &cont("Failed to copy file: $!") if $!;
+ close OLD;
+ close NEW;
+
+ # If we don't have to change the file, we are done
+ next FILE if $pipe;
+
+ # Rename the new file to the old file name.
+ # But we first check if everything went ok.
+ $oldsize = (stat $infile)[7];
+ $newsize = (stat $outfile)[7];
+ &cont("File size change ($oldsize to $newsize) is suspicious")
+ if ($oldsize <=0 || $newsize<=0 || abs($oldsize-$newsize)>50);
+
+ # We can safely remove the old copy
+ rename $infile,"$infile.bak"
+ or &cont("Can't rename $infile to $infile.bak: $!");
+ if ($opt_e && $infile =~ /\.ps$/) {
+ ($newfile = $infile) =~ s/\.ps$/.eps/;
+ if (-e $newfile && !$opt_f) {
+ print STDERR "$me: Cannot change filename to $newfile\n";
+ $newfile = $infile;
+ } else {
+ print STDERR "$me: Changing filename to $newfile\n";
+ }
+ } else {
+ $newfile = $infile;
+ }
+ rename $outfile,$newfile
+ or &cont("Cannot rename $outfile to $newfile: $!");
+ unlink "$infile.bak"
+ or &cont("Can't remove $infile.bak: $!");
+}
+
+sub cont {
+ # Move on to next file, with an error message about current
+ print STDERR "$me: $_[0]\n";
+ print STDERR "$me: $file not changed\n" unless $_[1] || $opt_l;
+ &cleanup;
+ next FILE;
+}
+
+sub handler {
+ # Signal handler, doing cleanup before exiting
+ local($sig) = @_;
+ print STDERR "\n$me: Caught a SIG$sig\n";
+ &cleanup;
+ exit(1);
+}
+
+sub cleanup {
+ # Remove the temporary files
+ unlink $tmpppmfile if -e $tmpppmfile;
+ unlink $tmppsfile if -e $tmppsfile;
+}
+
+sub write_landscape_prefix {
+ # write the landscape.ps file as the header of the rotated file
+ my $file = $_[0];
+
+ open (NEW, ">$file") or die ("could not open $file for temp file creation\n");
+
+ print NEW <<'EOF';
+%!
+% landscape.ps
+% This file can be prepended to most PostScript files to force
+% rotation of all pages to \"landscape\" mode.
+%
+% There are (at least) four possible ways to reasonably position a
+% page after rotation. Any of the four old corners (llx,lly e.g.)
+% can be moved to match the corresonding new corner.
+% By uncommmenting the appropriate line below (i.e., remove the
+% leading '%'), any such positioning can be chosen for positive or
+% negative rotation. The comments at the end of each \"rotate\" line
+% indicate the ORIGINAL corner to be aligned. For example, as given
+% below, the lower left hand corner is aligned. When viewed, this
+% corner will have moved to the urx,lly corner.
+%
+% James E. Burns, 3/8/93, burns\@nova.bellcore.com
+% Revised 11/9/93 for multi-page files
+%
+
+4 dict begin
+ gsave clippath pathbbox grestore
+ /ury exch def /urx exch def /lly exch def /llx exch def
+ [
+ % llx neg ury neg 90 % llx,ury
+ llx neg llx urx sub lly sub 90 % llx,lly
+ % ury lly sub urx sub ury neg 90 % urx,ury
+ % ury lly sub urx sub llx urx sub lly sub 90 % urx,lly
+ % urx neg lly neg -90 % urx,lly
+ % urx neg urx llx sub ury sub -90 % urx,ury
+ % llx lly add ury sub urx llx sub ury sub -90 % llx,ury
+ % llx lly add ury sub lly neg -90 % llx,lly
+ /rotate load /translate load ]
+end
+
+cvx dup exec
+/showpage [ /showpage load 3 index /exec load ] cvx def
+% End of landscape.ps
+
+EOF
+ close NEW;
+}
+
+__END__
+
+=head1 NAME
+
+B<psfixbb> - fix the BoundingBox in a Postscript file.
+
+=head1 SYNOPSIS
+
+C<psfixbb [-ceflr] [-x N] [-o outfile] filename [filename...]>
+
+=head1 DESCRIPTION
+
+B<psfixbb> is a tool to create a BoundingBox in Postscript(R) files
+which do not have one, or to fix an incorrect existing BoundingBox.
+
+Many applications write Postscript(R) files or Encapsulated
+Postscript(R) files with no or incorrect BoundingBox information.
+I.e. the box which contains the image or text on the page is often
+smaller than specified in the %%BoundingBox comment in the file. This
+can be annoying when importing the file into other documents.
+B<psfixbb> computes the size of the used part of a page and inserts
+the information into the file.
+
+B<psfixbb> uses ghostscript (B<gs>) to transform the page into a
+portable bit map (pbm), then the B<pnmfile> and B<pnmcrop> utilities
+to determine the size of the non-white part of the page. These three
+programs need to be installed for B<psfixbb> to work.
+
+Because B<psfixbb> really looks at the dark pixels of the page, it
+works even if the application which produced the Postscript file has
+painted the backgroud of the whole page white. Most other
+boundingbox-fixing utilities fail in such cases.
+
+For landscape files you need to run psfixbb with the B<-r> switch.
+
+=head1 OPTIONS
+
+=over 5
+
+=item B<-c>
+
+Send a new file with the correct BoundingBox to stdout. This will
+leave the original file untouched. Only the first filename on the
+command line will be processed.
+
+=item B<-e>
+
+When the filename extension is F<.ps>, change it to F<.eps> (unless
+the resulting file name corresponds to an existing file). See also
+the B<-f> flag.
+
+=item B<-f>
+
+When specified together with the B<-e> flag, existing F<.eps> files
+are overwritten when necessary.
+
+=item B<-l>
+
+List computed BoundingBoxes, do not change any files.
+
+=item B<-o outfile>
+
+Output to file OUTFILE.
+
+=item B<-r>
+
+Rotate the postscript file before attempting to compute the bounding
+box. Needed for landscape files.
+
+=item B<-x N>
+
+The BoundingBox created can be made larger than the actual image by N
+postscript points with this option.
+
+=back
+
+=head1 AUTHOR
+
+Carsten Dominik <dominik@strw.LeidenUniv.nl>
+
+Holger Karl <karl@informatik.hu-berlin.de>
+
+This program is free software. See the source file for the full
+copyright notice.
+
+=head1 FILES
+
+For the file F<file.ps>, F<file.ps%> is used temporarily to
+hold a new version of the file with changed BoundingBox.
+
+=head1 SEE ALSO
+
+gs(1), pnmfile(1), pnmcrop(1), pnm(5)
+
+=head1 BUGS
+
+B<psfixbb> does not work for images larger than a normal page.
+
+The file F<file.ps%> is overwritten without checking. For multipage
+documents, only the first page determines the value of the
+BoundingBox.
+
+=head1 ACKNOWLEDGMENTS
+
+Thanks to Georg Drenkhahn for pointing out how to enforce a showpage
+command in gs.
+
+=cut
diff --git a/support/psfixbb/psfixbb.html b/support/psfixbb/psfixbb.html
new file mode 100644
index 0000000000..8c8c3a751e
--- /dev/null
+++ b/support/psfixbb/psfixbb.html
@@ -0,0 +1,125 @@
+<HTML>
+<HEAD>
+<TITLE>B<psfixbb> - fix the BoundingBox in a Postscript file.</TITLE>
+<LINK REV="made" HREF="mailto:prospector@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<A NAME="__index__"></A>
+<!-- INDEX BEGIN -->
+
+<UL>
+
+ <LI><A HREF="#name">NAME</A></LI>
+ <LI><A HREF="#synopsis">SYNOPSIS</A></LI>
+ <LI><A HREF="#description">DESCRIPTION</A></LI>
+ <LI><A HREF="#options">OPTIONS</A></LI>
+ <LI><A HREF="#author">AUTHOR</A></LI>
+ <LI><A HREF="#files">FILES</A></LI>
+ <LI><A HREF="#see also">SEE ALSO</A></LI>
+ <LI><A HREF="#bugs">BUGS</A></LI>
+ <LI><A HREF="#acknowledgments">ACKNOWLEDGMENTS</A></LI>
+</UL>
+<!-- INDEX END -->
+
+<HR>
+<P>
+<H1><A NAME="name">NAME</A></H1>
+<P><STRONG>psfixbb</STRONG> - fix the BoundingBox in a Postscript file.</P>
+<P>
+<HR>
+<H1><A NAME="synopsis">SYNOPSIS</A></H1>
+<P><CODE>psfixbb [-ceflr] [-x N] [-o outfile] filename [filename...]</CODE></P>
+<P>
+<HR>
+<H1><A NAME="description">DESCRIPTION</A></H1>
+<P><STRONG>psfixbb</STRONG> is a tool to create a BoundingBox in <CODE>Postscript(R)</CODE> files
+which do not have one, or to fix an incorrect existing BoundingBox.</P>
+<P>Many applications write <CODE>Postscript(R)</CODE> files or Encapsulated
+<CODE>Postscript(R)</CODE> files with no or incorrect BoundingBox information.
+I.e. the box which contains the image or text on the page is often
+smaller than specified in the %%BoundingBox comment in the file. This
+can be annoying when importing the file into other documents.
+<STRONG>psfixbb</STRONG> computes the size of the used part of a page and inserts
+the information into the file.</P>
+<P><STRONG>psfixbb</STRONG> uses ghostscript (<STRONG>gs</STRONG>) to transform the page into a
+portable bit map (pbm), then the <STRONG>pnmfile</STRONG> and <STRONG>pnmcrop</STRONG> utilities
+to determine the size of the non-white part of the page. These three
+programs need to be installed for <STRONG>psfixbb</STRONG> to work.</P>
+<P>Because <STRONG>psfixbb</STRONG> really looks at the dark pixels of the page, it
+works even if the application which produced the Postscript file has
+painted the backgroud of the whole page white. Most other
+boundingbox-fixing utilities fail in such cases.</P>
+<P>For landscape files you need to run psfixbb with the <STRONG>-r</STRONG> switch.</P>
+<P>
+<HR>
+<H1><A NAME="options">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item_%2Dc"><STRONG>-c</STRONG></A></STRONG><BR>
+<DD>
+Send a new file with the correct BoundingBox to stdout. This will
+leave the original file untouched. Only the first filename on the
+command line will be processed.
+<P></P>
+<DT><STRONG><A NAME="item_%2De"><STRONG>-e</STRONG></A></STRONG><BR>
+<DD>
+When the filename extension is <EM>.ps</EM>, change it to <EM>.eps</EM> (unless
+the resulting file name corresponds to an existing file). See also
+the <STRONG>-f</STRONG> flag.
+<P></P>
+<DT><STRONG><A NAME="item_%2Df"><STRONG>-f</STRONG></A></STRONG><BR>
+<DD>
+When specified together with the <STRONG>-e</STRONG> flag, existing <EM>.eps</EM> files
+are overwritten when necessary.
+<P></P>
+<DT><STRONG><A NAME="item_%2Dl"><STRONG>-l</STRONG></A></STRONG><BR>
+<DD>
+List computed BoundingBoxes, do not change any files.
+<P></P>
+<DT><STRONG><A NAME="item_%2Do_outfile"><STRONG>-o outfile</STRONG></A></STRONG><BR>
+<DD>
+Output to file OUTFILE.
+<P></P>
+<DT><STRONG><A NAME="item_%2Dr"><STRONG>-r</STRONG></A></STRONG><BR>
+<DD>
+Rotate the postscript file before attempting to compute the bounding
+box. Needed for landscape files.
+<P></P>
+<DT><STRONG><A NAME="item_%2Dx_N"><STRONG>-x N</STRONG></A></STRONG><BR>
+<DD>
+The BoundingBox created can be made larger than the actual image by N
+postscript points with this option.
+<P></P></DL>
+<P>
+<HR>
+<H1><A NAME="author">AUTHOR</A></H1>
+<P>Carsten Dominik &lt;<A HREF="mailto:dominik@strw.LeidenUniv.nl">dominik@strw.LeidenUniv.nl</A>&gt;</P>
+<P>Holger Karl &lt;<A HREF="mailto:karl@informatik.hu-berlin.de">karl@informatik.hu-berlin.de</A>&gt;</P>
+<P>This program is free software. See the source file for the full
+copyright notice.</P>
+<P>
+<HR>
+<H1><A NAME="files">FILES</A></H1>
+<P>For the file <EM>file.ps</EM>, <EM>file.ps%</EM> is used temporarily to
+hold a new version of the file with changed BoundingBox.</P>
+<P>
+<HR>
+<H1><A NAME="see also">SEE ALSO</A></H1>
+<P>gs(1), pnmfile(1), pnmcrop(1), <CODE>pnm(5)</CODE></P>
+<P>
+<HR>
+<H1><A NAME="bugs">BUGS</A></H1>
+<P><STRONG>psfixbb</STRONG> does not work for images larger than a normal page.</P>
+<P>The file <EM>file.ps%</EM> is overwritten without checking. For multipage
+documents, only the first page determines the value of the
+BoundingBox.</P>
+<P>
+<HR>
+<H1><A NAME="acknowledgments">ACKNOWLEDGMENTS</A></H1>
+<P>Thanks to Georg Drenkhahn for pointing out how to enforce a showpage
+command in gs.</P>
+
+</BODY>
+
+</HTML>