File size: 4,195 Bytes
576a588
 
 
 
 
 
 
ca574af
7d83622
 
 
576a588
ca574af
576a588
 
 
 
 
 
 
 
 
 
 
7d83622
 
 
576a588
 
7d83622
 
576a588
7d83622
576a588
 
 
 
7d83622
576a588
 
 
 
 
 
 
7d83622
576a588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7d83622
576a588
 
 
 
 
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
# app.py
"""
Main Streamlit application file for the PDF to Single Image Converter.

Coordinates the UI, file handling, and calls the processing logic.
"""

import streamlit as st
import tempfile
import os
import time
from typing import Optional

# Import functions from our modules
from pdf_processor import pdf_to_single_image
from ui_components import (
    render_sidebar,
    display_file_details,
    display_results,
    render_initial_info,
    display_installation_info
)

# --- Page Configuration ---
st.set_page_config(
    page_title="PDF to Single Image Converter",
    page_icon="πŸ“„",
    layout="centered",  # Can be "wide" or "centered"
    initial_sidebar_state="expanded" # Keep sidebar open initially
)

# --- Main Application ---
st.title("πŸ“„ PDF to Single Image Converter")
st.markdown("Upload a multi-page PDF and convert it into a single, tall image file (PNG or JPG).")

# --- Sidebar ---
dpi_setting, format_setting = render_sidebar()

# --- File Upload ---
# Use a key for the file uploader to potentially reset it later if needed
uploaded_file: Optional[st.runtime.uploaded_file_manager.UploadedFile] = st.file_uploader(
    "Choose a PDF file", type="pdf", key="pdf_uploader"
)

# --- Processing Logic ---
if uploaded_file is not None:
    # Display details of the uploaded file
    display_file_details(uploaded_file)

    # Use a temporary file for robust handling by PyMuPDF
    temp_pdf_path: Optional[str] = None
    try:
        # Create a temporary file to store the uploaded PDF content
        with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
            tmp_file.write(uploaded_file.getvalue())
            temp_pdf_path = tmp_file.name # Store the path

        # Add a button to trigger the conversion
        if st.button(f"πŸš€ Convert to {format_setting}", key="convert_button"):
            if temp_pdf_path: # Ensure temp path is valid
                try:
                    # Show a spinner during processing
                    with st.spinner(f"Converting PDF to {format_setting} at {dpi_setting} DPI... Please wait."):
                        start_time = time.time()

                        # Call the core conversion function from pdf_processor
                        img_buffer = pdf_to_single_image(
                            pdf_path=temp_pdf_path,
                            output_format=format_setting,
                            dpi=dpi_setting
                        )

                        processing_time = time.time() - start_time

                        # Prepare output filename
                        base_filename = os.path.splitext(uploaded_file.name)[0]
                        output_filename = f"{base_filename}_converted.{format_setting.lower()}"

                        # Display the results (download button, preview)
                        if img_buffer.getbuffer().nbytes > 0: # Check if buffer has content
                             display_results(
                                img_buffer=img_buffer,
                                output_filename=output_filename,
                                output_format=format_setting,
                                processing_time=processing_time
                             )
                        else:
                             st.error("Conversion resulted in an empty image. Please check the PDF file.")


                except Exception as e:
                    st.error(f"❌ An error occurred during conversion:")
                    st.exception(e) # Displays the full traceback for debugging

    finally:
        # --- Cleanup ---
        # Ensure the temporary file is deleted after processing or if an error occurs
        if temp_pdf_path and os.path.exists(temp_pdf_path):
            try:
                os.unlink(temp_pdf_path)
                # st.write(f"Temporary file {temp_pdf_path} deleted.") # Optional debug message
            except OSError as e:
                st.warning(f"Could not delete temporary file {temp_pdf_path}: {e}")


else:
    # Show initial instructions if no file is uploaded
    render_initial_info()

# --- Footer / Installation Info ---
display_installation_info()