1
0
Files
PPTX/openspec/changes/archive/2026-03-04-remove-image-fit-modes/design.md
lanyuanxiaoyao f34405be36 feat: 移除图片适配模式功能
移除图片 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>
2026-03-04 14:23:12 +08:00

5.6 KiB
Raw Blame History

移除图片适配模式技术设计

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 文件

实现:

# 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 的运行时依赖(保留依赖但代码中不使用)
  • 代码更简洁,易于维护

实现:

# 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

无。移除操作明确清晰,无未决问题。