给 IOPaint 加了图像压缩功能,聊聊这个开源修图工具

给 IOPaint 加了图像压缩功能,聊聊这个开源修图工具

最近花了点时间研究了一个叫 IOPaint 的开源项目,还顺手给它加了个图像压缩的功能。这篇文章记录一下这个工具本身,以及做了些什么。

IOPaint 是什么

IOPaint 是一个完全免费开源的 AI 图像编辑工具。简单说,你涂抹掉图片上不想要的东西,它用 AI 给你补上。水印、路人、杂物,涂掉就行。

底层用的是各种 SOTA 的 AI 模型:

  • LaMA:快速擦除,处理普通物体/水印/缺陷
  • Stable Diffusion inpainting:更智能的填充,适合复杂场景
  • PowerPaint:不只是擦除,还能替换物体、扩展画布
  • AnyText:在图上写字

架构很干净:FastAPI 后端 + React 前端,PyTorch 做推理,支持 CPU / CUDA / MPS。

项目在 GitHub 上 21k+ stars,社区活跃,持续更新。

为什么要折腾它

IOPaint 本身已经很能打了,但有个问题——输出的图片太大了

它的默认质量是 95/100,而且保持原格式输出。如果你处理的是 PNG 原图,输出的 PNG 可能几 MB 甚至十几 MB。如果只是去个水印发个网页,完全没必要那么大。

所以我想加一个导出压缩的功能:让用户选择输出格式(JPEG / WebP / AVIF / PNG),控制质量,甚至无损压缩。处理完后直接拿到体积合适的文件,省掉「导出→再压缩」的步骤。

技术选型

核心是图像压缩库的选择。调研了几个方案:

方案 说明
Pillow 原生 IOPaint 已有,但 JPEG/WebP 压缩率一般
Squoosh CLI Google 出品,效果好,但得装 Node.js
imagecodecs Python 库,封装了 mozjpeg/libwebp/libavif,一步到位

最终选了 imagecodecs。纯 Python 包,底层就是 Squoosh 用的那套 C 库(mozjpeg、libwebp、libaom),压缩效果完全一样。

就是有个坑:imagecodecs 的版本和 API 有点混乱。VERSION.txt 翻了好久才发现,imwrite(None, data) 不行,得用 jpeg_encode()webp_encode() 这种函数。

如果你的环境里没有 imagecodecs,代码自动退回到 Pillow,不会报错。

前端改动

IOPaint 的前端是 React + Vite + shadcn/ui,代码写得不错,接入起来很顺畅。在设置面板里加了一个 Compress 标签页:

  • 开关:启用/禁用压缩
  • 格式选择:JPEG(兼容性最好)、WebP(平衡)、AVIF(最小体积)、PNG(无损)
  • 质量滑块:1-100
  • 无损开关:WebP/PNG 下可选

设置会持久化,保存在浏览器的 zustand store 里,下次打开还在。

部署体验

Docker 构建花了不少时间,主要是 PyTorch 太大了(2.2GB)。改成了多阶段构建:

  1. base 阶段:CUDA 12.1 + PyTorch 2.1.2 + imagecodecs
  2. frontend 阶段:Node 20 Alpine 编译前端 TypeScript
  3. final 阶段:合并后安装 IOPaint

镜像总大小约 4GB,主要是 PyTorch 和 CUDA runtime 占了绝大部分。

启动一条命令:

docker run -d --gpus all -p 8080:8080 --name iopaint iopaint:gpu-compress

RTX 3090 上推理一张 1080p 图片的 LaMA 擦除大约 200ms。

代码仓库

改动已推送到 GitHub: https://github.com/yinguobing/IOPaint

改了 10 个文件,新增 330 行。如果你想在本地跑,直接拉代码用 Docker 构建就行。

几点感想

  1. Python AI 工具的依赖管理是痛点。 一个 IOPaint 装下来几十个包,PyTorch + transformers + diffusers + gradio,哪个都不小。Docker 是唯一靠谱的交付方式。
  2. imagecodecs 是个好库,但文档太差。 好在源码可读,对着测试用例写调用比看文档快得多。
  3. 开源项目改起来比想象中舒服。 IOPaint 的代码结构清晰,前后端分离,插件体系完善,要扩展功能不需要大规模重构。
  4. AI 修图 + 压缩是一个很自然的组合。 处理图片的最终目的是使用,压缩应该是一站式体验的一部分,而不是额外步骤。
转发至

微信扫一扫分享

WeChat QR Code