移除图片 fit 和 background 参数支持,简化图片渲染逻辑。系统恢复到直接使用 python-pptx 原生图片添加功能,图片将被拉伸到指定尺寸。 变更内容: - 移除 ImageElement 的 fit 和 background 字段 - 移除 metadata.dpi 配置 - 删除 utils/image_utils.py 图片处理工具模块 - 删除 validators/image_config.py 验证器 - 简化 PPTX 和 HTML 渲染器的图片处理逻辑 - HTML 渲染器使用硬编码 DPI=96(Web 标准) - 删除相关测试文件(单元测试、集成测试、e2e 测试) - 更新规格文档和用户文档 - 保留 Pillow 依赖用于未来可能的图片处理需求 影响: - 删除 11 个文件 - 修改 10 个文件 - 净减少 1558 行代码 - 所有 402 个测试通过 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
185 lines
5.6 KiB
Markdown
185 lines
5.6 KiB
Markdown
# 移除图片适配模式技术设计
|
||
|
||
## Context
|
||
|
||
### 当前状态
|
||
|
||
图片适配模式功能已在 `openspec/changes/archive/2026-03-04-add-image-fit-modes/` 中实现并归档,包括:
|
||
|
||
- `utils/image_utils.py`: 图片处理工具模块(英寸像素转换、fit 模式处理)
|
||
- `validators/image_config.py`: 图片参数验证器
|
||
- `core/elements.py`: ImageElement 添加了 fit 和 background 字段
|
||
- `renderers/pptx_renderer.py`: 重写 _render_image() 支持四种 fit 模式
|
||
- `renderers/html_renderer.py`: render_image() 支持 CSS object-fit 映射
|
||
- `core/presentation.py`: 读取 metadata.dpi 配置
|
||
- 完整的单元测试和集成测试
|
||
|
||
该功能尚未上线使用,无需考虑向后兼容性。
|
||
|
||
### 约束条件
|
||
|
||
- 必须保留 Pillow 依赖(用户要求留作备用)
|
||
- HTML 渲染器需要保留英寸到像素的转换功能(使用硬编码 DPI=96)
|
||
- 移除后图片渲染行为:直接拉伸到 box 指定的尺寸
|
||
|
||
### 利益相关者
|
||
|
||
- 最终用户:获得更简单的图片配置(只需 src 和 box)
|
||
- 开发者:降低代码复杂度和维护成本
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
|
||
- 完全移除图片适配模式功能(fit、background、dpi 配置)
|
||
- 简化图片渲染逻辑,恢复到直接使用 python-pptx 原生功能
|
||
- 删除不再需要的工具模块和验证器
|
||
- 删除相关测试文件
|
||
- 更新规格文档和用户文档
|
||
- 保留 Pillow 依赖用于未来可能的图片处理需求
|
||
|
||
**Non-Goals:**
|
||
|
||
- 不移除 Pillow 依赖
|
||
- 不改变 HTML 渲染器的基础英寸到像素转换功能(保留硬编码 DPI=96)
|
||
- 不影响其他元素类型(text、shape、table)的渲染逻辑
|
||
|
||
## Decisions
|
||
|
||
### 决策 1: HTML 渲染器使用硬编码 DPI
|
||
|
||
**选择:** HtmlRenderer 使用硬编码的 `self.dpi = 96`,移除 __init__ 的 dpi 参数
|
||
|
||
**理由:**
|
||
|
||
- 96 是 Web 标准 DPI,适用于绝大多数场景
|
||
- HTML 预览的尺寸转换是基础功能,不需要用户配置
|
||
- 移除 metadata.dpi 配置后,简化了用户 YAML 文件
|
||
|
||
**实现:**
|
||
```python
|
||
# renderers/html_renderer.py
|
||
class HtmlRenderer:
|
||
def __init__(self): # 移除 dpi 参数
|
||
self.dpi = 96 # 硬编码 Web 标准 DPI
|
||
```
|
||
|
||
### 决策 2: PPTX 图片渲染恢复到简单实现
|
||
|
||
**选择:** 直接使用 python-pptx 的 `slide.shapes.add_picture()` 方法
|
||
|
||
**理由:**
|
||
|
||
- python-pptx 原生支持图片添加,会自动拉伸到指定尺寸
|
||
- 移除对 Pillow 的运行时依赖(保留依赖但代码中不使用)
|
||
- 代码更简洁,易于维护
|
||
|
||
**实现:**
|
||
```python
|
||
# renderers/pptx_renderer.py
|
||
def _render_image(self, slide, elem: ImageElement, base_path):
|
||
img_path = Path(elem.src)
|
||
if not img_path.is_absolute() and base_path:
|
||
img_path = Path(base_path) / elem.src
|
||
|
||
if not img_path.exists():
|
||
raise YAMLError(f"图片文件未找到: {img_path}")
|
||
|
||
x, y, w, h = [Inches(v) for v in elem.box]
|
||
slide.shapes.add_picture(str(img_path), x, y, width=w, height=h)
|
||
```
|
||
|
||
### 决策 3: 完全删除相关文件而非注释代码
|
||
|
||
**选择:** 直接删除 image_utils.py、image_config.py 及相关测试文件
|
||
|
||
**理由:**
|
||
|
||
- 功能尚未上线,无需保留代码历史
|
||
- Git 历史已记录所有实现细节
|
||
- 保持代码库整洁
|
||
|
||
### 决策 4: 删除 image-fit-modes 规格
|
||
|
||
**选择:** 删除 `openspec/specs/image-fit-modes/` 整个目录
|
||
|
||
**理由:**
|
||
|
||
- 该规格对应的 capability 正在被移除
|
||
- 归档的变更中已保留完整规格副本
|
||
|
||
## Risks / Trade-offs
|
||
|
||
### 风险 1: HTML 预览尺寸可能与 PPTX 不完全一致
|
||
|
||
**风险:** 硬编码 DPI=96 可能在某些显示器上导致预览尺寸与实际 PPTX 有差异
|
||
|
||
**缓解措施:**
|
||
- 96 是 Web 标准,覆盖绝大多数场景
|
||
- 预览功能主要用于布局参考,不需要像素级精确
|
||
- 用户主要关注 PPTX 输出结果
|
||
|
||
### 风险 2: 删除文件可能影响其他未发现的依赖
|
||
|
||
**风险:** 可能有其他代码或测试依赖 image_utils 或 image_config
|
||
|
||
**缓解措施:**
|
||
- 运行完整的测试套件验证
|
||
- 检查 imports 确保没有遗漏的引用
|
||
- 使用 Grep 搜索可能的引用点
|
||
|
||
### 风险 3: 文档更新可能不完整
|
||
|
||
**风险:** README.md 或 README_DEV.md 中可能残留相关说明
|
||
|
||
**缓解措施:**
|
||
- 在 tasks 中明确列出文档更新任务
|
||
- 人工审查最终文档内容
|
||
|
||
## Migration Plan
|
||
|
||
### 部署步骤
|
||
|
||
由于功能尚未上线,无需迁移策略。直接执行删除和修改即可。
|
||
|
||
1. **删除工具和验证器模块**
|
||
- 删除 `utils/image_utils.py`
|
||
- 删除 `validators/image_config.py`
|
||
- 更新 `validators/validator.py` 移除引用
|
||
|
||
2. **修改核心代码**
|
||
- 更新 `core/elements.py` 的 ImageElement
|
||
- 更新 `core/presentation.py` 的 Presentation
|
||
- 更新 `renderers/pptx_renderer.py`
|
||
- 更新 `renderers/html_renderer.py`
|
||
- 更新 `yaml2pptx.py`
|
||
- 更新 `preview/server.py`
|
||
|
||
3. **删除测试文件**
|
||
- 删除 `tests/unit/test_image_utils.py`
|
||
- 删除 `tests/unit/test_validators/test_image_config.py`
|
||
- 删除 `tests/integration/test_image_fit_modes.py`
|
||
|
||
4. **删除规格文件**
|
||
- 删除 `openspec/specs/image-fit-modes/` 目录
|
||
|
||
5. **更新文档**
|
||
- 更新 `README.md`
|
||
- 更新 `README_DEV.md`
|
||
- 更新 `openspec/specs/element-rendering/spec.md`
|
||
- 更新 `openspec/specs/html-rendering/spec.md`
|
||
|
||
6. **验证**
|
||
- 运行完整测试套件
|
||
- 检查是否有遗留的 import 引用
|
||
|
||
### 回滚策略
|
||
|
||
- Git 历史保留了所有实现
|
||
- 如需恢复功能,可以从归档的变更中恢复代码
|
||
- 或者从 Git 历史中恢复提交 `19d6661` 之前的代码
|
||
|
||
## Open Questions
|
||
|
||
无。移除操作明确清晰,无未决问题。
|