node.jspdfpdfmakepdfjam

PDF conversion to different page format using pdfjam


Basically, I have pdf letters generated in various of formats like A4, A3 and customers would like to convert those formats into Letter format

All pdfs are created using pdfmake library in node.js environment and I need to convert all of these documents into specified format. I don't want to write new layouts for each of those pdfs according to the Letter format because it will take too much time and I am willing to make it easier

For conversion, I am using this command pdfjam --outfile out.pdf --paper letter input.pdf

But I have a problem with one case of conversion, for instance If I insert images into pdf and provide a link to this image after conversion link for the image disappears

Here is the demo of pdf document layout defined using pdfmake. Codesandbox

And after conversion to letter format that link for the image is gone. If you know how to fix this or any other way for conversion I will be happy to use it :)


Solution

  • For the task example, so as not to disturb the internal contents, the page simply needs cropping down to a smaller viewport, at an offset. Here 612 points wide and 398 points up would be enough. However shifting the View is not the best answer for all cases. Note if the intent is to "Scale Down" the process will be similar. Scaling should be centered around the lower left corner, then crop to suit.

    Taking the example source A3 file with data at top left.

    1190 +-----+---+
         | USA |   | 
         | LET |   | 
         | TER |   | 
     398 +-----+   |
         |  ISO A3 |
       0 +---------+
         0    612
    

    This is possible simplest in any program shell by using PDFcpu

    pdfcpu crop -- "[0 398 612 1190]" input.pdf output.pdf

    enter image description here

    A better solution can be done, by using a shift of the page contents down then crop a conventional page. The page /MediaBox should be normalised down in height and ALL the contents and related links also edited to their new position. This shift again is desirable before scaling.

    1190 +---------+
         |↓↓↓↓↓ ISO|
     712 +-----+ A3|
         | USA |   | 
         | LET |   | 
         | TER |   | 
       0 +-----+---+
         0    612
    

    For this approach commercially licensed cpdf is easiest.

    cpdf -shift "0 -398" input-a3.pdf -o temp.pdf AND -mediabox "0pt 0pt usletterportrait" temp.pdf -o output-letter.pdf
    

    Neither are the best which is to transform all contents and box via binary string replacement. So the input.PDF needs decompress to working text format then all the values reduced by the correct amount (recompress is optional).

    String one.

    ***** in.pdf
    1 0 0 -1 0 1190.55 cm
    ***** out.pdf
    1 0 0 -1 0 0792.00 cm
    

    String two.

    ***** in.pdf
    6 0 obj<</Type/Page/Parent 1 0 R/MediaBox[0 0 841.89 1190.55]/Contents 5 0 R/Resources<</ExtGState<</Gs1 7 0 R>>/XObject<</I1 4 0 R>>>>/Annots[9 0 R]>>
    ***** out.pdf
    6 0 obj<</Type/Page/Parent 1 0 R/MediaBox[0 0 612.00 0792.00]/Contents 5 0 R/Resources<</ExtGState<</Gs1 7 0 R>>/XObject<</I1 4 0 R>>>>/Annots[9 0 R]>>
    

    String three.

    ***** in.pdf
    9 0 obj<</Subtype/Link/A 8 0 R/Type/Annot/Rect[40 967.55 315 1150.55]/Border[0 0 0]/F 4>>endobj
    ***** out.pdf
    9 0 obj<</Subtype/Link/A 8 0 R/Type/Annot/Rect[40 569.00 315 0752.00]/Border[0 0 0]/F 4>>endobj
    

    The co-responding changed values in cpdf will be similar, my guess was rounded as 0.55 points out! however the page contents in cpdf reflect a negative shift (-398) and the source height (1190.55) that may be undesirable.

    /MediaBox[0 0 612 792]  
    /Rect[40 569.55 315 752.55  
    stream
    1 0 0 1 0 -398 cm q 1 0 0 -1 0 1190.55 cm/Gs1 gs q 275 0 0 -183 40 223 cm/I1 Do Q Q
    endstream