【问题标题】:ps2pdf: preserve page sizeps2pdf:保留页面大小
【发布时间】:2015-07-19 15:08:03
【问题描述】:

我有myfile.ps,其中包含矢量图像。 但是当我跑步时

ps2pdf myfile.ps

输出的页面大小好像是A4:矢量图太大被切掉了,所以少了一寸左右。

除了原始矢量图像之外,输出 PDF 文件中还会打印以下伪标题:

PLOT SIZE:8.02x8.62Inches
Magnification:7354.21X

是否有任何选项或方法可以将 PS 文件转换为 PDF保留原始纸张尺寸?

【问题讨论】:

    标签: pdf ghostscript vector-graphics


    【解决方案1】:

    我怀疑您引用的 2 行是否真的在引用的 PS 文件中...它们之前不是有 % 注释字符吗?

    • 如果它们之前没有这些字符,则任何 PS 解释器都不会工作,因为它们不是已知的 PostScript 运算符。

      李>
    • 如果它们之前有这样的字符,PS 解释器会简单地忽略它们,因为...它们只是 cmets! :-)

    如果您想将此 PS 文件转换为 PDF,最好直接运行 Ghostscript(ps2pdf 无论如何只是一个围绕 Ghostscript 命令的瘦壳脚本包装器):

    gs -o myfile.pdf     \
       -sDEVICE=pdfwrite \
       -g5775x6207       \
       -dPDFFitPage      \
        myfile.ps
    

    说明:

    1. -g...像素为单位给出中等大小。
    2. A4 页面的尺寸为595x842pt(PostScript 点)。
    3. 1 英寸等于 72 个 PostScript 点。
    4. 默认情况下,Ghostscript 在内部以每英寸 720 像素的分辨率计算 PDF 输出。
    5. 因此用于 PDF 输出595x842pt == 5950x8420px
    6. 因此对于您的问题8.02x8.62Inches ≈≈ 5775x6207px

    【讨论】:

    • 你是对的:我将输出的 PDF 标题与 PS 标题混合在一起,错误地认为它们是相同的。现在我纠正了这个问题。不幸的是,根据您的价值观,图像仍然被切掉,可能是因为那个“标题”不那么值得信赖。但是将输出大小增加几百个像素会得到正确的结果。谢谢!
    【解决方案2】:

    如果输入后记有 EPS BoundingBox,这应该保留页面大小:

    ps2pdf -dEPSCrop <input.ps> <output.pdf>

    【讨论】:

    • @roy ps2pdf / ghostscript 的哪个版本?错误信息是什么?您的输入后记是否包含边界框?您似乎投了反对票,但您没有提供很多信息。
    • 未显示错误,但生成的 PDF 不会保留页面大小。正如您所说,也许该选项会读取边界框,但这个问题是关于存储在 DocumentMedia 标头中的页面大小,请参阅下面的答案。
    • @roy 感谢您的澄清。我更新了我的答案以反映其局限性。
    【解决方案3】:

    根据@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} = $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;
    }
    

    【讨论】:

      【解决方案4】:

      我不允许发表评论,但我必须警告大家,所有当前的答案都容易受到恶意 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
      

      而且效果很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-30
        • 1970-01-01
        • 2015-06-05
        • 2010-12-20
        • 1970-01-01
        相关资源
        最近更新 更多