galkahana / HummusJS

Node.js module for high performance creation, modification and parsing of PDF files and streams
http://www.pdfhummus.com
Other
1.14k stars 169 forks source link

How to resize an existing PDF ? #192

Open GautierT opened 7 years ago

GautierT commented 7 years ago

Hi ! I want to resize an existing PDF to A4 format. I don't know the size of the existing PDF and it can be different each time. I want to scale it to A4 (595,842).

I don't find the info in the wiki/tests or in the issues.

Thanks a lot.

galkahana commented 7 years ago

this should help you - https://github.com/galkahana/HummusJS/wiki/Embedding-pdf#create-form-xobjects-from-source-pages

create form xobjects from the pages, and then you can place them scaled in new pages.

GautierT commented 7 years ago

Thanks @galkahana. But i have trouble understanding the function name and role. I should create a new page with the right format ? Like this : var page = pdfWriter.createPage(0,0,595,842);

Then merge my existing PDF (who have multiple page in it) on my new PDF ?

Thanks in advance for the help.

galkahana commented 7 years ago

right. creating a page is step one.

create the form by calling: pdfWriter.createFormXObjectsFromPDF(inSourceFilePath, [inFormBox || inSourcePageBoxEnum], [inPageRangeObject]);

then you can place it. placing form (as well as creating your own), is explained here: https://github.com/galkahana/HummusJS/wiki/Reusable-forms

specifically you will need to use the cm command to determine the scale and position of the page form. cm sets a two dimensional transformation matrix, meaning that the 2 last numbers are offset, and number at 0 and 3 set the scale for X and Y respectively (which in your case should be the division between the end width/height (A4) and source width/height (of the original page).

getting the original page size: https://github.com/galkahana/HummusJS/wiki/Parsing#page-info-objects

you need the media box.

Gal.

GautierT commented 7 years ago

Thanks a lot @galkahana.

For futur reference here is my code to resize a PDF in javascript / node.js with HummusJs :

export const resize_pdf = async (file_path)=>{

  let file_path_tmp = `./tmp/tmp.pdf`
  const resizeWriter = hummus.createWriter(file_path_tmp)

  const xobjectForm = resizeWriter.createFormXObjectsFromPDF(file_path, hummus.ePDFPageBoxMediaBox)

  const resizeReader = hummus.createReader(file_path)
  const resize_page_count = resizeReader.getPagesCount()

  for (let i = 0; i < resize_page_count; i++) {
    const currentHeight = resizeReader.parsePage(i).getMediaBox()[3]
    const currentWidth = resizeReader.parsePage(i).getMediaBox()[2]

    const maxHeight = 842
    const maxWidth = 595

    let width = 595
    let height = 842

    let ratio = 1

    if(currentWidth > maxWidth){
      ratio = maxWidth / currentWidth
      width = currentWidth * ratio
      height = currentHeight * ratio
    }

    if(currentHeight > maxHeight){
      ratio = maxHeight / currentHeight
      width = currentWidth * ratio
      height = currentHeight * ratio
    }

    const page = resizeWriter.createPage(0, 0, 595, 842)

    const pageContent = resizeWriter.startPageContentContext(page)

    pageContent.q()
      .cm(ratio, 0, 0, ratio, 0, 0)
      .doXObject(page.getResourcesDictionary().addFormXObjectMapping(xobjectForm[i]))
      .Q()

    resizeWriter.writePage(page)
  }

  resizeWriter.end()

  await fs.renameAsync(file_path_tmp, file_path)
}
GautierT commented 6 years ago

@galkahana : Can i do that this way ? Using drawImage instead of addFormXObjectMapping ?

const resizeWriter = hummus.createWriter(file_path_tmp)
const resizeReader = hummus.createReader(file_path)

const resize_page_count = resizeReader.getPagesCount()

  for (let i = 0; i < resize_page_count; i++) {
    debug('Page : ', i)
    const page = resizeWriter.createPage(0, 0, 595, 842)

    const pageContent = resizeWriter.startPageContentContext(page)

    const margin = 0

    pageContent
      .q()
      .drawImage(margin, margin, file_path, {
        index: i,
        transformation: {
          width: maxWidth - (margin*2),
          height: maxHeight - (margin*2),
          proportional: true
        }
      })
      .Q()

    resizeWriter.writePage(page)
  }

  resizeWriter.end()
galkahana commented 6 years ago

Sure. Under the hood it does pretty much the same thing.

GautierT commented 6 years ago

Awesome ! Sounds a lot more easier. Thanks.

GautierT commented 6 years ago

Hi @galkahana : are you aware of other way to resize a PDF ? It is very slow when the PDF have a multiple page. Even with an other library. I tried http://www.graphicsmagick.org/ but it transform the PDF to an image so we loose the ability to read text from the PDF.

Thanks !

vegarringdal commented 5 years ago

moved to own issue

vegarringdal commented 5 years ago

moved to own issue