Create_PDF_Booklet / ui_PDF_booklet.py
nicoaspra
footer, title
bd57041
import io
from PyPDF2 import PdfReader, PdfWriter, PageObject
import streamlit as st
def validate_pdf(file_stream):
"""
Validates if the file is a proper PDF by trying to read it.
"""
try:
PdfReader(file_stream)
return True
except Exception:
return False
def merge_two_pages_on_one(page1, page2):
"""
Merges two PDF pages into a single PDF page (side by side).
"""
width = page1.mediabox.width + page2.mediabox.width
height = max(page1.mediabox.height, page2.mediabox.height)
new_page = PageObject.create_blank_page(width=width, height=height)
new_page.merge_page(page1)
page2_content = PageObject.create_blank_page(width=width, height=height)
page2_content.merge_page(page2)
page2_content.add_transformation([1, 0, 0, 1, page1.mediabox.width, 0]) # x translation by page1 width
new_page.merge_page(page2_content)
return new_page
def reverse_pdf(input_pdf_stream):
"""
Reverses the order of pages in a PDF and returns the reversed file stream.
"""
reader = PdfReader(input_pdf_stream)
writer = PdfWriter()
for page_num in reversed(range(len(reader.pages))):
writer.add_page(reader.pages[page_num])
output_stream = io.BytesIO()
writer.write(output_stream)
output_stream.seek(0)
return output_stream
def create_booklet_with_two_pages_per_sheet(pdf_file):
"""
Processes the uploaded PDF to create a booklet with two pages per sheet.
"""
input_pdf_stream = io.BytesIO(pdf_file.read())
# Validate the PDF file
if not validate_pdf(input_pdf_stream):
raise ValueError("Uploaded file is not a valid PDF.")
input_pdf_stream.seek(0)
reader = PdfReader(input_pdf_stream)
total_pages = len(reader.pages)
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
remainder = total_pages % 4
blank_pages_needed = (4 - remainder) if remainder > 0 else 0
for _ in range(blank_pages_needed):
writer.add_blank_page()
temp_pdf_stream = io.BytesIO()
writer.write(temp_pdf_stream)
temp_pdf_stream.seek(0)
modified_reader = PdfReader(temp_pdf_stream)
total_pages = len(modified_reader.pages)
front_writer = PdfWriter()
back_writer = PdfWriter()
# Create front pages
for i in range(total_pages // 4):
page1 = modified_reader.pages[total_pages - 1 - (2 * i)]
page2 = modified_reader.pages[2 * i]
merged_page = merge_two_pages_on_one(page1, page2)
front_writer.add_page(merged_page)
# Create back pages
for i in reversed(range(total_pages // 4)):
page1 = modified_reader.pages[2 * i + 1]
page2 = modified_reader.pages[total_pages - 2 - (2 * i)]
merged_page = merge_two_pages_on_one(page1, page2)
back_writer.add_page(merged_page)
# Prepare output streams
front_pdf_stream = io.BytesIO()
back_pdf_stream = io.BytesIO()
reversed_front_pdf_stream = io.BytesIO()
reversed_back_pdf_stream = io.BytesIO()
front_writer.write(front_pdf_stream)
back_writer.write(back_pdf_stream)
front_pdf_stream.seek(0)
back_pdf_stream.seek(0)
# Reverse PDFs
reversed_front_pdf_stream = reverse_pdf(front_pdf_stream)
reversed_back_pdf_stream = reverse_pdf(back_pdf_stream)
return front_pdf_stream, back_pdf_stream, reversed_front_pdf_stream, reversed_back_pdf_stream
# Streamlit UI
# st.title("Booklet Generator: Create Print-Ready PDFs")
st.title("Print-Ready PDF Booklet Generator")
st.write("""
This tool simplifies the process of creating booklet-style PDFs. It generates booklet-ready files designed for back-to-back printing. Additionally, it provides multiple versions, including reversed formats, to accommodate all printer configurations seamlessly.
Ideal for printing books, modules, and other documents, this tool specifically helps save paper while ensuring efficient, professional-quality results.
""")
# Initialize session state
if "pdf_outputs" not in st.session_state:
st.session_state["pdf_outputs"] = None
uploaded_file = st.file_uploader("Upload PDF", type=["pdf"])
if uploaded_file is not None and st.button("Generate Booklet"):
with st.spinner("Processing..."):
try:
front_pdf, back_pdf, reversed_front_pdf, reversed_back_pdf = create_booklet_with_two_pages_per_sheet(uploaded_file)
st.session_state["pdf_outputs"] = {
"front_pdf": front_pdf,
"back_pdf": back_pdf,
"reversed_front_pdf": reversed_front_pdf,
"reversed_back_pdf": reversed_back_pdf,
}
st.success("Booklet generated successfully!")
except Exception as e:
st.error(f"Error: {str(e)}")
# Add a separator before downloads
st.divider() # Adds a horizontal line
# Display download buttons if PDFs are available
if st.session_state["pdf_outputs"] is not None:
outputs = st.session_state["pdf_outputs"]
st.download_button("Download Booklet Front PDF", outputs["front_pdf"], "booklet_front.pdf", "application/pdf")
st.download_button("Download Booklet Back PDF", outputs["back_pdf"], "booklet_back.pdf", "application/pdf")
st.download_button("Download Reversed Booklet Front PDF", outputs["reversed_front_pdf"], "reversed_booklet_front.pdf", "application/pdf")
st.download_button("Download Reversed Booklet Back PDF", outputs["reversed_back_pdf"], "reversed_booklet_back.pdf", "application/pdf")
# Add footer
st.markdown("""
---
<div style="text-align: center; font-size: small;">
Developed by <strong>Aspra, N.</strong> | © 2025 All Rights Reserved
</div>
""", unsafe_allow_html=True)
# streamlit run 241009_PDF_booklet/ui_PDF_booklet.py