Files
AI-comic-generator/backend/app/routers/export.py
T

81 lines
3.2 KiB
Python

import shutil
import os
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session
from app.core.database import get_session
from app.models.models import Project
from app.services.image_service import split_comic_page
router = APIRouter()
@router.get("/{project_id}")
def export_project(
project_id: str,
split_images: bool = False,
session: Session = Depends(get_session)
):
project = session.get(Project, project_id)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
# Check if any images generated
has_images = any(item.image_url for item in project.storyboard_items) or any(c.image_url for c in project.characters)
if not has_images:
raise HTTPException(status_code=400, detail="No images generated yet. Cannot export.")
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
project_static_dir = os.path.join(base_dir, "static", project_id)
export_dir = os.path.join(project_static_dir, "export")
if os.path.exists(export_dir):
shutil.rmtree(export_dir)
os.makedirs(export_dir)
# Export Characters
chars_dir = os.path.join(export_dir, "characters")
os.makedirs(chars_dir)
for char in project.characters:
if char.image_url:
# Resolve absolute path from relative URL
# URL: /static/{project_id}/characters/xxx.png
# Path: backend/static/{project_id}/characters/xxx.png
# We can construct it directly if we know the structure, but let's parse url
rel_path = char.image_url.lstrip("/") # static/...
local_path = os.path.join(base_dir, rel_path.replace("/", os.sep))
if os.path.exists(local_path):
shutil.copy(local_path, os.path.join(chars_dir, f"{char.name}.png"))
panels_dir = os.path.join(export_dir, "panels")
if split_images:
os.makedirs(panels_dir)
# Sort items
items = sorted(project.storyboard_items, key=lambda x: x.sequence)
for item in items:
if item.image_url:
rel_path = item.image_url.lstrip("/")
local_path = os.path.join(base_dir, rel_path.replace("/", os.sep))
if os.path.exists(local_path):
shutil.copy(local_path, os.path.join(export_dir, f"comic_part_{item.sequence}.png"))
if split_images:
with open(local_path, "rb") as f:
img_bytes = f.read()
try:
panels = split_comic_page(img_bytes)
for idx, panel_bytes in enumerate(panels):
p_name = f"panel_{item.sequence}_{idx+1}.png"
with open(os.path.join(panels_dir, p_name), "wb") as f:
f.write(panel_bytes)
except Exception as e:
print(f"Failed to split panel {item.id}: {e}")
zip_path_base = os.path.join(project_static_dir, "export_archive")
shutil.make_archive(zip_path_base, 'zip', export_dir)
return {"download_url": f"/static/{project_id}/export_archive.zip"}