fill_pdf_form_with_annotations.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import json
  2. import sys
  3. from pypdf import PdfReader, PdfWriter
  4. from pypdf.annotations import FreeText
  5. def transform_from_image_coords(bbox, image_width, image_height, pdf_width, pdf_height):
  6. x_scale = pdf_width / image_width
  7. y_scale = pdf_height / image_height
  8. left = bbox[0] * x_scale
  9. right = bbox[2] * x_scale
  10. top = pdf_height - (bbox[1] * y_scale)
  11. bottom = pdf_height - (bbox[3] * y_scale)
  12. return left, bottom, right, top
  13. def transform_from_pdf_coords(bbox, pdf_height):
  14. left = bbox[0]
  15. right = bbox[2]
  16. pypdf_top = pdf_height - bbox[1]
  17. pypdf_bottom = pdf_height - bbox[3]
  18. return left, pypdf_bottom, right, pypdf_top
  19. def fill_pdf_form(input_pdf_path, fields_json_path, output_pdf_path):
  20. with open(fields_json_path, "r") as f:
  21. fields_data = json.load(f)
  22. reader = PdfReader(input_pdf_path)
  23. writer = PdfWriter()
  24. writer.append(reader)
  25. pdf_dimensions = {}
  26. for i, page in enumerate(reader.pages):
  27. mediabox = page.mediabox
  28. pdf_dimensions[i + 1] = [mediabox.width, mediabox.height]
  29. annotations = []
  30. for field in fields_data["form_fields"]:
  31. page_num = field["page_number"]
  32. page_info = next(p for p in fields_data["pages"] if p["page_number"] == page_num)
  33. pdf_width, pdf_height = pdf_dimensions[page_num]
  34. if "pdf_width" in page_info:
  35. transformed_entry_box = transform_from_pdf_coords(
  36. field["entry_bounding_box"],
  37. float(pdf_height)
  38. )
  39. else:
  40. image_width = page_info["image_width"]
  41. image_height = page_info["image_height"]
  42. transformed_entry_box = transform_from_image_coords(
  43. field["entry_bounding_box"],
  44. image_width, image_height,
  45. float(pdf_width), float(pdf_height)
  46. )
  47. if "entry_text" not in field or "text" not in field["entry_text"]:
  48. continue
  49. entry_text = field["entry_text"]
  50. text = entry_text["text"]
  51. if not text:
  52. continue
  53. font_name = entry_text.get("font", "Arial")
  54. font_size = str(entry_text.get("font_size", 14)) + "pt"
  55. font_color = entry_text.get("font_color", "000000")
  56. annotation = FreeText(
  57. text=text,
  58. rect=transformed_entry_box,
  59. font=font_name,
  60. font_size=font_size,
  61. font_color=font_color,
  62. border_color=None,
  63. background_color=None,
  64. )
  65. annotations.append(annotation)
  66. writer.add_annotation(page_number=page_num - 1, annotation=annotation)
  67. with open(output_pdf_path, "wb") as output:
  68. writer.write(output)
  69. print(f"Successfully filled PDF form and saved to {output_pdf_path}")
  70. print(f"Added {len(annotations)} text annotations")
  71. if __name__ == "__main__":
  72. if len(sys.argv) != 4:
  73. print("Usage: fill_pdf_form_with_annotations.py [input pdf] [fields.json] [output pdf]")
  74. sys.exit(1)
  75. input_pdf = sys.argv[1]
  76. fields_json = sys.argv[2]
  77. output_pdf = sys.argv[3]
  78. fill_pdf_form(input_pdf, fields_json, output_pdf)