puzzle/content/ws_fairytales/linkify.py

120 lines
3.8 KiB
Python

from pypdf import PdfReader, PdfWriter, PageObject
from pypdf.annotations import Link
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from PIL import Image
import io
def image_to_page(image_path: str,
x_position: int, y_position: int,
desired_width: int, desired_height: int) -> PageObject:
image_pdf = io.BytesIO()
c = canvas.Canvas(image_pdf, pagesize=letter)
c.drawImage(image_path, x_position, y_position,
width=desired_width, height=desired_height)
c.save()
image_pdf.seek(0)
return PdfReader(image_pdf).pages[0]
class Stamp:
def __init__(self,
image_path: str,
x_position: int, y_position: int,
desired_width: int, desired_height: int) -> None:
self._image_page = image_to_page(
image_path, x_position, y_position, desired_width, desired_height)
self._bounding_box = (x_position, y_position, x_position +
desired_width - 1,
y_position + desired_height - 1)
def stamp(self, page: PageObject) -> None:
page.merge_page(self._image_page)
def add_link(self, writer: PdfWriter, i: int, j: int):
annotation = Link(rect=self._bounding_box, target_page_index=j)
writer.add_annotation(page_number=i, annotation=annotation)
def main() -> None:
writer = PdfWriter()
# Add a title page and "how to play"
writer.add_page(image_to_page("grayscale-1.png", 25, 25, 550, 990))
writer.add_page(
PdfReader("Fairy tale puzzle book interior PRINT_VERSION.pdf").pages[0])
# Next, add the stamps to all puzzle pages
reader = PdfReader("Fairy tale puzzle book interior PRINT_VERSION.pdf")
stamp = Stamp("link_text.png", 495, 15, 100, 50)
back_arrows = [
Stamp("back.png", 278, 388, 20, 20),
Stamp("back.png", 490, 388, 20, 20),
Stamp("back.png", 278, 124, 20, 20),
Stamp("back.png", 490, 124, 20, 20)
]
# Add pages and merge the image to the specified page
skips = [0, 1, 23]
for i, page in enumerate(reader.pages):
if i in skips:
continue
if i < 22:
stamp.stamp(page)
elif i > 22:
for a in back_arrows:
a.stamp(page)
writer.add_page(page)
# Add forward and back annotations
for i in range(2, 22):
stamp.add_link(writer, i, 23 + (i - 2) // 4)
for i in range(23, 28):
offset = 4 * (i - 23) + 2
for j in range(4):
back_arrows[j].add_link(writer, i, offset + j)
# Add bookmarks
writer.add_outline_item("Cover", 0)
writer.add_outline_item("How to play", 1)
parent = writer.add_outline_item("Puzzles", 2)
for i, n in enumerate([
"Cinderella",
"Snow white",
"The emperor's new clothes",
"The Bremen town musicians",
"Little red riding hood",
"The three little pigs",
"The princcess and the pea",
"The ugly duckling",
"The little mermaid",
"Rumplestiltskin",
"Sleeping beauty",
"Hansel and Gretel",
"Rapunzel",
"The magic pen",
"The talking animals",
"Goldilocks and the three bears",
"The gingerbread man",
"The tortoise and the hare",
"Jack and the beanstalk",
"The frog prince",
]):
writer.add_outline_item(n, i + 2, parent)
writer.add_outline_item("Solution", 22)
# Add copyright page
writer.add_page(PdfReader('copyright.pdf').pages[0])
writer.add_outline_item("Copyright", len(writer.pages) - 1)
# Write the output
with open("Fairy tale puzzle book interior.pdf", "wb") as output_file:
writer.write(output_file)
print("DONE")
if __name__ == '__main__':
main()