Spaces:
Sleeping
Sleeping
# ui_components.py | |
""" | |
Defines functions for creating distinct UI sections of the Streamlit application. | |
""" | |
import streamlit as st | |
from typing import Tuple, Dict, Any, Optional | |
from PIL import Image | |
import io | |
# Constants | |
MAX_PREVIEW_HEIGHT = 10000 # Maximum height in pixels for full-size preview | |
def render_sidebar() -> Tuple[int, str]: | |
""" | |
Renders the sidebar UI elements for settings. | |
Returns | |
------- | |
Tuple[int, str] | |
A tuple containing: | |
- dpi (int): The selected resolution in DPI. | |
- output_format (str): The selected output format ('PNG' or 'JPG'). | |
""" | |
with st.sidebar: | |
st.header("βοΈ Settings") | |
# DPI Slider | |
dpi = st.slider( | |
"Resolution (DPI)", | |
min_value=72, | |
max_value=600, | |
value=300, | |
step=1, | |
help="Dots Per Inch. Higher DPI means better quality but larger file size and longer processing time." | |
) | |
# Output Format Radio Buttons | |
output_format = st.radio( | |
"Output Format", | |
["PNG", "JPG"], | |
index=0, # Default to PNG | |
help="PNG offers lossless quality (larger file). JPG uses lossy compression (smaller file)." | |
) | |
st.write("---") | |
st.write("### About") | |
st.info( | |
"This app converts multi-page PDFs into a single, vertically stitched image file. " | |
"Useful for sharing or archiving documents as images." | |
) | |
st.write("Made with β€οΈ using [Streamlit](https://streamlit.io) & [PyMuPDF](https://pymupdf.readthedocs.io/en/latest/)") | |
st.write("Tim might be a π§") | |
# A little fun :) | |
# st.write("Tim might be a π§") # Uncomment if desired | |
return dpi, output_format | |
def display_file_details(uploaded_file: st.runtime.uploaded_file_manager.UploadedFile) -> None: | |
""" | |
Displays details of the uploaded file. | |
Parameters | |
---------- | |
uploaded_file : st.runtime.uploaded_file_manager.UploadedFile | |
The file uploaded by the user via st.file_uploader. | |
""" | |
file_details = { | |
"Filename": uploaded_file.name, | |
"Type": uploaded_file.type, | |
"Size": f"{uploaded_file.size / (1024*1024):.2f} MB" # Show size in MB | |
} | |
st.write("### File Details") | |
# Use columns for better layout | |
col1, col2 = st.columns(2) | |
with col1: | |
st.write(f"**Filename:**") | |
st.write(f"**Type:**") | |
st.write(f"**Size:**") | |
with col2: | |
st.write(f"{file_details['Filename']}") | |
st.write(f"{file_details['Type']}") | |
st.write(f"{file_details['Size']}") | |
def display_results( | |
img_buffer: io.BytesIO, | |
output_filename: str, | |
output_format: str, | |
processing_time: float | |
) -> None: | |
""" | |
Displays the conversion results: success message, download button, and image preview. | |
Parameters | |
---------- | |
img_buffer : io.BytesIO | |
The buffer containing the generated image data. | |
output_filename : str | |
The suggested filename for the downloaded image. | |
output_format : str | |
The format of the output image ('PNG' or 'JPG'). | |
processing_time : float | |
The time taken for the conversion process in seconds. | |
""" | |
st.success(f"β Conversion completed in {processing_time:.2f} seconds!") | |
# Determine MIME type based on format | |
mime_type = f"image/{output_format.lower()}" | |
# Provide download button | |
st.download_button( | |
label=f"β¬οΈ Download {output_format} Image", | |
data=img_buffer, | |
file_name=output_filename, | |
mime=mime_type | |
) | |
# Image preview section | |
st.write("---") | |
st.write("### πΌοΈ Image Preview") | |
try: | |
# Open image from buffer for preview | |
img = Image.open(img_buffer) | |
width, height = img.size | |
st.write(f"**Image dimensions:** {width}x{height} pixels") | |
# Warn and scale down preview if the image is excessively tall | |
if height > MAX_PREVIEW_HEIGHT: | |
st.warning(f"β οΈ Image is very tall ({height}px). Preview is scaled down.") | |
# Calculate width based on a max preview width (e.g., 800px) to maintain aspect ratio | |
preview_width = min(width, 800) | |
st.image(img, caption=f"Scaled Preview of {output_filename}", width=preview_width) | |
else: | |
# Show image using Streamlit's default width handling or a fixed width | |
st.image(img, caption=f"Preview of {output_filename}", use_column_width='auto') | |
except Exception as e: | |
st.error(f"Could not display image preview: {e}") | |
st.warning("The image file might be corrupted or too large for preview.") | |
def render_initial_info() -> None: | |
""" | |
Displays the initial instructions and placeholder content when no file is uploaded. | |
""" | |
st.info("π Upload a PDF file using the sidebar to get started.") | |
st.write("---") | |
# Placeholder or example section (optional) | |
# st.write("### Example Output Structure") | |
# st.image("https://via.placeholder.com/600x800/ccc/888?text=Page+1", caption="Page 1") | |
# st.image("https://via.placeholder.com/600x800/eee/777?text=Page+2", caption="Page 2") | |
# st.caption("...(Pages are stitched vertically)") | |
def display_installation_info() -> None: | |
"""Displays the installation requirements and run command.""" | |
st.write("---") | |
with st.expander("π οΈ Installation & Usage"): | |
st.code(""" | |
# 1. Install required libraries | |
pip install streamlit Pillow PyMuPDF | |
# 2. Save the code files (app.py, pdf_processor.py, ui_components.py) | |
# in the same directory. | |
# 3. Run the Streamlit application | |
streamlit run app.py | |
""", language="bash") | |