Libby
Libby

Reputation: 1022

Find PDF Form Field position

I realize this question has been asked a lot, but I could not find any information about how to do this in RoR. I am filling a PDF with form text fields using pdf-forms but this does not support adding images, and I need to be able to add an image of a customer's signature into the PDF. I have used prawn to render the image on the existing PDF, but I need to know the exact location to add the image on the signature line. So my question is how can I look at an arbitrary PDF and find the exact position of the "Signature" form field?

Upvotes: 4

Views: 2529

Answers (3)

Michael Wasser
Michael Wasser

Reputation: 1837

Here's a pure ruby implementation that will return the field's name, page, x, y, height, and width using Origami https://github.com/gdelugre/origami

require "origami"

def pdf_field_metadata(file_path)
  pdf = Origami::PDF.read file_path

  field_to_page = {}
  pdf.pages.each_with_index do |page, page_index|
    (page.Annots || []).each do |annot|
      field_to_page[annot.refno] = page_index
    end
  end

  field_metas = []
  pdf.fields.each do |field|
    field_metas << {
      name: field.T,
      page_index: field_to_page[field.no],
      x: field.Rect[0].to_f,
      y: field.Rect[1].to_f,
      h: field.Rect[3].to_f - field.Rect[1],
      w: field.Rect[2].to_f - field.Rect[0]
    }
  end

  field_metas
end

pdf_field_metadata "<path to pdf>"

I haven't tested it particularly thoroughly but the snippet can hopefully get you most of the way there.

Also -- keep in mind the above coordinates calculated are in points from the bottom left of the pdf page rather than the top right (and are not in pixels). I believe there's always 72 points per inch, and you can get the total page points by calling page.MediaBox in the pdf.pages loop above. If you're looking for pixel coordinates, you need to know the DPI of the resulting rendered document.

Upvotes: 0

Libby
Libby

Reputation: 1022

I ended up using pdf2json to find the x,y position of the form field. I generate a JSON file of the original pdf using this command:

%x{ pdf2json -f "#{form_path}" }

The JSON file is generated in the same directory as form_path. I find the field I want using these commands:

jsonObj = JSON.parse(File.read(json_path))
signature_fields = jsonObj["formImage"]["Pages"].first["Fields"].find_all do |f|
    f["id"]["Id"] == 'signature'
end

I can use prawn to first create a new PDF with the image. Then using pdf-forms, I multistamp the image pdf onto the original PDF that I want to add the image to. But multistamp applies each page of the stamp PDF to the corresponding page of the input PDF so make sure your image PDF has the correct number of pages or else your image will get stamped on every page. I only want the image stamped onto the first page, so I do the following:

  num_pages = %x{ #{Rails.configuration.pdftk_path} #{form_path} dump_data | grep "NumberOfPages" | cut -d":" -f2 }.to_i
  signaturePDF = "/tmp/signature.pdf"
  Prawn::Document.generate(signaturePDF) do
    signature_fields.each do |field|
      image Rails.root.join("signature.png"), at: [field["x"], field["y"]], 
                                                  width: 50
    end
    [0...num_pages - 1].each{|p| start_new_page }
  end

  outputPDF = "/tmp/output.pdf"
  pdftk.multistamp originalPDF, signaturePDF, outputPDF

Upvotes: 3

Marat Tynarbekov
Marat Tynarbekov

Reputation: 115

You can use this gem 'wicked_pdf. You just write html, and this gem automatically convert it to pdf Read more https://github.com/mileszs/wicked_pdf

Upvotes: 1

Related Questions