JPF
JPF

Reputation: 45

How to crop a multipage pdf using ghostscript with an array of page specific cropboxes

This post is a follow-up of "How do I crop pages 3&4 in a multipage pdf using ghostscript", but it changes the input to an array of data.


The quest: I have a pdf file (a set of drawings) where all pages have the same size and I want to crop some pages in one way and others differently. The following screenshot shows how I generated the data below for cropping:spreadsheet The "left,bottom,right,top" are to be handed over to the postscript /CropBox [934 350 3318 2034] command. Pagenumbers are just consecutive numbers, so they may not rally be needed.

page#,left,bottom,right,top

1   0   0   4252    2384
2   0   0   4252    2384
3   0   0   4252    2384
4   0   0   4252    2384
5   934 350 3318    2034
6   934 350 3318    2034
7   441 0   3811    2384
8   441 0   3811    2384

With the solution in the above mentioned question I was able to crop a specific page in an multipage pdf and it probably is a good starting point for a solution to this question. I just didn't figure it out on my own.

The relevant postscript code which tried to use as a base to solve this problem is (thanks to KenS):

<<
  /EndPage {
    0 eq {
      pop /Page# where {
        /Page# get
        3 eq {
          (page 3) == flush
          [/CropBox [0 0 1612 1792] /PAGE pdfmark 
          true
        }
        {
          (not page 3) == flush
          [/CropBox [500 500 612 792] /PAGE pdfmark
          true
        } ifelse
      }{
        true
      } ifelse
    }
    {
      false
    }
    ifelse
  }
>> setpagedevice

I guess we need some test numbers for "realistic" page sizes for my crazy page size dictionary... just for some fun testing.

/MyCrazyPageSizeDictionary begin
/PageSizeArray [
[0 0 595 842]       % original A4 portrait
[87 123 508 719]    % cut to A5
[149 210 446 631]   % cut to A6
[192 272 403 570]   % cut to A7
[223 316 372 526]   % cut to A8
] def

Upvotes: 2

Views: 918

Answers (1)

KenS
KenS

Reputation: 31199

I'd suggest you place the cropping information for each page in an array, and then add each array to an enclosing array. The problem is likely to be retaining the information.

The best way to do this, probably, is to create the array of page information as a named object in a specific dictionary. If you don't create your own dictionary, then userdict will be used instead.

Then in your EndPage procedure you simply pull the relevant index of the enclosing array, which gives you an array of crop sizes:

So, for example;

%!
/MyCrazyPageSizeDictionary 1 dict def
/MyCrazyPageSizeDictionary begin
/PageSizeArray [
[   0   0   4252    2384]
[   0   0   4252    2384]
[   0   0   4252    2384]
[   0   0   4252    2384]
[   934 350 3318    2034]
[   934 350 3318    2034]
[   441 0   3811    2384]
[   441 0   3811    2384]
] def
end

<<
  /EndPage {
    0 eq {
      pop /Page# where {
        /Page# get                                    % stack - pagenum
        /MyCrazyPageSizeDictionary /PageSizeArray get % stack - pagenum [[]]
        exch                                          % stack - [[]] pagenum
        get                                           % stack - []
        [ /CropBox                                    % stack - [] [ /CropBox
        3 -1 roll                                     % stack - [ /CropBox []
        /Page pdfmark
        true
      }{
        true
      } ifelse
    }
    {
      false
    }
    ifelse
  }
>> setpagedevice

If you put that in a file (named eg crop.ps) then run your PDF file through Ghostscript but put 'crop.ps' as one of the input files before your PDF file:

gs <options....> crop.ps input.pdf

Then it should do what you want. With the caveat that I haven't tested this program in any way......

[Edit, added the corrected program]

/MyCrazyPageSizeDictionary 1 dict def
MyCrazyPageSizeDictionary begin
/PageSizeArray [
[   0   0   4252    2384]
[   0   0   4252    2384]
[   0   0   4252    2384]
[   0   0   4252    2384]
[   934 350 3318    2034]
[   934 350 3318    2034]
[   441 0   3811    2384]
[   441 0   3811    2384]
] def
end

<<
  /EndPage {
    0 eq {
      pop /Page# where {
        /Page# get                                    % stack - pagenum
        1 sub                                         % array index is 0 based, page numbers start at 1
        MyCrazyPageSizeDictionary /PageSizeArray get  % stack - pagenum [[]]
        exch                                          % stack - [[]] pagenum
        1 index length mod                            % get array, find length, clamp page number to length
        get                                           % stack - []
        [ /CropBox                                    % stack - [] [ /CropBox
        3 -1 roll                                     % stack - [ /CropBox []
        /PAGE pdfmark
        true
      }{
        true
      } ifelse
    }
    {
      false
    }
    ifelse
  }
>> setpagedevice

Upvotes: 2

Related Questions