Spaces:
Sleeping
Sleeping
File size: 5,779 Bytes
bd57041 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
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 |