Originally reported by: nobody@users.sourceforge.net The aim is to take a pdf file and rearrange to page order such that a 2-up duplexed print can be folded in half to form a booklet. Commercialware equivilant is Quite Imposing.
Comment originally by nobody@users.sourceforge.net Logged In: NO Try www.gdykes.com. Hope this help.
I don't have time to do this properly, but it's relatively simple and along the lines of: 1. modify pdfshowpage_setpage in pdf_main.ps change the setpagedevice to globaldict /MYVAR known {pop} {setpagedevice} ifelse 2. modify endpage in pdf_ops.pdf change the showpage to globaldict /MYVAR known {pop} {showpage} ifelse 3. use the following postscript to "pair" the pages 0 1 Booksize 1 sub 2 div { /i exch def << /PageSize [x y] >> setpagedevice i 2 mod 0 eq { /leftpage Booksize i sub def /rightpage i 1 add def } { /leftpage i 1 add def /rightpage Booksize i sub def } ifelse 0 0 translate /FirstPage leftpage def /LastPage leftpage def (multipagefile.pdf) run x 2 div 0 translate /FirstPage rightpage def /LastPage rightpage def (multipagefile.pdf) run showpage }for 4. run gs with the command-line options -dMYVAR -sBooksize=<number of pages>
Created attachment 1701 [details] Library file to sequence PDF pages for imposition This file defines one procedure, pdfimpose, that will render the pages of a PDF in an order that can be concisely specified for imposition. Depending on the selected output device, the result can be a reordered pdf, ps, or whatever. Imposition has two separable issues, sequencing and geometry; pdfimpose handles the sequencing part, as the report requested, as once the pages are in proper sequence there is existing work for n-up pages and duplexing (e.g. gsnup.ps is already distributed with ghostscript).
Created attachment 1702 [details] Example: impose a simple pdf manual as a folio Example takes a simple pdf manual found in the wild and makes a folio of it. Creates a folio pdf in one step; uses pdfimpose for the sequencing, and net.anastigmatix.PageNest for the geometry.
Created attachment 1703 [details] Example: another way to create folio (several signatures this time) Demonstrates a few more possibilities than attachment #1702 [details]. Produces multiple signatures (will fold better than one fat one) assuming they will be bound as a book somehow.
Created attachment 1704 [details] Example: fancy folio imposition of the same manual This example takes care of the original pdf having the table of contents in the wrong place, and instead of breaking the manual into signatures by an arbitrary page count, makes a logical division at the appendices; also handles the fact that each appendix starts on an even (should be verso) page.
Created attachment 1705 [details] Example: quarto imposition of a more elaborate pdf The more elaborate pdf of this product manual, also found in the wild, includes pages with very different native dimensions and orientations that must be accounted for. It also includes many pdfmarks that cannot be simply copied into the new pdf because the page rearrangement would make them nonsense.
Created attachment 1706 [details] Example: sixmo imposition of the same pdf The same elaborate pdf from attachment #1705 [details], this time imposed as a sixmo to save a little more paper.
I have an implementation (attachment #1701 [details]) working in GPL Ghostscript 8.15 and I expect it will work on the HEAD. {pop} [] [-1 0 1 -2] (file.pdf) pdfimpose will show the pages of file.pdf in the proper order for a folio (print 2-up duplex, fold once) imposition, the kind most people have in mind for printing some random article as a booklet. If the pdf does not have a multiple of 4 pages, a few blank (half-)pages may be generated. A procedure other than {pop} can be specified to paint something on those pages, like "This page left blank." As you can see, the simple folio is only one special case of the sequencing pdfimpose can do - it has to support arbitrary impositions if it is to be described as anything close to equivalent of Quite Imposing etc. Imposition has two separable issues: sequencing and geometry. pdfimpose handles the sequencing part, as this report requested; it will put the pages in the right sequence so they can be combined, with the right geometry, to get the final result. Used by itself, it will simply output the original pages in a new order on whatever device is selected, so it can generate a reordered pdf, reordered ps, or whatever. Existing tools like Angus Duggan's psnup from psutils, the gsnup.ps already in the ghostscript distribution, or net.anastigmatix.PageNest, can be used with those files to arrange the pages on sheets with the right geometry. It can be handy to do the sequencing and geometry in one step, as the attached examples do by using pdfimpose for the sequencing and PageNest for the geometry (which has enough flexibility to handle the more elaborate examples). PageNest I had already written, not specifically for ghostscript, so it is not included in the copyright assignment, but that should pose no problem for anyone who would like to use it, as it is already licensed for unrestricted use and redistribution. It should also be possible to use the gsnup.ps already present for the simpler imposition geometries; I would have included some examples done with gsnup but it has a few bugs I'll add to the tracker. Two enhancements to the underlying PDF processing would simplify this, and eliminate the need for -dDELAYBIND to get the examples working. 1. pdfshowpage_finish calls showpage (endpage) before restore, rather than after, where it belongs. Both gsnup and PageNest include showpage/restore hacks intended to work around that issue in ordinary PostScript code, but for them to work in gs library code, DELAYBIND is needed. Fixing pdfshowpage_finish to get the restore and showpage in the right order would eliminate this issue; it is not clear to me what if anything depends on the current late restore, so I have not tried to fix it myself. 2. there is no facility to disable pdfmark with the pdfwrite device, or to intercept it with a callback. When rewriting a pdf to pdf, by default all pdfmarks from the original get copied; when the page order and dimensions are really being totally rearranged, those pdfmarks are worse than useless, and will cause a viewer to display the file incorrectly. I get around it with DELAYBIND to bind a version of pdfmark that has a callback hook, and completes the action only if the callback returns true. If some similar hook arrangement became a standard feature, this use of DELAYBIND would be unnecessary. Perhaps a new pdfwrite pseudoparameter could be used to specify a pdfmark callback procedure, or it could be a special pdfmark or a PUT to a special object: [ {gspdfmarkcallback} { dup = false } /PUT pdfmark. Partly a matter of taste, so I have not made a decision on my own. One of the difficulties with gsnup.ps is it blows the execution stack if DELAYBIND is used; it would need some attention to make sure its procedures don't become recursive in that case. Everything gets easier if those two enhancements make the DELAYBIND unnecessary. There is another issue that is likely to cause the one-step approach in the examples to fail: transparency. At present any page that contains a use of transparency results in a .pushpdf14devicefilter, which seems to erase anything rendered on the medium to that point. That will be a problem if an n-up page is being accumulated. A workaround is to go back to two steps, use pdfimpose just to make a reordered file, use (hopefully something better than) pswrite to get reordered PostScript, and use any n-up geometry tool of choice to finish the job. Is it true that the pdf14 filter just turns everything into an image for the device below? Is it possible to make it conditional, so it doesn't get pushed if the output device is pdfwrite with CompatibilityLevel >= 1.4? (Or does it already do the right thing in that case? I didn't explore too deeply.) That would at least make it simple to do pdf->pdf impositions in one step, even with transparency. For trying out the examples, PageNest can be downloaded from http://www.anastigmatix.net/postscript/PageNest.html. Two files are needed, MetaPre and PageNest, as described on the page.
A couple documentation errata: The comments in attachment #1701 [details] fail to document that if seqSpec is empty, pdfimpose uses blockSpec (exactly once, regardless of its length) as a list of explicit page numbers to process in order (0 being FirstPage; negative values are still usable, -1 meaning LastPage); in that way pdfimpose's calculations can be overridden to do completely arbitrary page ordering. Attachment #1704 [details] used that feature for the table of contents and the start of the appendices, so the example would be hard to understand without the explanation. In attachment #1705 [details] and attachment #1706 [details], there are two sentences each about "In principle, the UserBBox could be obtained ..." where there is no longer any UserBBox or related code. The sentences should have been deleted. In attachment #1706 [details], the old code they pertained to is still there, commented out; it should have been deleted too.
I've taken the liberty of marking this bug resolved, because (a) I believe pdfimpose.ps resolves it, (b) I looked at the lifecycle help and thought perhaps marking it resolved helps it show up as something for QA to look at, and (c) bugzilla didn't object. I'm sure if you review it and decide there was something I missed after all, you'll reopen it. Looking forward to hearing your opinions.
We generally only close bugs when the fix has been committed. This will take a few days for us to finish reviewing, but my initial thought is that this is worthwhile and should be added to the Ghostscript distribution (committed to CVS). Once this is committed, then we'll close the bug.
assigning to myself to do the review and/or commit.
No problem - didn't mean to step on any toes. Out of curiosity, is bugs.ghostscript.com/bug_status.html a reasonable picture of the bug lifecycle used for ghostscript, or is it a default page installed with bugzilla that hasn't been locally customized? That was where I got the idea the progression would be Resolved (here's a fix, I think) -> Verified (yep, looks like a fix) -> Closed (it's committed). Sorry if I misunderstood. One more for the errata: in attachment #1705 [details] and attachment #1706 [details], the example pdfimpose_setpage procedure should not be considered complete for the general case. It assumes the CropBox is given in llx lly urx ury form, which is true for the sample PDF, but the PDF spec for some unfathomable reason allows any two opposite box corners to be given in any order, so a general solution needs to normalize the corners. I'm pretty sure there is already code somewhere in pdf_*.ps for doing that. It also looks only for CropBox and, if none, falls back to MediaBox. A general solution ought to look at TrimBox, BleedBox, or ArtBox first; the fallback for each of those is CropBox, and the ultimate fallback is MediaBox. Which of TrimBox, BleedBox, or ArtBox to look at is not a purely automatable choice, because it will depend on the intended use and how the pages will be folded, trimmed, and finished. TrimBox is a good general purpose choice if making a folio where nothing will really be trimmed so the printed folded page is already at its final dimensions. BleedBox is the canonical choice if something is really going to be trimmed and finished with the traditional methods. ArtBox would be a good choice if the goal is to enlarge the visible content as much as possible when fitting to the page, sacrificing margins.
Examples errata: the example scripts should contain << /AutoRotatePages /None >> setdistillerparams or << /AutoRotatePages /All >> setdistillerparams. Otherwise, I seem to get a default of /PageByPage, which can cause the generated PDF file to have nonuniform page orientations ... not useful for imposition ....
Have now tried pdfimpose and the examples in GS 8.51 and can confirm they work.
Hi, comment #12 suggested several days might be needed to review and/or commit. Of course the 8.53 release was in the works and must have needed a lot of time and attention, and maybe there will be a better chance now. I hope not to be a pest, but if the solution seems to address the requirements, for various utterly nontechnical reasons it would be convenient for me to process the bounty this calendar year. If there seems to be any way it falls short of addressing the requirements, I would be pleased to know about it. Thanks!
Passing to Alex who owns gs/lib . Or maybe it shoyld go to gs/toolbin .
After discussion amongst the developers we've decided to close this as wontfix because its been dormant for so long. I'd like to take the opportunity to apologise to everyone concerned about the fact that this was left to rot, I really am terribly sorry.