ps2pdf: preserve page size

前端 未结 4 1246
-上瘾入骨i
-上瘾入骨i 2021-02-13 22:34

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

相关标签:
4条回答
  • 2021-02-13 22:49

    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;
    }
    
    0 讨论(0)
  • 2021-02-13 22:52

    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:

    1. -g... gives the medium size in pixels.
    2. An A4 page has a dimension of 595x842pt (PostScript points).
    3. 1 Inch is the same as 72 PostScript points.
    4. Ghostscript internally by default computes with a resolution of 720 pixels per inch when it comes to PDF output.
    5. Hence for PDF output 595x842pt == 5950x8420px.
    6. Hence for your case in question 8.02x8.62Inches ≈≈ 5775x6207px.
    0 讨论(0)
  • 2021-02-13 22:54

    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.

    0 讨论(0)
  • 2021-02-13 23:03

    If the input postscript has an EPS BoundingBox, this should preserve the page size:

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

    0 讨论(0)
提交回复
热议问题