{ "cells": [ { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Front pages PDF saved as: booklet_front.pdf\n", "Back pages PDF saved as: booklet_back.pdf\n" ] } ], "source": [ "import math\n", "import io\n", "from PyPDF2 import PdfReader, PdfWriter\n", "\n", "def create_booklet_with_blank_pages(pdf_path, output_front_path, output_back_path):\n", " try:\n", " # Step 1: Read the PDF using the file path\n", " reader = PdfReader(pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Ensure the number of pages is divisible by 4 by adding blank pages if needed\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " # Calculate how many blank pages are needed\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " # Step 3: Add the necessary number of blank pages\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page() # Add a blank page directly\n", "\n", " # Step 4: Write the new PDF with added blank pages to a BytesIO stream\n", " modified_pdf = io.BytesIO()\n", " writer.write(modified_pdf)\n", " modified_pdf.seek(0)\n", "\n", " # Step 5: Create the front and back arrangement for booklet-style printing\n", " modified_reader = PdfReader(modified_pdf)\n", " total_pages = len(modified_reader.pages)\n", "\n", " # Create writers for the front and back pages\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Arrange pages for the front: (e.g., 8 & 1, 6 & 3)\n", " for i in range(total_pages // 4):\n", " front_writer.add_page(modified_reader.pages[total_pages - 1 - (2 * i)])\n", " front_writer.add_page(modified_reader.pages[2 * i])\n", "\n", " # Arrange pages for the back: (e.g., 2 & 7, 4 & 5)\n", " for i in range(total_pages // 4):\n", " back_writer.add_page(modified_reader.pages[2 * i + 1])\n", " back_writer.add_page(modified_reader.pages[total_pages - 2 - (2 * i)])\n", "\n", " # Step 6: Write the front and back PDFs to the specified output paths\n", " with open(output_front_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(output_back_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " print(f\"Front pages PDF saved as: {output_front_path}\")\n", " print(f\"Back pages PDF saved as: {output_back_path}\")\n", "\n", " except Exception as e:\n", " print(f\"Error during PDF processing: {str(e)}\")\n", "\n", "# Example usage\n", "pdf_path = \"input.pdf\" # Replace with your input PDF path\n", "output_front_path = \"booklet_front.pdf\"\n", "output_back_path = \"booklet_back.pdf\"\n", "create_booklet_with_blank_pages(pdf_path, output_front_path, output_back_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## attempt to directly merge the 2 pages together" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Front pages PDF saved as: booklet_front.pdf\n", "Back pages PDF saved as: booklet_back.pdf\n" ] } ], "source": [ "import tempfile\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " # Create a new blank page with double width to place the two pages side by side\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", "\n", " # Merge page1 on the left side\n", " new_page.merge_page(page1)\n", "\n", " # Translate page2 to the right by the width of page1\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width\n", "\n", " # Merge the translated page2 onto the new page\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path):\n", " try:\n", " # Step 1: Read the PDF using the file path\n", " reader = PdfReader(pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Ensure the number of pages is divisible by 4 by adding blank pages if needed\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " # Calculate how many blank pages are needed\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " # Step 3: Add the necessary number of blank pages\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page() # Add a blank page directly\n", "\n", " # Step 4: Write the new PDF with added blank pages to a temporary file\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " # Read the modified PDF back\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " # Create writers for the front and back pages\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Arrange pages for the front: (e.g., 8 & 1, 6 & 3)\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " # Arrange pages for the back: (e.g., 2 & 7, 4 & 5)\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Step 5: Write the front and back PDFs to the specified output paths\n", " with open(output_front_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(output_back_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " print(f\"Front pages PDF saved as: {output_front_path}\")\n", " print(f\"Back pages PDF saved as: {output_back_path}\")\n", "\n", " except Exception as e:\n", " print(f\"Error during PDF processing: {str(e)}\")\n", "\n", "# Example usage\n", "pdf_path = \"input.pdf\" # Replace with your input PDF path\n", "output_front_path = \"booklet_front.pdf\"\n", "output_back_path = \"booklet_back.pdf\"\n", "create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Booklet with reverse and normal back" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Front pages PDF saved as: booklet_front.pdf\n", "Back pages PDF saved as: booklet_back.pdf\n", "Reversed PDF saved as: reversed_booklet_back.pdf\n" ] } ], "source": [ "import tempfile\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " # Create a new blank page with double width to place the two pages side by side\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", "\n", " # Merge page1 on the left side\n", " new_page.merge_page(page1)\n", "\n", " # Translate page2 to the right by the width of page1\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width\n", "\n", " # Merge the translated page2 onto the new page\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def reverse_pdf(input_pdf_path, output_pdf_path):\n", " \"\"\"\n", " Reverses the order of pages in a PDF.\n", " \"\"\"\n", " try:\n", " # Step 1: Read the PDF using the file path\n", " reader = PdfReader(input_pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Create a writer and add pages in reverse order\n", " writer = PdfWriter()\n", " for page_num in reversed(range(total_pages)):\n", " writer.add_page(reader.pages[page_num])\n", "\n", " # Step 3: Write the reversed pages to the new PDF\n", " with open(output_pdf_path, \"wb\") as output_file:\n", " writer.write(output_file)\n", "\n", " print(f\"Reversed PDF saved as: {output_pdf_path}\")\n", "\n", " except Exception as e:\n", " print(f\"Error during PDF reversing: {str(e)}\")\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path, output_reversed_back_path):\n", " try:\n", " # Step 1: Read the PDF using the file path\n", " reader = PdfReader(pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Ensure the number of pages is divisible by 4 by adding blank pages if needed\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " # Calculate how many blank pages are needed\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " # Step 3: Add the necessary number of blank pages\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page() # Add a blank page directly\n", "\n", " # Step 4: Write the new PDF with added blank pages to a temporary file\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " # Read the modified PDF back\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " # Create writers for the front and back pages\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Arrange pages for the front: (e.g., 8 & 1, 6 & 3)\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " # Arrange pages for the back: (e.g., 2 & 7, 4 & 5)\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Step 5: Write the front and back PDFs to the specified output paths\n", " with open(output_front_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(output_back_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " print(f\"Front pages PDF saved as: {output_front_path}\")\n", " print(f\"Back pages PDF saved as: {output_back_path}\")\n", "\n", " # Step 6: Reverse the back PDF pages\n", " reverse_pdf(output_back_path, output_reversed_back_path)\n", "\n", " except Exception as e:\n", " print(f\"Error during PDF processing: {str(e)}\")\n", "\n", "# Example usage\n", "pdf_path = \"Calculus_Module.pdf\" # Replace with your input PDF path\n", "output_front_path = \"booklet_front.pdf\"\n", "output_back_path = \"booklet_back.pdf\"\n", "output_reversed_back_path = \"reversed_booklet_back.pdf\"\n", "create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path, output_reversed_back_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Booklet Reversed Back" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Front pages PDF saved as: booklet_front.pdf\n", "Back pages PDF (already reversed) saved as: booklet_back.pdf\n" ] } ], "source": [ "import tempfile\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " # Create a new blank page with double width to place the two pages side by side\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", "\n", " # Merge page1 on the left side\n", " new_page.merge_page(page1)\n", "\n", " # Translate page2 to the right by the width of page1\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width\n", "\n", " # Merge the translated page2 onto the new page\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path):\n", " try:\n", " # Step 1: Read the PDF using the file path\n", " reader = PdfReader(pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Ensure the number of pages is divisible by 4 by adding blank pages if needed\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " # Calculate how many blank pages are needed\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " # Step 3: Add the necessary number of blank pages\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page() # Add a blank page directly\n", "\n", " # Step 4: Write the new PDF with added blank pages to a temporary file\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " # Read the modified PDF back\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " # Create writers for the front and back pages\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Arrange pages for the front: (e.g., 8 & 1, 6 & 3)\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " # Arrange pages for the back, but in reverse order directly: (e.g., 2 & 7, 4 & 5)\n", " for i in reversed(range(total_pages // 4)):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", "\n", " # Merge the two pages onto one sheet\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Step 5: Write the front and reversed back PDFs to the specified output paths\n", " with open(output_front_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(output_back_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " print(f\"Front pages PDF saved as: {output_front_path}\")\n", " print(f\"Back pages PDF (already reversed) saved as: {output_back_path}\")\n", "\n", " except Exception as e:\n", " print(f\"Error during PDF processing: {str(e)}\")\n", "\n", "# Example usage\n", "pdf_path = \"input.pdf\" # Replace with your input PDF path\n", "output_front_path = \"booklet_front.pdf\"\n", "output_back_path = \"booklet_back.pdf\"\n", "create_booklet_with_two_pages_per_sheet(pdf_path, output_front_path, output_back_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# With UI" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/nicoaspra/Documents/Professor/Jupyter Notebook/venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7860\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/nicoaspra/Documents/Professor/Jupyter Notebook/venv/lib/python3.12/site-packages/gradio/analytics.py:106: UserWarning: IMPORTANT: You are using gradio version 4.37.1, however version 5.0.1 is available, please upgrade. \n", "--------\n", " warnings.warn(\n" ] } ], "source": [ "import tempfile\n", "import shutil\n", "import gradio as gr\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", " new_page.merge_page(page1)\n", "\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0])\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_file):\n", " try:\n", " # Step 1: Read the PDF from the uploaded file\n", " reader = PdfReader(pdf_file)\n", " total_pages = len(reader.pages)\n", "\n", " # Step 2: Ensure the number of pages is divisible by 4 by adding blank pages if needed\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page()\n", "\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " for i in reversed(range(total_pages // 4)):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Save the front and back files with fixed names\n", " front_pdf_path = \"booklet_front.pdf\"\n", " back_pdf_path = \"booklet_back.pdf\"\n", "\n", " with open(front_pdf_path, \"wb\") as front_pdf_file:\n", " front_writer.write(front_pdf_file)\n", "\n", " with open(back_pdf_path, \"wb\") as back_pdf_file:\n", " back_writer.write(back_pdf_file)\n", "\n", " return front_pdf_path, back_pdf_path\n", "\n", " except Exception as e:\n", " return str(e), None\n", "\n", "# Gradio UI\n", "def gradio_interface():\n", " with gr.Blocks() as demo:\n", " gr.Markdown(\"## Booklet Creator\")\n", " \n", " with gr.Row():\n", " pdf_input = gr.File(label=\"Upload PDF\", type=\"filepath\", file_types=[\".pdf\"])\n", " \n", " with gr.Row():\n", " generate_button = gr.Button(\"Generate Booklet\")\n", " \n", " with gr.Row():\n", " front_pdf_output = gr.File(label=\"Download Booklet Front PDF\")\n", " back_pdf_output = gr.File(label=\"Download Booklet Back PDF\")\n", " \n", " # Button action\n", " generate_button.click(\n", " create_booklet_with_two_pages_per_sheet,\n", " inputs=[pdf_input],\n", " outputs=[front_pdf_output, back_pdf_output]\n", " )\n", "\n", " gr.Markdown(\"---\")\n", " gr.Markdown(\"Developed by **Aspra, N.**\")\n", " \n", " return demo\n", "\n", "# Run the Gradio interface\n", "gradio_interface().launch()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## with UI and reversed front and back" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "* Running on local URL: http://127.0.0.1:7860\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "name": "stderr", "output_type": "stream", "text": [ "Traceback (most recent call last):\n", " File \"/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/gradio/queueing.py\", line 624, in process_events\n", " response = await route_utils.call_process_api(\n", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", " ...<5 lines>...\n", " )\n", " ^\n", " File \"/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/gradio/route_utils.py\", line 323, in call_process_api\n", " output = await app.get_blocks().process_api(\n", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", " ...<11 lines>...\n", " )\n", " ^\n", " File \"/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/gradio/blocks.py\", line 2025, in process_api\n", " data = await self.postprocess_data(block_fn, result[\"prediction\"], state)\n", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", " File \"/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/gradio/blocks.py\", line 1831, in postprocess_data\n", " prediction_value = block.postprocess(prediction_value)\n", " File \"/Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/gradio/components/file.py\", line 220, in postprocess\n", " size=Path(value).stat().st_size,\n", " ~~~~~~~~~~~~~~~~^^\n", " File \"/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/pathlib/_local.py\", line 515, in stat\n", " return os.stat(self, follow_symlinks=follow_symlinks)\n", " ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", "FileNotFoundError: [Errno 2] No such file or directory: \"Invalid Elementary Object starting with b'b' @7: b'3\\\\n%\\\\xc4\\\\xe5\\\\xf2\\\\xe5\\\\xeb\\\\xa7\\\\xf3\\\\xa0\\\\xd0\\\\xc4\\\\xc6\\\\n3 0 obj\\\\n<< /Filter /FlateDecode /Length 3454 >>\\\\nstream\\\\nx\\\\x01\\\\xadZ\\\\xcb\\\\x8e\\\\x1d\\\\xb7\\\\x11\\\\xdd'\"\n" ] } ], "source": [ "import tempfile\n", "import gradio as gr\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", " new_page.merge_page(page1)\n", "\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width\n", "\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def reverse_pdf(input_pdf_path, output_pdf_path):\n", " \"\"\"\n", " Reverses the order of pages in a PDF.\n", " \"\"\"\n", " try:\n", " reader = PdfReader(input_pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " writer = PdfWriter()\n", " for page_num in reversed(range(total_pages)):\n", " writer.add_page(reader.pages[page_num])\n", "\n", " with open(output_pdf_path, \"wb\") as output_file:\n", " writer.write(output_file)\n", "\n", " return output_pdf_path\n", "\n", " except Exception as e:\n", " return str(e)\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_file):\n", " try:\n", " reader = PdfReader(pdf_file)\n", " total_pages = len(reader.pages)\n", "\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page()\n", "\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Create front pages\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " # Create back pages\n", " for i in reversed(range(total_pages // 4)):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Save front and back PDFs\n", " front_pdf_path = \"booklet_front.pdf\"\n", " back_pdf_path = \"booklet_back.pdf\"\n", " reversed_back_pdf_path = \"reversed_booklet_back.pdf\"\n", " reversed_front_pdf_path = \"reversed_booklet_front.pdf\"\n", "\n", " with open(front_pdf_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(back_pdf_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " # Reverse the back and front PDF pages and save\n", " reverse_pdf(back_pdf_path, reversed_back_pdf_path)\n", " reverse_pdf(front_pdf_path, reversed_front_pdf_path)\n", "\n", " return front_pdf_path, back_pdf_path, reversed_front_pdf_path, reversed_back_pdf_path\n", "\n", " except Exception as e:\n", " return str(e), None, None, None\n", "\n", "# Gradio UI\n", "def gradio_interface():\n", " with gr.Blocks() as demo:\n", " gr.Markdown(\"## Booklet Creator and Page Reverser\")\n", "\n", " with gr.Row():\n", " pdf_input = gr.File(label=\"Upload PDF\", type=\"filepath\", file_types=[\".pdf\"])\n", "\n", " with gr.Row():\n", " generate_button = gr.Button(\"Generate Booklet\")\n", "\n", " with gr.Row():\n", " front_pdf_output = gr.File(label=\"Download Booklet Front PDF\")\n", " back_pdf_output = gr.File(label=\"Download Booklet Back PDF\")\n", " with gr.Row():\n", " reversed_front_pdf_output = gr.File(label=\"Download Reversed Booklet Front PDF\")\n", " reversed_back_pdf_output = gr.File(label=\"Download Reversed Booklet Back PDF\")\n", "\n", " # Button action\n", " generate_button.click(\n", " create_booklet_with_two_pages_per_sheet,\n", " inputs=[pdf_input],\n", " outputs=[front_pdf_output, back_pdf_output, reversed_front_pdf_output, reversed_back_pdf_output]\n", " )\n", "\n", " return demo\n", "\n", "# Run the Gradio interface\n", "gradio_interface().launch()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Streamlit" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-04-22 14:42:46.429 WARNING streamlit.runtime.scriptrunner_utils.script_run_context: Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.508 \n", " \u001b[33m\u001b[1mWarning:\u001b[0m to view this Streamlit app on a browser, run it with the following\n", " command:\n", "\n", " streamlit run /Users/nicoaspra/Documents/Professor/Jupyter Notebook/.venv/lib/python3.13/site-packages/ipykernel_launcher.py [ARGUMENTS]\n", "2025-04-22 14:42:46.508 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.508 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.508 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.508 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.509 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n", "2025-04-22 14:42:46.510 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.\n" ] } ], "source": [ "import tempfile\n", "from PyPDF2 import PdfReader, PdfWriter, PageObject\n", "import streamlit as st\n", "\n", "def merge_two_pages_on_one(page1, page2):\n", " \"\"\"\n", " Merges two PDF pages into a single PDF page (side by side).\n", " \"\"\"\n", " width = page1.mediabox.width + page2.mediabox.width\n", " height = max(page1.mediabox.height, page2.mediabox.height)\n", " \n", " new_page = PageObject.create_blank_page(width=width, height=height)\n", " new_page.merge_page(page1)\n", "\n", " page2_content = PageObject.create_blank_page(width=width, height=height)\n", " page2_content.merge_page(page2)\n", " page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width\n", "\n", " new_page.merge_page(page2_content)\n", "\n", " return new_page\n", "\n", "def reverse_pdf(input_pdf_path, output_pdf_path):\n", " \"\"\"\n", " Reverses the order of pages in a PDF.\n", " \"\"\"\n", " try:\n", " reader = PdfReader(input_pdf_path)\n", " total_pages = len(reader.pages)\n", "\n", " writer = PdfWriter()\n", " for page_num in reversed(range(total_pages)):\n", " writer.add_page(reader.pages[page_num])\n", "\n", " with open(output_pdf_path, \"wb\") as output_file:\n", " writer.write(output_file)\n", "\n", " return output_pdf_path\n", "\n", " except Exception as e:\n", " return str(e)\n", "\n", "def create_booklet_with_two_pages_per_sheet(pdf_file):\n", " try:\n", " reader = PdfReader(pdf_file)\n", " total_pages = len(reader.pages)\n", "\n", " writer = PdfWriter()\n", " for page in reader.pages:\n", " writer.add_page(page)\n", "\n", " remainder = total_pages % 4\n", " blank_pages_needed = (4 - remainder) if remainder > 0 else 0\n", "\n", " for _ in range(blank_pages_needed):\n", " writer.add_blank_page()\n", "\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf_file:\n", " writer.write(temp_pdf_file)\n", " temp_pdf_path = temp_pdf_file.name\n", "\n", " modified_reader = PdfReader(temp_pdf_path)\n", " total_pages = len(modified_reader.pages)\n", "\n", " front_writer = PdfWriter()\n", " back_writer = PdfWriter()\n", "\n", " # Create front pages\n", " for i in range(total_pages // 4):\n", " page1 = modified_reader.pages[total_pages - 1 - (2 * i)]\n", " page2 = modified_reader.pages[2 * i]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " front_writer.add_page(merged_page)\n", "\n", " # Create back pages\n", " for i in reversed(range(total_pages // 4)):\n", " page1 = modified_reader.pages[2 * i + 1]\n", " page2 = modified_reader.pages[total_pages - 2 - (2 * i)]\n", " merged_page = merge_two_pages_on_one(page1, page2)\n", " back_writer.add_page(merged_page)\n", "\n", " # Save front and back PDFs\n", " front_pdf_path = \"booklet_front.pdf\"\n", " back_pdf_path = \"booklet_back.pdf\"\n", " reversed_back_pdf_path = \"reversed_booklet_back.pdf\"\n", " reversed_front_pdf_path = \"reversed_booklet_front.pdf\"\n", "\n", " with open(front_pdf_path, \"wb\") as front_file:\n", " front_writer.write(front_file)\n", "\n", " with open(back_pdf_path, \"wb\") as back_file:\n", " back_writer.write(back_file)\n", "\n", " # Reverse the back and front PDF pages and save\n", " reverse_pdf(back_pdf_path, reversed_back_pdf_path)\n", " reverse_pdf(front_pdf_path, reversed_front_pdf_path)\n", "\n", " return front_pdf_path, back_pdf_path, reversed_front_pdf_path, reversed_back_pdf_path\n", "\n", " except Exception as e:\n", " return str(e), None, None, None\n", "\n", "# Streamlit UI\n", "st.title(\"Booklet Creator and Page Reverser\")\n", "\n", "uploaded_file = st.file_uploader(\"Upload PDF\", type=[\"pdf\"])\n", "\n", "if uploaded_file is not None:\n", " with tempfile.NamedTemporaryFile(delete=False, suffix=\".pdf\") as temp_pdf:\n", " temp_pdf.write(uploaded_file.read())\n", " temp_pdf_path = temp_pdf.name\n", "\n", " if st.button(\"Generate Booklet\"):\n", " front_pdf_path, back_pdf_path, reversed_front_pdf_path, reversed_back_pdf_path = create_booklet_with_two_pages_per_sheet(temp_pdf_path)\n", "\n", " if front_pdf_path and back_pdf_path:\n", " st.success(\"Booklet generated successfully!\")\n", " st.download_button(\"Download Booklet Front PDF\", open(front_pdf_path, \"rb\"), \"booklet_front.pdf\")\n", " st.download_button(\"Download Booklet Back PDF\", open(back_pdf_path, \"rb\"), \"booklet_back.pdf\")\n", " st.download_button(\"Download Reversed Booklet Front PDF\", open(reversed_front_pdf_path, \"rb\"), \"reversed_booklet_front.pdf\")\n", " st.download_button(\"Download Reversed Booklet Back PDF\", open(reversed_back_pdf_path, \"rb\"), \"reversed_booklet_back.pdf\")\n", " else:\n", " st.error(\"An error occurred while generating the booklet.\")" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" } }, "nbformat": 4, "nbformat_minor": 2 }