tile.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # SPDX-FileCopyrightText: 2026 geisserml <geisserml@gmail.com>
  2. # SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
  3. from enum import Enum
  4. from pathlib import Path
  5. import pypdfium2.raw as pdfium_c
  6. import pypdfium2._helpers as pdfium
  7. from pypdfium2._cli._parsers import add_input, get_input
  8. class Units (Enum):
  9. PT = 0
  10. MM = 1
  11. CM = 2
  12. IN = 3
  13. def units_to_pt(value, unit):
  14. if unit is Units.PT:
  15. return value
  16. elif unit is Units.IN:
  17. return value*72
  18. elif unit is Units.CM:
  19. return (value*72) / 2.54
  20. elif unit is Units.MM:
  21. return (value*72) / 25.4
  22. else:
  23. raise ValueError(f"Invalid unit type {unit}")
  24. def attach(parser):
  25. add_input(parser, pages=False)
  26. parser.add_argument(
  27. "--output", "-o",
  28. required = True,
  29. type = Path,
  30. help = "Target path for the new document",
  31. )
  32. parser.add_argument(
  33. "--rows", "-r",
  34. type = int,
  35. required = True,
  36. help = "Number of rows (horizontal tiles)",
  37. )
  38. parser.add_argument(
  39. "--cols", "-c",
  40. type = int,
  41. required = True,
  42. help = "Number of columns (vertical tiles)",
  43. )
  44. # NOTE no short aliases for width and height since -h would conflict with argparse help
  45. parser.add_argument(
  46. "--width",
  47. type = float,
  48. required = True,
  49. help = "Target width",
  50. )
  51. parser.add_argument(
  52. "--height",
  53. type = float,
  54. required = True,
  55. help = "Target height",
  56. )
  57. parser.add_argument(
  58. "--unit", "-u",
  59. default = Units.MM,
  60. type = lambda string: Units[string.upper()],
  61. help = "Unit for target width and height (pt, mm, cm, in)",
  62. )
  63. def main(args):
  64. # Rudimentary page tiling, powered by pdfium
  65. # A more sophisticated implementation could place XObjects rather than using PDFium's helper function, support merging and arranging on the fly, etc.
  66. w = units_to_pt(args.width, args.unit)
  67. h = units_to_pt(args.height, args.unit)
  68. src_pdf = get_input(args)
  69. raw_dest = pdfium_c.FPDF_ImportNPagesToOne(src_pdf, w, h, args.cols, args.rows)
  70. dest_pdf = pdfium.PdfDocument(raw_dest)
  71. dest_pdf.save(args.output)