把超大图片压到模型能接收的尺寸,避免 413 Payload Too Large。
English · 快速开始 · Codex Skill · 命令行 · 开发
Codex Image Compress 是一个本地图片压缩工具与 Codex Skill,面向模型上传场景的体积限制与 HTTP 413 问题。
把截图、照片或设计稿直接贴给模型时,原始文件经常达到十几 MB。接口拒绝请求时只返回一句 413 Payload Too Large,很难判断究竟是尺寸、格式还是 base64 编码后的体积超限。
Codex Image Compress 在本地完成三件事:
- 精确控制文件体积:以目标字节数为硬上限,自动搜索质量与尺寸。
- 估算真实请求体:同时计算 base64 与 multipart 开销,提前拦截可能触发 413 的图片。
- 保留视觉质量:照片走 WebP,截图可保持 PNG,透明通道与动图帧数完整保留。
所有处理都在本机完成,不上传图片,不需要云端账号。
| 能力 | 说明 |
|---|---|
| 单图上限 | --max-bytes 900KB,支持 KB、MB 和纯字节数 |
| 请求预算 | --request-limit 4MB,按 base64 后体积做保守估算 |
| 智能缩放 | 优先保画质,超出预算时才逐步缩小最长边 |
| 多格式输出 | WebP、JPEG、PNG、AVIF、GIF,auto 跟随输入 |
| 透明保护 | PNG/WebP 保留 alpha,不把透明区填黑或填白 |
| 动图支持 | GIF/WebP 动画保持帧数与播放信息 |
| EXIF 方向 | 手机竖拍照片不会出现方向错误 |
| 批量处理 | 目录、通配符、多文件与递归扫描 |
| 安全交付 | 默认不覆盖原图,同名结果自动编号 |
| 可集成 | JSON 输出、退出码、dry-run 与 PowerShell 启动器 |
需要 Python 3.10 或更高版本。
py -3.12 -m pip install pillow压缩一张图片:
py -3.12 .\scripts\image_compress.py `
"C:\photos\screenshot.png" `
--max-bytes 900KB `
--max-edge 1600Windows 用户可以使用包装器:
& .\scripts\compress-image.ps1 `
"C:\photos\screenshot.png" `
--max-bytes 900KB结果默认写入原图旁的 compressed/ 目录:
screenshot.png -> compressed/screenshot-compressed.webp
12.2 MB -> 0.4 MB
1200x800 WEBP q=95
先按接口的实际限制压缩。常见安全起点是单图 900 KB:
py -3.12 .\scripts\image_compress.py .\image.png --max-bytes 900KB --max-edge 1600仍触发 413 时,按下面顺序收紧:
# 1. 保守档,适合多数截图与照片
py -3.12 .\scripts\image_compress.py .\image.png --max-bytes 700KB --max-edge 1440
# 2. 多图对话,按总请求预算分配
py -3.12 .\scripts\image_compress.py .\image.png --max-bytes 500KB --max-edge 1280
# 3. 只压缩字节,不改变像素尺寸
py -3.12 .\scripts\image_compress.py .\image.png --max-bytes 500KB --no-resize如果一次发送多张图片,413 往往来自整个请求体而不是某一张图。先估算总预算:
单图预算 = 请求上限 / 图片数量 - 文本与协议开销
脚本用 --request-limit 检查单张图的 base64 估算;批量多图时,建议把 --max-bytes 设为 500KB 或更低。
把本仓库放到 Codex 的 skills 目录即可作为 Skill 使用:
$skillRoot = Join-Path $env:USERPROFILE ".codex\skills"
New-Item -ItemType Directory -Force -Path $skillRoot | Out-Null
Copy-Item -Recurse -Force .\codex-image-compress "$skillRoot\image-compress"在对话中可以直接说:
用 $image-compress 把这张图压到 900KB 以内,再发给模型。
Skill 的 SKILL.md 会把默认处理流程、413 排查顺序和输出约定提供给 Codex;脚本入口和命令行参考保持在 scripts/ 与 references/ 中,按需读取。
py -3.12 .\scripts\image_compress.py photo.jpg默认输出 WebP,单图不超过 900 KB,最长边 1600 px。
py -3.12 .\scripts\image_compress.py .\screenshots `
--recursive `
--output-dir .\compressed `
--max-bytes 700KBpy -3.12 .\scripts\image_compress.py .\ui.png `
--format png `
--max-bytes 1MB `
--max-edge 2048PNG 是无损格式,如果仍然超过预算,脚本会逐步缩小画布;需要更小体积时改用 WebP。
py -3.12 .\scripts\image_compress.py .\logo.png `
--format webp `
--max-bytes 300KBpy -3.12 .\scripts\image_compress.py .\animation.gif `
--format webp `
--max-bytes 1MBpy -3.12 .\scripts\image_compress.py .\image.png --json返回字段包括:
output:压缩结果绝对或相对路径output_bytes:最终字节数width、height:输出尺寸quality:最终编码质量,PNG 为nullrequest_bytes:base64 + multipart 的保守估算skipped:源图小于目标且启用--skip-smaller时为true
退出码:0 表示全部成功,1 表示至少一张失败,2 表示参数或输入错误。
| 参数 | 默认值 | 说明 |
|---|---|---|
--max-bytes |
900KB |
单图字节上限 |
--request-limit |
4MB |
base64 请求体估算上限,0 关闭 |
--max-edge |
1600 |
最长边像素上限 |
--min-quality |
60 |
自动搜索的最低质量 |
--format |
webp |
auto、jpeg、png、webp、avif、gif |
--output / -o |
compressed/ |
输出文件或目录 |
--output-dir |
无 | 批量统一输出目录 |
--recursive |
关闭 | 递归扫描目录 |
--no-resize |
关闭 | 只调质量,不缩尺寸 |
--overwrite |
关闭 | 覆盖同名输出 |
--skip-smaller |
关闭 | 小图直接复制,不重新编码 |
--dry-run |
关闭 | 只分析,不写文件 |
--json |
关闭 | 输出机器可读结果 |
完整说明见 references/cli.md。
下面是一张 6000x4000 测试照片压到 1200x800、500KB 预算以内的示例;它用于展示视觉质量,实际处理全部在本地完成。
目标字节数是硬约束。 搜索过程不会因为质量下限或尺寸上限而返回一个“看起来接近”的超限文件;最终写入前会再次检查字节数和请求预算。
质量优先,再降尺寸。 照片通常能在原尺寸下通过质量搜索进入预算;只有画质已经触底时才缩小画布。这样既能压小体积,也能保留文字、边缘与纹理。
原始素材不动。 默认写入 compressed/,重名自动加序号,避免覆盖用户唯一的源文件。
git clone https://github.com/miku1130/codex-image-compress.git
cd codex-image-compress
py -3.12 -m pip install -r requirements-dev.txt
py -3.12 -m unittest discover -s scripts -p "test_*.py" -v测试覆盖体积上限、透明通道、请求预算、dry-run、批量重名与动图帧数。CI 在 Python 3.10、3.11、3.12 上运行同一套测试。
提交前建议执行:
py -3.12 -m py_compile .\scripts\image_compress.py
py -3.12 -m unittest discover -s scripts -p "test_*.py"为什么默认是 WebP?
WebP 在照片和截图上的体积通常比 JPEG/PNG 小,同时支持透明通道。需要上传接口兼容性时用 --format jpeg。
压缩后文字变糊怎么办?
先提高 --max-edge,再降低 --max-bytes 允许的质量下限。截图可尝试 --format png,或用 --format webp --min-quality 75。
为什么设置了 900KB,输出却更小? 这是正常的。脚本按质量从高到低搜索,第一次满足预算就停止;有时高质量结果本身已经远低于上限。
图片会不会被上传? 不会。脚本只使用本机 Pillow 编解码,不调用网络接口。
MIT License,见 LICENSE。
