ps2pdf:保留页面大小
ps2pdf: preserve page size
我有 myfile.ps
,其中包含矢量图像。
但是当我 运行
ps2pdf myfile.ps
输出的页面尺寸好像是A4:矢量图太大被切掉了,所以少了一英寸。
除原始矢量图像外,输出的 PDF 文件中还会打印以下 pseudo-header:
PLOT SIZE:8.02x8.62Inches
Magnification:7354.21X
是否有任何选项或方法可以将 PS 文件转换为 PDF 保留 原始纸张大小?
我怀疑你引用的 2 行是否真的在引用的 PS 文件中......它们前面不是有 %
注释字符吗?
如果没有前面有这样的字符,PS解释器将无法工作,因为它们不是已知的 PostScript 运算符。
如果它们 是 前面有这样的字符,PS 解释器将简单地忽略它们,因为...它们只是评论! :-)
如果要将此 PS 文件转换为 PDF,最好直接 运行 Ghostscript(ps2pdf
只是一个薄的 shell 脚本包装器无论如何都是 Ghostscript 命令):
gs -o myfile.pdf \
-sDEVICE=pdfwrite \
-g5775x6207 \
-dPDFFitPage \
myfile.ps
解释:
-g...
以 像素 给出中等大小。
- A4 页面的尺寸为
595x842pt
(PostScript 点)。
- 1 英寸等于 72 PostScript 点。
- 当涉及到 PDF 输出时,Ghostscript 在内部默认使用每英寸 720 像素的分辨率进行计算。
- 因此用于 PDF 输出
595x842pt == 5950x8420px
。
- 因此对于您的问题
8.02x8.62Inches ≈≈ 5775x6207px
。
如果输入后记有 EPS BoundingBox
,这应该保留页面大小:
ps2pdf -dEPSCrop <input.ps> <output.pdf>
根据@Kurt Pfeifle 的回答,我编写了这个 Perl 脚本来完成任务:
#! /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} = ;
}
# look for any other field
# Ex: %%BoundingBox: 0 0 1008 612
elsif(/^%%(\w+)\s*:\s*(.*\S)/) {
$head{} = ;
}
# discard regular comments and blank lines
elsif(/^\s*(%.*)?$/) {
next;
}
# any other thing will finish the header
else {
last;
}
}
return \%head;
}
不允许评论,但必须警告大家,目前所有答案都容易受到恶意postscript文件的攻击。
像这样使用 gs
是非常危险的。 ps2pdf
内部使用 -dSAFER
选项,例如,它会阻止不受信任的 postscript 文件加密您的文件并呈现 pdf,要求您为解密密钥支付赎金!始终使用 -dSAFER
!
虽然 -o outputFile.pdf
很好,但从 9.23 版开始它也没有记录(通过手册页或 gs -h
)。
下面的命令可以正常工作,而不必像其他解决方案那样担心顶部被切断:
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -sPAPERSIZE=a4 -sDEVICE=pdfwrite -dSAFER file.ps
-sPAPERSIZE=a4
就是a4纸尺寸的指定方式。
要获取页面大小,您可以查找如下一行:
%%PageBoundingBox:·12·12·583·830
然后使用
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -g583x830 -r72 -sDEVICE=pdfwrite -dSAFER file.ps
而且效果很好。
我有 myfile.ps
,其中包含矢量图像。
但是当我 运行
ps2pdf myfile.ps
输出的页面尺寸好像是A4:矢量图太大被切掉了,所以少了一英寸。
除原始矢量图像外,输出的 PDF 文件中还会打印以下 pseudo-header:
PLOT SIZE:8.02x8.62Inches
Magnification:7354.21X
是否有任何选项或方法可以将 PS 文件转换为 PDF 保留 原始纸张大小?
我怀疑你引用的 2 行是否真的在引用的 PS 文件中......它们前面不是有 %
注释字符吗?
如果没有前面有这样的字符,PS解释器将无法工作,因为它们不是已知的 PostScript 运算符。
如果它们 是 前面有这样的字符,PS 解释器将简单地忽略它们,因为...它们只是评论! :-)
如果要将此 PS 文件转换为 PDF,最好直接 运行 Ghostscript(ps2pdf
只是一个薄的 shell 脚本包装器无论如何都是 Ghostscript 命令):
gs -o myfile.pdf \
-sDEVICE=pdfwrite \
-g5775x6207 \
-dPDFFitPage \
myfile.ps
解释:
-g...
以 像素 给出中等大小。- A4 页面的尺寸为
595x842pt
(PostScript 点)。 - 1 英寸等于 72 PostScript 点。
- 当涉及到 PDF 输出时,Ghostscript 在内部默认使用每英寸 720 像素的分辨率进行计算。
- 因此用于 PDF 输出
595x842pt == 5950x8420px
。 - 因此对于您的问题
8.02x8.62Inches ≈≈ 5775x6207px
。
如果输入后记有 EPS BoundingBox
,这应该保留页面大小:
ps2pdf -dEPSCrop <input.ps> <output.pdf>
根据@Kurt Pfeifle 的回答,我编写了这个 Perl 脚本来完成任务:
#! /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} = ;
}
# look for any other field
# Ex: %%BoundingBox: 0 0 1008 612
elsif(/^%%(\w+)\s*:\s*(.*\S)/) {
$head{} = ;
}
# discard regular comments and blank lines
elsif(/^\s*(%.*)?$/) {
next;
}
# any other thing will finish the header
else {
last;
}
}
return \%head;
}
不允许评论,但必须警告大家,目前所有答案都容易受到恶意postscript文件的攻击。
像这样使用 gs
是非常危险的。 ps2pdf
内部使用 -dSAFER
选项,例如,它会阻止不受信任的 postscript 文件加密您的文件并呈现 pdf,要求您为解密密钥支付赎金!始终使用 -dSAFER
!
虽然 -o outputFile.pdf
很好,但从 9.23 版开始它也没有记录(通过手册页或 gs -h
)。
下面的命令可以正常工作,而不必像其他解决方案那样担心顶部被切断:
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -sPAPERSIZE=a4 -sDEVICE=pdfwrite -dSAFER file.ps
-sPAPERSIZE=a4
就是a4纸尺寸的指定方式。
要获取页面大小,您可以查找如下一行:
%%PageBoundingBox:·12·12·583·830
然后使用
gs -sOutputFile=file.pdf -dNOPAUSE -dBATCH -g583x830 -r72 -sDEVICE=pdfwrite -dSAFER file.ps
而且效果很好。