81 lines
3.2 KiB
Python
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"}
|