Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@

### 5. 可自由编辑的pptx导出(Beta迭代中)
- **导出图像为高还原度、背景干净的、可自由编辑图像和文字的PPT页面**
- 可在导出前勾选「仅文字层可编辑」,生成只抹除文字的底图并让识别出的文字变成可编辑文本框;系统会用 VLM 复核底图文字是否抹除,失败时自动重试并选择漏抹最少的版本(默认不勾选)。
- 相关更新见 https://github.com/Anionex/banana-slides/issues/121
<img width="1000" alt="image" src="https://github.com/user-attachments/assets/a85d2d48-1966-4800-a4bf-73d17f914062" />

Expand Down
1 change: 1 addition & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ No longer restricted by complex menu buttons, issue modification commands direct
### 5. Freely Editable PPTX Export (In Beta)

- **Export images as high-fidelity, clean-background PPT pages with freely editable images and text**
- Enable **Only Text Layers Editable** before export to generate a text-erased background while making only detected text editable. VLM verification checks whether the background still contains text; Banana Slides retries failed erasures and keeps the candidate with the fewest missed text regions. This option is off by default.
- For related updates, see https://github.com/Anionex/banana-slides/issues/121
<img width="1000" alt="image" src="https://github.com/user-attachments/assets/a85d2d48-1966-4800-a4bf-73d17f914062" />

Expand Down
52 changes: 35 additions & 17 deletions backend/controllers/export_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import time
import zipfile
from pathlib import Path
from datetime import datetime

from flask import Blueprint, request, current_app
from werkzeug.utils import secure_filename
Expand Down Expand Up @@ -384,7 +385,8 @@ def export_editable_pptx(project_id):
"filename": "optional_custom_name.pptx",
"page_ids": ["id1", "id2"], // 可选,要导出的页面ID列表(不提供则导出所有)
"max_depth": 1, // 可选,递归深度(默认1=不递归,2=递归一层)
"max_workers": 4 // 可选,并发数(默认4)
"max_workers": 4, // 可选,并发数(默认4)
"text_only": false // 可选,仅让文字层可编辑,默认false
}

Returns:
Expand Down Expand Up @@ -433,6 +435,7 @@ def export_editable_pptx(project_id):
# max_depth 语义:1=只处理表层不递归,2=递归一层(处理图片/图表中的子元素)
max_depth = data.get('max_depth', 1) # 默认不递归,与测试脚本一致
max_workers = data.get('max_workers', 4)
text_only = data.get('text_only', False)

# Validate parameters
# max_depth >= 1: 至少处理表层元素
Expand All @@ -441,6 +444,9 @@ def export_editable_pptx(project_id):

if not isinstance(max_workers, int) or max_workers < 1 or max_workers > 16:
return bad_request("max_workers must be an integer between 1 and 16")

if not isinstance(text_only, bool):
return bad_request("text_only must be a boolean")

# Create task record
task = Task(
Expand All @@ -451,7 +457,10 @@ def export_editable_pptx(project_id):
db.session.add(task)
db.session.commit()

logger.info(f"Created export task {task.id} for project {project_id} (recursive analysis: depth={max_depth}, workers={max_workers})")
logger.info(
f"Created export task {task.id} for project {project_id} "
f"(recursive analysis: depth={max_depth}, workers={max_workers}, text_only={text_only})"
)

# Get services
from services.file_service import FileService
Expand All @@ -476,20 +485,28 @@ def export_editable_pptx(project_id):
)

# 使用递归分析任务(不需要 ai_service,使用 ImageEditabilityService)
task_manager.submit_task(
task.id,
export_editable_pptx_with_recursive_analysis_task,
project_id=project_id,
filename=filename,
file_service=file_service,
page_ids=selected_page_ids if selected_page_ids else None,
max_depth=max_depth,
max_workers=max_workers,
export_extractor_method=export_extractor_method,
export_inpaint_method=export_inpaint_method,
enable_icon_subject_extraction=enable_icon_subject_extraction,
app=app
)
try:
task_manager.submit_task(
task.id,
export_editable_pptx_with_recursive_analysis_task,
project_id=project_id,
filename=filename,
file_service=file_service,
page_ids=selected_page_ids if selected_page_ids else None,
max_depth=max_depth,
max_workers=max_workers,
export_extractor_method=export_extractor_method,
export_inpaint_method=export_inpaint_method,
enable_icon_subject_extraction=enable_icon_subject_extraction,
text_only=text_only,
app=app
)
except Exception as submission_err:
task.status = 'FAILED'
task.error_message = f"Task submission failed: {submission_err}"
task.completed_at = datetime.utcnow()
db.session.commit()
raise

logger.info(f"Submitted recursive export task {task.id} to task manager")

Expand All @@ -498,7 +515,8 @@ def export_editable_pptx(project_id):
"task_id": task.id,
"method": "recursive_analysis",
"max_depth": max_depth,
"max_workers": max_workers
"max_workers": max_workers,
"text_only": text_only
},
message="Export task created (using recursive analysis)"
)
Expand Down
1 change: 1 addition & 0 deletions backend/controllers/project_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,7 @@ def create_ppt_renovation_project():
image_caption_model=current_app.config['IMAGE_CAPTION_MODEL'],
provider_format=current_app.config.get('AI_PROVIDER_FORMAT', 'gemini'),
lazyllm_image_caption_source=current_app.config.get('IMAGE_CAPTION_MODEL_SOURCE', 'doubao'),
upload_folder=current_app.config['UPLOAD_FOLDER'],
)

app = current_app._get_current_object()
Expand Down
1 change: 1 addition & 0 deletions backend/controllers/settings_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ def _create_file_parser():
Config, 'IMAGE_CAPTION_MODEL_SOURCE', None
),
provider_format=caption_format,
upload_folder=current_app.config.get("UPLOAD_FOLDER", Config.UPLOAD_FOLDER),
)


Expand Down
Loading
Loading