I have myfile.ps
with a vector image included.
But when I run
ps2pdf myfile.ps
it seems that the output page size is A4: the vecto
Based on @Kurt Pfeifle's answer I wrote this Perl script to do the task:
#! /usr/bin/env perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
use List::Util qw(all);
sub ps2pdf;
sub get_ps_headers;
sub get_media_size;
sub main;
# Run the program
main();
# Function: main
#
# Program's entry point.
#
sub main {
for (@ARGV) {
# check input file
if(not -r) {
print "WARN: Cannot read input file: $_\n";
next;
}
# build PDF file name
my $pdf = $_;
$pdf =~ s/(\.e?ps)?$/.pdf/i;
ps2pdf($_, $pdf);
}
}
# Function: ps2pdf
#
# Converts a PostScript file to PDF format using GhostScript,
# keeping the medium size.
#
# Params:
#
# $ps_file - (string) Input [E]PS file name
# $pdf_file - (string) Output PDF file name
#
sub ps2pdf {
my ($ps_file, $pdf_file) = @_;
my $cmd = "gs -q -sDEVICE=pdfwrite -dPDFFitPage ";
# try to find the media size
my ($width, $height) = get_media_size(get_ps_header($ps_file));
# keep media size
if(defined $height) {
$cmd .= "-g${width}x${height} ";
}
# set input/output
$cmd .= "-o $pdf_file $ps_file";
print "Running: $cmd\n";
system($cmd);
}
# Function: get_media_size
#
# Computes the size of a PostScript document in pixels,
# from the headers in the PS file.
#
# Params:
#
# $hdr - (hash ref) Parsed PS header values
#
# Returns:
#
# On success: Two-element array holding the document's width and height
# On failure: undef
#
sub get_media_size {
my ($hdr) = @_;
# we need the DocumentMedia header
return undef if not defined $hdr->{DocumentMedia};
# look for valid values
my @values = split(/\s+/, $hdr->{DocumentMedia});
return undef if scalar @values < 3;
my ($width, $height) = @values[1, 2];
return undef if not all { looks_like_number($_) } ($width, $height);
# Ghostscript uses a default resolution of 720 pixels/inch,
# there are 72 PostScript points/inch.
return ($width*10, $height*10);
}
# Function: get_ps_header
#
# Parses a PostScript file looking for headers.
#
# Params:
#
# $ps_file - (string) Path of the input file
#
# Returns:
#
# (hash ref) - As expected, keys are header names,
# values are corresponding header values. A special key
# named `version' is included for headers of the type
# `PS-Adobe-3.0'
#
sub get_ps_header {
my ($ps_file) = @_;
my %head;
open my $fh, "<$ps_file" or die "Failed to open $ps_file\n";
while(<$fh>) {
# look for end of header
last if /^%%EndComments\b/;
# look for PS version
if(/^%!(\w+)/) {
$head{version} = $1;
}
# look for any other field
# Ex: %%BoundingBox: 0 0 1008 612
elsif(/^%%(\w+)\s*:\s*(.*\S)/) {
$head{$1} = $2;
}
# discard regular comments and blank lines
elsif(/^\s*(%.*)?$/) {
next;
}
# any other thing will finish the header
else {
last;
}
}
return \%head;
}
I doubt your quoted 2 lines are really inside the PS file as quoted... Aren't they preceeded by %
comment characters?
If they weren't preceeded by such characters, no PS interpreter would work, because they are no known PostScript operators.
If they are preceeded by such characters, the PS interpreter would simply ignore them, because... they are comments only! :-)
If you want to convert this PS file to PDF, it is better to run Ghostscript directly (ps2pdf
is only a thin shell script wrapper around a Ghostscript command anyway):
gs -o myfile.pdf \
-sDEVICE=pdfwrite \
-g5775x6207 \
-dPDFFitPage \
myfile.ps
Explanation:
-g...
gives the medium size in pixels.595x842pt
(PostScript points).595x842pt == 5950x8420px
.8.02x8.62Inches ≈≈ 5775x6207px
.I am not allowed to comment, but I must warn everyone that all the current answers are vulnerable to malicious postscript files.
Using gs
like this is VERY dangerous. ps2pdf
internally uses the -dSAFER
option which would, for example, prevent an untrusted postscript file from encrypting your files and rendering a pdf that demands a ransom payment from you for the decryption key! ALWAYS use -dSAFER
!
While -o outputFile.pdf
is nice, it is also undocumented (via man page or gs -h
) as of version 9.23.
The below command works without worrying about the top being cut off like with the other solutions:
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -sPAPERSIZE=a4 -sDEVICE=pdfwrite -dSAFER file.ps
-sPAPERSIZE=a4
is how the a4 paper size is specified.
to get the page size you can look for a line like the following:
%%PageBoundingBox:·12·12·583·830
and then use
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -g583x830 -r72 -sDEVICE=pdfwrite -dSAFER file.ps
and it works perfectly.
If the input postscript has an EPS BoundingBox
, this should preserve the page size:
ps2pdf -dEPSCrop <input.ps> <output.pdf>