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()