Splitting one page into two pages with ghostscript

I have a PDF with something like presentation slides and multiple slides per page. How can I use ghostscript to split the file so that it has one slide on it?

+3


source to share


3 answers


A long time ago I wrote some code for someone at comp.lang.postscript to do this, again for PowerPoint slides. This PostScript code assumes that all "subpages" (that is, slides) are the same size and location on the PDF page, and that all PDF pages are the same size. Save the following as a pdf_slice.ps file and follow the usage as described in the comments.



%!PS
% Copyright (C) 2011 Artifex Software, Inc.  All rights reserved.
% 
% This software is provided AS-IS with no warranty, either express or
% implied.
% 
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
% 
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA  94903, U.S.A., +1(415)492-9861.
%
% Slice up a PDF file
%
% usage: gs -sFile=____.pdf  -dSubPagesX= -dSubPagesY= [-dSubPageOrder=] [-dVerbose=]pdf_slice.ps
%
% SubPageOrder is a bit field;
% Default = 0
% Bit 0 - 0 = top to bottom
%         1 = bottom to top
% Bit 1 - 0 = left to right
%         1 = right to left
% Bit 3 - 0 = increase x then y
%       - 1 = increase y then x
% 
% 0 - page 1 at top left, increasing left to right, top to bottom
% 1 - page 1 at bottom left increasing left to right, bottom to top
% 2 - page 1 at top right, increasing right to left, top to bottom
% 3 - page 1 at bottom right increasing right to left, bottom to top
% 4 - page 1 at top left, increasing top to bottom, left to right
% 5 - page 1 at bottom left increasing bottom to top, left to right
% 6 - page 1 at top right, increasing top to bottom, right to left 
% 7 - page 1 at bottom right increasing bottom to top, right to left

%
% Check the parameters to see they are present and of the correct type
%
/Usage {
  (  usage: gs -dNODISPLAY -q -sFile=____.pdf \n) =
  (     -dSubPagesX= -dSubPagesY= [-dSubPageOrder=] pdf_slice.ps \n) =
  (Please see comments in pdf_slice.ps for more details) =
  flush
  quit
} bind def

/Verbose where not {
  /Verbose false def
}{
  pop /Verbose true def
} ifelse

/File where not {
  (\n   *** Missing source file. \(use -sFile=____.pdf\)\n) =
  Usage
} {
  pop
}ifelse

/SubPagesX where not {
  (\n   *** SubPagesX not integer! \(use -dSubPagesX=\)\n) =
  Usage
} {
  Verbose { (SubPagesX ) print } if 
  SubPagesX type 
  Verbose { dup == } if
  /integertype eq not {
    (\n   *** SubPagesX not integer! \(use -dSubPagesX=\)\n) =
    Usage
  }
  pop 
}ifelse

/SubPagesY where not {
  (\n   *** SubPagesY not integer! \(use -dSubPagesY=\)\n) =
  Usage
} {
  Verbose { (SubPagesY ) print } if
  SubPagesY type 
  Verbose { dup == } if
  /integertype eq not {
    (\n   *** SubPagesY not integer! \(use -dSubPagesY=\)\n) =
    Usage
  }
  pop 
}ifelse

/SubPageOrder where not {
  /SubPageOrder 0 def
} {
  Verbose { (SubPageOrder ) print } if
  SubPageOrder type 
  Verbose { dup == } if
  dup == 
  /integertype eq not {
    (\n   *** SubPageOrder not integer! \(use -dSubPageOrder=\)\n) =
    Usage
  }
  pop 
}ifelse

% 
% Turns off most messages
%
/QUIET true def     % in case they forgot

%() =

%
% Open the PDF file and tell the PDF interpreter to start dealing with it
%
File dup (r) file runpdfbegin pop
/PDFPageCount pdfpagecount def

%
% Set up our bookkeeping
%
% First get the size of the page from page 1 of the PDF file
% We assume that all PDF pages are the same size.
%
1 pdfgetpage currentpagedevice
1 index get_any_box 
exch pop dup 2 get exch 3 get
/PDFHeight exch def
/PDFWidth exch def

%
% Now get the page size of the current device. We are assuming that
% this is the size of the individual sub-pages in the original PDF. NB
% This assumes no margins between sub-pages, all sub-pages the same size.
%
currentpagedevice /PageSize get
dup 0 get /SubPageWidth exch def
1 get /SubPageHeight exch def

% 
% Calculate the margins. This is the margin between the page border and
% the enclosed group of sub-pages, we assume there are no borders
% between sub pages.
%
/TopMargin PDFHeight SubPageHeight SubPagesY mul sub 2 div def
/LeftMargin PDFWidth SubPageWidth SubPagesX mul sub 2 div def

Verbose {
  (PDFHeight = ) print PDFHeight ==
  (PDFWidth = ) print PDFWidth ==
  (SubPageHeight = ) print SubPageHeight ==
  (SubPageWidth = ) print SubPageWidth ==
  (TopMargin = ) print TopMargin ==
  (LeftMmargin = ) print LeftMargin ==
} if

%
% This rouitne calculates and sets the PageOffset in the page device
% dictionary for each subpage, so that the PDF page is 'moved' in such 
% a way that the required sub page is under the 'window' which is the current
% page being imaged.
%
/NextPage {
    SubPageOrder 2 mod 0 eq {
        /H SubPagesY SubPageY sub SubPageHeight mul TopMargin add def
    }{
        /H SubPageY 1 sub SubPageHeight mul TopMargin add def
    } ifelse
    SubPageOrder 2 div floor cvi 2 mod 0 eq {
        /W SubPageX 1 sub SubPageWidth mul LeftMargin add def
    }{
        /W SubPagesX SubPageX sub SubPageWidth mul LeftMargin add def
    } ifelse
    << /PageOffset [W neg H neg]>> setpagedevice

Verbose {
  (SubPageX ) print SubPageX ==
  (SubPageY ) print SubPageY ==
  (X Offset ) print W ==
  (Y Offset ) print H == flush
} if

    PDFPage
} bind def

%
% The main loop
% For every page in the original PDF file
%
1 1 PDFPageCount 
{
    /PDFPage exch def

    % Do the gross ordering here rather than in
    % NextPage. We eiither process rows and then 
    % columns, or columns then rows, depending on
    % Bit 3 of SubPageorder
    SubPageOrder 3 le {
        1 1 SubPagesY {
            /SubPageY exch def
            1 1 SubPagesX {
                /SubPageX exch def
                NextPage
                pdfgetpage
                pdfshowpage
            } for
        } for
    } {
        1 1 SubPagesX {
            /SubPageX exch def
            1 1 SubPagesY {
                /SubPageY exch def
                NextPage
                pdfgetpage
                pdfshowpage
            } for
        } for
    } ifelse
} for

      

+4


source


KenS's answer is one that should be accepted by @howardh. KenS uses a very clever PostScript language program to achieve the result. (Always remember what KenS said: his solution will only work "if all" subpages "(ie slides) are the same size and location on the PDF page and that all PDF pages are the same size).

However, for completeness, let me link a few other previous answers (some of which are illustrated) that address similar problems:



These answers also use PostScript code, but only as "snippets" that are passed to Ghostscript on the command line. (If you are not familiar with PostScript, they can be easily modified and adapted for cases where the "subpages" do not have the same size and location on the PDF pages, and where the PDF pages are different sizes.)

+1


source


I would like to suggest one solution that actually
1) splits one PS or PDF page into many separate pages and
2) then concatenates * .pdf to multi-page pdf. But this solution doesn't process fields.

This script works in Linux BASH:

INPUT="input.ps" ; 
RESOLUTION=72 ;
WHOLE_WIDTH=598 ; # current size of portrait A4
WHOLE_HEIGHT=843 ;
COLOUMNS=2 ; #  split vertically
ROWS=1 ; # split horizontally
PAGE_WIDTH=$((WHOLE_WIDTH/COLOUMNS)) ;
PAGE_HEIGHT=$((WHOLE_HEIGHT/ROWS)) ;

# Split: 

for x in `seq 1 ${COLOUMNS}` ; do
  for y in `seq 1 ${ROWS}` ; do 
    gs  -dBATCH -dNOPAUSE -dSAFER \
    -o gramps_tmp_${x},${y}.pdf \
    -r${RESOLUTION} \
    -sDEVICE=pdfwrite \
    -g${PAGE_WIDTH}x${PAGE_HEIGHT} \
    -c "<</PageOffset [$(((x - 1)*(0 - PAGE_WIDTH))) \
                       $(((y - 1)*(0 - PAGE_HEIGHT)))]>> setpagedevice" \
    -f "$INPUT" ;
  done ;
done ;

# Merge:

gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=singleCombinedPdfFile.pdf -dBATCH gramps_tmp_*.pdf ;

      

But we can organize the pages in the order we want:

ORDERED="tmp_1,1.pdf tmp_1,2.pdf" ;
gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=singleCombinedMultipagePdfFile.pdf -dBATCH  ${ORDERED};

      

+1


source







All Articles