|
|
|
|
|
""" |
|
|
Main Gradio application for Text-to-Infographics Generator |
|
|
""" |
|
|
import os |
|
|
import logging |
|
|
import gradio as gr |
|
|
from typing import Dict, List, Tuple, Optional |
|
|
import tempfile |
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
from config import Config |
|
|
from src.text_processor import TextProcessor |
|
|
from src.gemini_client import GeminiClient |
|
|
from src.template_manager import TemplateManager |
|
|
from src.layout_engine import LayoutEngine |
|
|
from src.color_palette import ColorPalette |
|
|
from src.image_generator import ImageGenerator |
|
|
from utils.helpers import sanitize_text, validate_content_length, generate_unique_id |
|
|
from examples.sample_texts import get_sample_text, get_all_categories |
|
|
|
|
|
|
|
|
text_processor = TextProcessor() |
|
|
gemini_client = GeminiClient() |
|
|
template_manager = TemplateManager() |
|
|
layout_engine = LayoutEngine() |
|
|
color_palette = ColorPalette() |
|
|
image_generator = ImageGenerator() |
|
|
|
|
|
def generate_infographic(text: str, template_style: str, custom_color: str, |
|
|
layout_type: str, progress=gr.Progress()) -> Tuple[str, str, str]: |
|
|
""" |
|
|
Main function to generate infographic |
|
|
|
|
|
Args: |
|
|
text: Input text content |
|
|
template_style: Selected template style |
|
|
custom_color: Custom primary color |
|
|
layout_type: Layout arrangement type |
|
|
progress: Gradio progress tracker |
|
|
|
|
|
Returns: |
|
|
Tuple of (image_path, status_message, download_file_path) |
|
|
""" |
|
|
try: |
|
|
|
|
|
progress(0.1, desc="Validating input...") |
|
|
|
|
|
if not text or len(text.strip()) < 10: |
|
|
return None, "β Please provide more substantial text content (at least 10 characters)", None |
|
|
|
|
|
|
|
|
text = sanitize_text(text) |
|
|
content_validation = validate_content_length(text) |
|
|
|
|
|
if not content_validation['valid']: |
|
|
return None, f"β {content_validation['message']}", None |
|
|
|
|
|
|
|
|
progress(0.2, desc="Analyzing text content...") |
|
|
logger.info("Starting text analysis") |
|
|
text_analysis = text_processor.analyze_text(text) |
|
|
|
|
|
|
|
|
progress(0.3, desc="Getting AI insights...") |
|
|
logger.info("Getting AI insights from Gemini") |
|
|
enhanced_analysis = gemini_client.analyze_content(text_analysis) |
|
|
|
|
|
|
|
|
if not enhanced_analysis.get('title'): |
|
|
progress(0.35, desc="Generating title...") |
|
|
enhanced_analysis['title'] = gemini_client.generate_title(text) |
|
|
|
|
|
|
|
|
progress(0.4, desc="Applying template styling...") |
|
|
logger.info(f"Applying {template_style} template") |
|
|
styled_content = template_manager.apply_template_to_content( |
|
|
enhanced_analysis, template_style, custom_color, layout_type |
|
|
) |
|
|
|
|
|
|
|
|
progress(0.6, desc="Creating layout...") |
|
|
logger.info("Generating layout") |
|
|
layout_data = layout_engine.create_layout(styled_content) |
|
|
|
|
|
|
|
|
progress(0.7, desc="Optimizing layout...") |
|
|
layout_data = layout_engine.optimize_layout(layout_data) |
|
|
|
|
|
|
|
|
progress(0.8, desc="Generating infographic image...") |
|
|
logger.info("Creating final image") |
|
|
export_data = layout_engine.export_layout_data(layout_data) |
|
|
image_path = image_generator.create_infographic(export_data) |
|
|
|
|
|
|
|
|
progress(0.9, desc="Preparing download...") |
|
|
download_path = _prepare_download_file(image_path, template_style) |
|
|
|
|
|
progress(1.0, desc="Complete!") |
|
|
|
|
|
success_message = f"β
Infographic generated successfully!\nπ Template: {template_style}\nπ Layout: {layout_type}\nπ {len(text.split())} words processed" |
|
|
|
|
|
return image_path, success_message, download_path |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error generating infographic: {e}") |
|
|
error_message = f"β Error generating infographic: {str(e)}" |
|
|
return None, error_message, None |
|
|
|
|
|
def _prepare_download_file(image_path: str, template_style: str) -> str: |
|
|
"""Prepare downloadable file""" |
|
|
try: |
|
|
if not image_path or not os.path.exists(image_path): |
|
|
return None |
|
|
|
|
|
|
|
|
download_filename = f"infographic_{template_style.lower()}_{generate_unique_id()}.png" |
|
|
download_path = os.path.join(tempfile.gettempdir(), download_filename) |
|
|
|
|
|
|
|
|
import shutil |
|
|
shutil.copy2(image_path, download_path) |
|
|
|
|
|
return download_path |
|
|
except Exception as e: |
|
|
logger.error(f"Error preparing download file: {e}") |
|
|
return image_path |
|
|
|
|
|
def load_sample_text(category: str) -> str: |
|
|
"""Load sample text by category""" |
|
|
try: |
|
|
return get_sample_text(category) |
|
|
except Exception as e: |
|
|
logger.error(f"Error loading sample text: {e}") |
|
|
return "" |
|
|
|
|
|
def get_template_info(template_name: str) -> str: |
|
|
"""Get template information""" |
|
|
try: |
|
|
info = template_manager.get_template_preview_data(template_name) |
|
|
if info: |
|
|
description = info.get('description', 'Professional infographic template') |
|
|
best_for = ', '.join(info.get('best_for', ['General use'])) |
|
|
return f"**{template_name}**: {description}\n**Best for**: {best_for}" |
|
|
return f"**{template_name}**: Professional infographic template" |
|
|
except Exception as e: |
|
|
logger.error(f"Error getting template info: {e}") |
|
|
return f"**{template_name}**: Professional template" |
|
|
|
|
|
def create_interface(): |
|
|
"""Create the main Gradio interface""" |
|
|
|
|
|
|
|
|
css = """ |
|
|
.gradio-container { |
|
|
max-width: 1400px !important; |
|
|
margin: auto; |
|
|
} |
|
|
.main-header { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
.feature-box { |
|
|
padding: 1rem; |
|
|
border-radius: 8px; |
|
|
margin: 0.5rem 0; |
|
|
} |
|
|
.status-box { |
|
|
padding: 1rem; |
|
|
border-radius: 8px; |
|
|
margin-top: 1rem; |
|
|
} |
|
|
""" |
|
|
|
|
|
with gr.Blocks( |
|
|
theme=gr.themes.Soft( |
|
|
primary_hue="blue", |
|
|
secondary_hue="gray", |
|
|
neutral_hue="gray", |
|
|
), |
|
|
css=css, |
|
|
title="AI Text-to-Infographics Generator" |
|
|
) as app: |
|
|
|
|
|
|
|
|
gr.HTML(""" |
|
|
<div class="main-header"> |
|
|
<h1>π¨ AI Text-to-Infographics Generator</h1> |
|
|
<p>Transform your text into stunning, professional infographics with the power of AI</p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
|
|
|
with gr.Column(scale=1): |
|
|
gr.Markdown("## π Input Content") |
|
|
|
|
|
|
|
|
with gr.Group(): |
|
|
text_input = gr.Textbox( |
|
|
label="Your Text Content", |
|
|
placeholder="Paste your content here... (articles, reports, data, etc.)", |
|
|
lines=12, |
|
|
max_lines=20, |
|
|
show_label=True |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
sample_category = gr.Dropdown( |
|
|
choices=get_all_categories(), |
|
|
label="Load Sample Text", |
|
|
value="business_report", |
|
|
scale=2 |
|
|
) |
|
|
load_sample_btn = gr.Button("Load Sample", scale=1, size="sm") |
|
|
|
|
|
gr.Markdown("## π¨ Customization") |
|
|
|
|
|
|
|
|
template_choice = gr.Dropdown( |
|
|
choices=Config.TEMPLATES, |
|
|
value="Modern", |
|
|
label="Template Style", |
|
|
info="Choose the visual style for your infographic" |
|
|
) |
|
|
|
|
|
template_info = gr.Markdown( |
|
|
get_template_info("Modern"), |
|
|
elem_classes=["feature-box"] |
|
|
) |
|
|
|
|
|
|
|
|
custom_color = gr.ColorPicker( |
|
|
label="Primary Color", |
|
|
value="#3498db", |
|
|
info="Choose your brand or preferred color" |
|
|
) |
|
|
|
|
|
|
|
|
layout_type = gr.Radio( |
|
|
choices=Config.LAYOUTS, |
|
|
value="Vertical", |
|
|
label="Layout Arrangement", |
|
|
info="How content should be arranged" |
|
|
) |
|
|
|
|
|
|
|
|
generate_btn = gr.Button( |
|
|
"π Generate Infographic", |
|
|
variant="primary", |
|
|
size="lg", |
|
|
scale=1 |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Column(scale=1): |
|
|
gr.Markdown("## πΌοΈ Generated Infographic") |
|
|
|
|
|
|
|
|
output_image = gr.Image( |
|
|
label="Your Infographic", |
|
|
show_label=False, |
|
|
height=600, |
|
|
show_download_button=True |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Group(): |
|
|
status_output = gr.Textbox( |
|
|
label="Generation Status", |
|
|
interactive=False, |
|
|
show_label=True, |
|
|
elem_classes=["status-box"] |
|
|
) |
|
|
|
|
|
download_file = gr.File( |
|
|
label="Download High Resolution", |
|
|
visible=True, |
|
|
show_label=True |
|
|
) |
|
|
|
|
|
|
|
|
gr.Markdown("## π Examples & Tips") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Examples( |
|
|
examples=[ |
|
|
[ |
|
|
get_sample_text("business_report")[:500] + "...", |
|
|
"Corporate", |
|
|
"#2c3e50", |
|
|
"Horizontal" |
|
|
], |
|
|
[ |
|
|
get_sample_text("technology_overview")[:500] + "...", |
|
|
"Modern", |
|
|
"#3498db", |
|
|
"Vertical" |
|
|
], |
|
|
[ |
|
|
get_sample_text("health_wellness")[:500] + "...", |
|
|
"Creative", |
|
|
"#27ae60", |
|
|
"Grid" |
|
|
] |
|
|
], |
|
|
inputs=[text_input, template_choice, custom_color, layout_type], |
|
|
label="Example Configurations" |
|
|
) |
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown(""" |
|
|
### π‘ Tips for Better Results |
|
|
- **Length**: 200-2000 words work best |
|
|
- **Structure**: Use clear paragraphs and sections |
|
|
- **Data**: Include numbers and statistics for visual impact |
|
|
- **Keywords**: Use descriptive keywords for better AI analysis |
|
|
- **Format**: Bullet points and lists enhance visual appeal |
|
|
""") |
|
|
|
|
|
|
|
|
gr.HTML(""" |
|
|
<div style="text-align: center; margin-top: 2rem; padding: 1rem; border-top: 1px solid #eee;"> |
|
|
<p>Built with β€οΈ using <strong>Gradio</strong>, <strong>Google Gemini</strong>, and <strong>Hugging Face Spaces</strong></p> |
|
|
<p><small>Transform your ideas into visual stories β’ Perfect for presentations, social media, and reports</small></p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
|
|
|
generate_btn.click( |
|
|
fn=generate_infographic, |
|
|
inputs=[text_input, template_choice, custom_color, layout_type], |
|
|
outputs=[output_image, status_output, download_file], |
|
|
show_progress=True |
|
|
) |
|
|
|
|
|
load_sample_btn.click( |
|
|
fn=load_sample_text, |
|
|
inputs=[sample_category], |
|
|
outputs=[text_input] |
|
|
) |
|
|
|
|
|
template_choice.change( |
|
|
fn=get_template_info, |
|
|
inputs=[template_choice], |
|
|
outputs=[template_info] |
|
|
) |
|
|
|
|
|
return app |
|
|
|
|
|
def main(): |
|
|
"""Main application entry point""" |
|
|
try: |
|
|
logger.info("Initializing Text-to-Infographics Generator") |
|
|
|
|
|
|
|
|
if not Config.GEMINI_API_KEY: |
|
|
logger.warning("Gemini API key not found. AI features will be limited.") |
|
|
|
|
|
|
|
|
app = create_interface() |
|
|
|
|
|
|
|
|
app.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
share=False, |
|
|
show_error=True |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Failed to launch application: {e}") |
|
|
raise |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |