tsphan's picture
breaks away from single file
576a588
# 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()