| 名称 | doc-to-image-resizer |
| 版本 | 1.0.0 display_name: 文档转图片与智能压缩 display_name_en: 文档转图片与智能压缩 |
| 描述 | “文档逐页转图片并按体积约束自动压缩的标准化流水线。支持 PDF、Word(doc/docx)、Excel(xls/xlsx)、PowerPoint(ppt/pptx) 与常见图片,逐页输出 JPG/PNG,并通过调整像素与 JPEG 质量把文件体积压到指定上限或区间(如 500k、450k-500k)。当用户提出“文档转图片”“PDF 转 jpg”“每页一张图”“扫描件转图片”“批量转图”“图片压缩到 500k”“控制图片大小在 450k-500k”“图片太大传不上去”等需求时使用。” description_zh: “文档逐页转图片并按体积约束自动压缩的标准化流水线。支持 PDF、Word、Excel、PowerPoint 与常见图片格式,逐页输出 JPG,并通过调整像素分辨率与 JPEG 质量参数,把每张图片的文件体积精确压到指定上限或区间(例如 500k、450k-500k)。内置三步流程:核对校验、文档转图片、按规调整大小。源文档全程只读,所有写操作走原子替换,每批产出可回滚的处理清单,全程本地处理不外传。” description_en: “一条标准化流水线:把文档逐页转换为图片,并自动压缩到目标文件体积。支持 PDF、Word(doc/docx)、Excel(xls/xlsx)、PowerPoint(ppt/pptx)以及常见图片格式,将每一页渲染为 JPG,并通过调整像素分辨率与 JPEG 质量,使字节体积符合给定上限或区间(例如 500k、450k-500k)。共三步:校验与扫描、转换、调整大小。源文档只读,所有写入均为原子操作,每批次生成可用于回滚的处理清单,全程本地处理、不上传网络。” agent_created: true |
文档转图片 + 按规调整大小
把文档逐页转成图片,并按用户给定的体积要求精确控制每张图的文件大小。严格分三步执行: 核对校验 → 文档转图片 → 按规调整大小。
硬约束(任何情况下不得违反)
- 源文档只读:绝不改名、移动、删除、覆盖源文档。第三步中的"原图"仅指第二步产出的图片。
- 不擅自处理问题数据:扫描发现异常或重复,必须先告知用户并征求意见,取得明确答复后才继续。
- 不覆盖既有输出:目标文件已存在时默认追加
-2后缀(--conflict可改),不静默覆盖。 - 原子写入:调整大小一律"临时文件 → 落盘校验字节数 → 原子替换",中途失败原地保留。
- 不破解加密:加密/带口令文档直接跳过并报告。
- 全本地处理:不联网上传、不外传任何文件;中间产出的临时 PDF 落系统临时目录,用完即清。
- 可核查:每批必须产出处理清单 CSV,记录处理前后字节数,作为交付凭证与回滚依据。
环境
运行环境(平台打包 / 部署用,必读)
| 项 | 要求 |
|---|---|
| 操作系统 | Windows(Office 转图依赖本机 COM 自动化;非 Windows 仅 PDF / 图片可用,Office 文档不可用) |
| Python | >= 3.10(本机使用 WorkBuddy 托管 Python 3.13.12,见下方路径) |
| 第三方库 | PyMuPDF、Pillow、pywin32(依赖清单见 requirements.txt) |
| Office / WPS | 本机需安装 Microsoft Word / Excel / PowerPoint 或 WPS,用于把 Office 文档经 COM 导出为临时 PDF 再渲染 |
依赖缺失时安装:pip install -r requirements.txt(或 pip install pymupdf pillow pywin32)。
Office 缺失时自动回退 WPS(KWPS);Office 与 WPS 均不可用则仅 PDF / 图片路径可运行。
解释器
优先使用托管解释器(已装上述全部依赖):
C:\Users\admin\.workbuddy\binaries\python\envs\default\Scripts\python.exe
若改用系统 Python,需先 pip install -r requirements.txt。
执行方式
一条命令跑完三步(scripts/pipeline.py)。首次执行一律加 --dry-run 预演,确认队列与体积约束无误后再正式跑。
# 预演(不写任何文件)
python scripts/pipeline.py "D:\docs" --size 450k-500k --dry-run
# 正式:区间模式(严格落在 450KB~500KB)
python scripts/pipeline.py "D:\docs" --size 450k-500k
# 仅上限模式(压缩到上限的 80%~90%)
python scripts/pipeline.py "D:\docs\a.pdf" --size 500k
# 指定输出目录、精度,或只要转图不要压缩(不传 --size)
python scripts/pipeline.py "D:\docs" --outdir "D:\out" --dpi 200 --format jpg
主要参数
| 参数 | 默认 | 说明 |
|---|---|---|
--size |
无 | 体积约束:500k(仅上限)或 450k-500k(区间,严格执行)。不传则跳过第三步 |
--outdir |
源文档所在目录 | 图片保存目录 |
--dpi |
150 |
渲染精度。清晰度与体积的平衡点,一般无需调整 |
--format |
jpg |
jpg(可控体积)或 png(无损,无法按 KB 精确控制) |
--order |
size |
队列顺序:size 先小后大 / name / dir |
--conflict |
rename |
输出重名时:rename 加后缀 / skip / overwrite |
--no-backup |
关 | 默认把压缩前的原图备份到 _原图备份 子目录 |
--min-edge |
800 |
清晰度红线:缩放后最长边不得小于此值 |
--timeout |
300 |
单文件转换超时(秒),超时会终止 Office 进程并记录失败 |
--force |
关 | 存在异常/重复仍继续(问题文件自动跳过) |
--dup-all |
关 | 重复文件也全部转换(默认每组只转队列中最靠前的一份) |
--include-hidden |
关 | Excel 是否包含隐藏工作表 |
三步流程与判停规则
步骤一 · 核对校验(scripts/scan.py,pipeline 自动执行)
清点数量、类别、大小;检测异常与重复;按源文件字节数升序(同大小按路径字典序,稳定排序)编排队列;
分配输出目录与基名(同目录同名自动加 -2)。
异常判定清单:0 字节、损坏无法解析、加密/带口令、被 Office 占用锁定、非白名单格式、 单文件 >500MB、路径长度 >240、文件名含特殊字符、目标目录不可写、PDF 页数 >300(告警)。
重复判定:SHA-256 完全一致视为内容重复。
判停:pipeline.py 退出码 2 = 发现异常或重复,必须停止并向用户报告,等待明确答复。
用户在答复中确认"跳过重复/忽略异常"后,方可追加 --force 重跑。绝不可自行判定后继续执行。
步骤二 · 文档转图片(scripts/convert.py)
- PDF:PyMuPDF 按 DPI 渲染;
- Office:COM 先导出临时 PDF 再渲染(锁定排版);Excel 按工作表顺序导出,页码跨表连续;
- 图片源文件:按 1 页处理。
命名 {文档名}_第{NNN}页.{jpg|png},页码从文档首页起算(不是文档内部页码),3 位补零,超 999 页自动扩位。
默认保存至源文档所在目录。基线质量 q92,为第三步留足压缩空间。
步骤三 · 按规调整大小(scripts/resize.py)
- 未指定体积约束则整步跳过;
- 只处理超出上限的图片;天然小于下限的一律不放大、不处理,仅在清单中标注"低于下限(未处理)";
- 仅给上限:目标 = 上限 × 85%,验收区间 = 上限的 80%~90%;
- 给定区间:目标 = 区间中值,验收必须严格落在
[min, max]; - 默认备份原图到
_原图备份后替换(--no-backup可跳过备份)。
算法与调参见 references/sizing-algorithm.md。Office COM 的已知坑见 references/conversion-notes.md。
收尾交付
- 汇报:文档数、生成图片数、压缩张数、未达标/失败数、体积约束、耗时;
- 用 present_files 呈现清单 CSV(UTF-8 BOM,Excel 可直接打开);
- 若存在"未达标"行,必须逐条说明原因(区间过窄 / 触碰清晰度红线 / 转换失败),不得笼统报成功。
故障速查
| 现象 | 处理 |
|---|---|
| 转换超时 | 多为 Office 弹窗(文档锁定/字体缺失/恢复未保存版本)。关闭该文档的 Office 窗口后重跑,或提高 --timeout |
| 体积压不进区间 | 区间过窄或图片内容特殊。先放宽区间(如 400k-500k)验证,再收窄 |
| 提示"仅 JPG 可控体积" | PNG 无法按 KB 调参,改用 --format jpg 重新转换 |
输出全是 -2 后缀 |
目录里已有同名图片,默认不覆盖。清理旧图或加 --conflict overwrite |
| 中文乱码 | 已强制 UTF-8;若终端仍异常,设置 PYTHONUTF8=1 |