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