#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os, sys, shutil, subprocess, tempfile, uuid from pathlib import Path import gradio as gr # Import font installation function from install_fonts import install_fonts_from_repository BASE_DIR = Path(__file__).parent.resolve() BINARY_PATH = BASE_DIR / "PptxToJpgZip" os.chmod(BINARY_PATH, 0o755) # Ignore exceptions def _safe_name() -> str: """Generate ASCII-only temporary filename""" return f"input_{uuid.uuid4().hex}.pptx" def convert_pptx_to_zip(pptx_file) -> str: """Call PptxToJpgZip to convert PPTX to JPG images ZIP; auto-zip if only folder exists.""" tmpdir = Path(tempfile.mkdtemp()) src = tmpdir / _safe_name() shutil.copy(pptx_file.name, src) # Call external executable proc = subprocess.run( [str(BINARY_PATH), str(src)], cwd=tmpdir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) if proc.returncode != 0: raise RuntimeError( f"PptxToJpgZip failed with exit code {proc.returncode}\n" f"stderr:\n{proc.stderr.decode(errors='ignore')}" ) # ---- ① Priority: find *_images.zip ---- zips = list(tmpdir.glob("*_images.zip")) if zips: return str(zips[0]) # ---- ② If no ZIP, find *_images directory and auto-package ---- img_dirs = [p for p in tmpdir.glob("*_images") if p.is_dir()] if img_dirs: folder = img_dirs[0] zip_path = folder.with_suffix(".zip") # _images.zip shutil.make_archive(zip_path.with_suffix(""), "zip", folder) return str(zip_path) # ---- ③ Still not found: list tmpdir contents for debugging ---- contents = "\n".join([" • " + p.name for p in tmpdir.iterdir()]) raise FileNotFoundError( "Output ZIP not found, and no *_images folder discovered.\n" f"Temporary directory contents:\n{contents}" ) # ----------------- Enhanced Gradio UI with English Interface ----------------- # with gr.Blocks( title="PPTX to JPG ZIP Converter", theme=gr.themes.Soft(), css=""" .download-btn { background: linear-gradient(45deg, #4CAF50, #45a049) !important; color: white !important; font-weight: bold !important; font-size: 16px !important; padding: 12px 24px !important; border-radius: 8px !important; border: none !important; box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important; transition: all 0.3s ease !important; } .download-btn:hover { background: linear-gradient(45deg, #45a049, #4CAF50) !important; transform: translateY(-2px) !important; box-shadow: 0 6px 12px rgba(0,0,0,0.3) !important; } .main-container { max-width: 800px; margin: 0 auto; padding: 20px; } .header-section { text-align: center; margin-bottom: 30px; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; color: white; } .instructions-section { background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #007bff; } """ ) as demo: with gr.Column(elem_classes="main-container"): # Header Section with gr.Column(elem_classes="header-section"): gr.Markdown( """ # 🎯 PPTX to JPG ZIP Converter ### Transform your PowerPoint presentations into high-quality JPG images **Fast • Reliable • Easy to Use** """, elem_classes="header-content" ) # Instructions Section with gr.Column(elem_classes="instructions-section"): gr.Markdown( """ ## 📋 How to Use **Step 1:** Click "Upload PPTX File" and select your PowerPoint presentation (.pptx) **Step 2:** Click "🚀 Convert to JPG ZIP" to start the conversion process **Step 3:** Wait for processing to complete (usually takes 10-30 seconds) **Step 4:** Click the green "📥 Download ZIP" button to get your converted images ### ✨ Features - **High Quality**: Converts each slide to crisp JPG images - **Batch Processing**: All slides converted in one go - **ZIP Package**: Convenient download as a single ZIP file - **Font Support**: Automatic font installation for better rendering """ ) # Main Conversion Interface gr.Markdown("## 🔄 Conversion Interface") with gr.Row(): with gr.Column(scale=2): pptx_input = gr.File( label="📁 Upload PPTX File", file_types=[".pptx"], elem_id="pptx_upload" ) with gr.Column(scale=1): convert_btn = gr.Button( "🚀 Convert to JPG ZIP", variant="primary", size="lg", elem_id="convert_button" ) # Download Section gr.Markdown("## 📥 Download Results") with gr.Row(): with gr.Column(scale=2): zip_output = gr.File( label="📦 Converted ZIP File", elem_id="zip_output" ) with gr.Column(scale=1): download_btn = gr.Button( "📥 Download ZIP", variant="secondary", size="lg", elem_classes="download-btn", elem_id="download_button" ) # Status Section with gr.Row(): status_text = gr.Textbox( label="📊 Status", interactive=False, value="📁 Please upload a PPTX file to begin conversion...", elem_id="status_display" ) # Footer Section gr.Markdown( """ --- ### 💡 Tips - **Supported Format**: Only .pptx files (PowerPoint 2007+) - **File Size**: Works best with files under 100MB - **Processing Time**: Depends on slide count and complexity - **Output**: High-resolution JPG images (300 DPI) ### 🔧 Technical Info - **Engine**: PptxToJpgZip binary converter - **Image Format**: JPG (JPEG) - **Compression**: ZIP archive - **Font Rendering**: Enhanced with system fonts """, elem_classes="footer-info" ) # Event Handlers def process_conversion(pptx_file): if pptx_file is None: return None, "❌ Please upload a PPTX file first" try: # Update status yield None, "🔄 Processing your PPTX file..." # Perform conversion result_zip = convert_pptx_to_zip(pptx_file) # Success yield result_zip, "✅ Conversion completed successfully! Click 'Download ZIP' to get your files." except Exception as e: yield None, f"❌ Conversion failed: {str(e)}" def handle_download(zip_file): """Handle download button - create a new downloadable file""" if zip_file and hasattr(zip_file, 'name') and os.path.exists(zip_file.name): return gr.File(value=zip_file.name), "📥 Download started! File will be downloaded automatically." elif zip_file and isinstance(zip_file, str) and os.path.exists(zip_file): return gr.File(value=zip_file), "📥 Download started! File will be downloaded automatically." else: return None, "❌ No file available for download. Please convert a file first." # Connect events convert_btn.click( fn=process_conversion, inputs=[pptx_input], outputs=[zip_output, status_text], show_progress=True ) # Download button - creates a downloadable file output download_output = gr.File(label="Download", visible=False) download_btn.click( fn=handle_download, inputs=[zip_output], outputs=[download_output, status_text], show_progress=False ) if __name__ == "__main__": # Install fonts before starting the application print("🔧 Installing fonts for better rendering...") install_fonts_from_repository() print("✅ Font installation completed!") print("🚀 Starting PPTX to JPG ZIP Converter...") demo.launch( server_name="0.0.0.0", server_port=7860, share=False, show_error=True, quiet=False )