# 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")