一行字符串驱动图像处理流水线:基于Pillow的Python图像处理库 一行字符串驱动图像处理流水线基于Pillow的Python图像处理库如果你用过阿里云 OSS 或七牛的图片处理服务一定熟悉这样的 URLhttps://cdn.example.com/photo.jpg?x-oss-processimage/resize,w_200/watermark,text_SGVsbG8但你有没有想过——不依赖云厂商在自己的服务上实现同样简洁的图片处理能力它解决什么问题在内容平台和电商系统中几乎所有图片都需要处理才能到达用户端列表页要缩略图、详情页要大图、不同终端要不同分辨率、还要加水印、转格式……目前主流的做法是使用云厂商的图片处理服务阿里云 OSS、七牛、又拍云等前端只需在图片 URL 后拼接处理参数就能拿到处理后的图片。体验很好但问题也很明显供应商锁定各家参数语法不同迁移成本高持续付费按量计费高流量场景费用可观私有化受限内网或私有部署环境无法使用云服务py-img-processor就是为此而生——在自有服务上复刻 OSS 风格的图片处理能力。一行参数字符串描述完整处理流水线可直接嵌入 URLhttps://your-service.com/img/photo.jpg?actionresize,s_200/crop,w_200,h_200,g_center/watermark,text_SGVsbG8/format,webp后端只需一行代码fromimgprocessor.processorimportprocess_image process_image(photo.jpg,request.GET[action],out_pathoutput.webp)比如这张原图400x225经过resize,s_200/crop,w_200,h_200,g_center/watermark,text_SGVsbG8,color_FFF,size_20/circle,r_10/format,png处理后200x200一行参数完成了缩放 → 居中裁剪 → 文字水印 → 圆角 → 转 PNG 五步操作。能做什么功能字符串写法示例说明等比缩放resize,s_200长边缩放到 200px指定宽高resize,w_300,h_200,m_pad,color_FFFFFF缩放到 300x200不足部分白色填充裁剪crop,w_200,h_200,g_center居中裁剪 200x200圆角circle,r_2020px 圆角圆形裁切circle裁为圆形不传 r 时自动取半径高斯模糊blur,r_5半径 5 的高斯模糊旋转rotate,v_90顺时针旋转 90°透明度alpha,v_5050% 透明度灰度图gray转灰度文字水印watermark,text_SGVsbG8,size_30,color_FFF添加文字水印图片水印watermark,image_bG9nby5wbmc叠加图片水印平铺水印watermark,text_SGVsbG8,fill_1全图平铺水印图片合并merge,image_Ymcucg5n,order_0与另一张图合并格式转换format,webp转为 WebP质量控制quality,q_80输出质量 80渐进显示interlace,v_1渐进式 JPEG所有操作可通过/串联——一行字符串完成多步操作resize,s_400/crop,w_300,h_300,g_center/watermark,text_SGVsbG8,size_20,color_FFF/circle,r_15/format,webp快速上手安装pipinstallpy-img-processorPython 接口fromimgprocessor.processorimportprocess_image# 缩放 裁剪 水印 圆角 转 PNGprocess_image(photo.jpg,resize,s_200/crop,w_200,h_200,g_center/watermark,text_SGVsbG8,color_FFF,size_20/circle,r_10/format,png,out_pathoutput.png,)JSON 格式复杂参数推荐字符串中的文字内容需要 Base64 编码如果觉得不方便可以用 JSON 格式——text等字段直接写明文process_image(photo.jpg,{actions:[{key:resize,s:200},{key:crop,w:200,h:200,g:center},{key:watermark,text:Hello 世界,color:FFF,size:20},{key:circle,r:10},],format:png,},out_pathoutput.png,)命令行工具# 缩放并转 WebPimg-processor-Pphoto.jpg--actionresize,s_200/format,webp-Ooutput.webp# 批量处理整个目录img-processor-P./images/--actionresize,s_400/format,webp-O./output/--overwrite# 同一张图执行多组操作img-processor-Pphoto.jpg-O/tmp/\--actionresize,s_200/format,webpresize,s_400/circle/format,png\--overwrite参数语法说明字符串格式操作名,参数1_值1,参数2_值2/操作名,参数1_值1三个分隔符分隔符作用示例/分隔不同操作resize,s_200/crop,w_100,h_100,分隔操作名和参数resize,s_200,m_lfit_分隔参数的 key 和 values_200→s200文字/路径等复杂值需要 Base64 URL 编码可用内置工具fromimgprocessor.utilsimportbase64url_encode base64url_encode(Hello 世界)# SGVsbG8g5LiW55WM缩放模式详解缩放是最常用的操作m参数控制缩放逻辑模式说明效果lfit默认等比缩放限制在目标矩形内的最大图图片可能小于目标尺寸mfit等比缩放延伸出目标矩形外的最小图图片可能大于目标尺寸fit等比缩放后居中裁剪精确输出目标尺寸可能裁掉部分内容pad等比缩放后补色填充精确输出目标尺寸用color填充空白fixed强制拉伸到目标尺寸可能变形示例将图片缩放到 300x200 区域不足部分白色填充resize,w_300,h_200,m_pad,color_FFFFFF典型使用场景场景一搭建图片处理服务最典型的使用方式——后端接收图片 URL 中的处理参数返回处理后的图片# Django 视图示例fromdjango.httpimportHttpResponsefromimgprocessor.processorimportprocess_imagedefimage_view(request,image_path):actionrequest.GET.get(action,)img_bytesprocess_image(f/data/images/{image_path},action)returnHttpResponse(img_bytes,content_typeimage/webp)前端调用imgsrc/img/photo.jpg?actionresize,s_400/format,webp/场景二CDN 回源处理CDN 节点收到带处理参数的请求回源到你的图片服务执行处理CDN 缓存处理后的结果。后续相同请求直接命中缓存——兼顾灵活性和性能。场景三数据库驱动的处理规则将处理参数存储在数据库中不同业务场景使用不同规则# 从数据库读取处理规则productProduct.objects.get(idproduct_id)# product.thumbnail_action resize,s_200/format,webp# product.detail_action resize,w_800/watermark,text_xxx,size_30/format,webpthumbnailprocess_image(product.image_path,product.thumbnail_action)场景四批量处理运营素材运营同学不需要学 Photoshop一行命令批量搞定# 把整个目录的图片统一缩放、加水印、转 WebPimg-processor\-P./campaign-images/\-O./output/\--actionresize,s_800/watermark,text_TWFya2V0aW5n,size_30,color_FFFFFF,t_80/format,webp\--overwrite安全配置面向服务端使用py-img-processor 内置了多层安全防护通过环境变量或 settings 模块配置exportPY_SETTINGS_MODULEyour_project.settings配置项作用默认值PROCESSOR_MAX_FILE_SIZE限制原图大小MB防止超大文件耗尽内存20PROCESSOR_MAX_W_H单边像素上限30000PROCESSOR_MAX_PIXEL总像素上限宽×高防止像素炸弹300000000PROCESSOR_WORKSPACES本地路径白名单水印等资源只能从这些目录加载()PROCESSOR_ALLOW_DOMAINSURL 域名白名单限制远程资源来源()PROCESSOR_TEXT_FONT文字水印字体路径Arial Unicode.ttfPROCESSOR_TEMP_DIR临时文件目录系统默认生产环境强烈建议配置PROCESSOR_WORKSPACES和PROCESSOR_ALLOW_DOMAINS防止路径穿越和 SSRF 攻击。常见问题Q: 文字水印显示不出来文字水印依赖系统字体。默认使用Arial Unicode.ttf仅 macOS 自带其他系统需要PROCESSOR_TEXT_FONT/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc设为已安装的支持中文的字体文件路径。Q: 字符串里的中文怎么处理字符串格式使用_分隔 key 和 value如果 value 中包含中文、特殊字符、文件路径等需要 Base64 URL 编码fromimgprocessor.utilsimportbase64url_encode# 编码base64url_encode(Hello 世界)# SGVsbG8g5LiW55WM# 用在参数中watermark,text_SGVsbG8g5LiW55WM如果觉得不方便用 JSON 格式可以直接写明文。Q: 支持 HEIF / AVIF 格式吗默认支持 JPEG、PNG、WebP。扩展格式需要安装额外依赖格式方案AVIFPillow 12.0.0 已内置低版本安装pillow-avif-pluginHEIF安装pillow-heif同时支持 HEIF 和 AVIFQ: 可以处理远程 URL 图片吗可以。图片路径支持本地文件和 HTTP/HTTPS URL。但生产环境需要配置PROCESSOR_ALLOW_DOMAINS域名白名单PROCESSOR_ALLOW_DOMAINS(.your-cdn.com,.your-oss.com)Q: 如何与 Django 集成py-img-processor 支持读取DJANGO_SETTINGS_MODULE指向的配置模块将上述配置项直接写在 Django settings 中即可# settings.pyPROCESSOR_MAX_FILE_SIZE10PROCESSOR_WORKSPACES(/data/images/,)PROCESSOR_ALLOW_DOMAINS(.cdn.example.com,)PROCESSOR_TEXT_FONT/usr/share/fonts/NotoSansCJK-Regular.ttcQ: 多个操作的执行顺序是什么严格按照字符串中/分隔的从左到右顺序执行。format、quality等输出相关参数在最后统一处理。Q: 手机拍的照片方向不对怎么办py-img-processor 会自动读取 EXIF 方向信息并矫正无需额外处理。即使 EXIF 数据损坏也会安全跳过不会报错。总结py-img-processor 的核心思路很简单把图片处理描述为一行可序列化的参数。无论是嵌入 URL、存进数据库还是写在配置文件里都能以最低的集成成本完成图片处理。如果你正在寻找一个不依赖云厂商、可私有化部署的图片处理方案不妨试试。更多资源GitHubskylerhu/py-img-processor完整参数文档py-img-processor.readthedocs.io安装pip install py-img-processor开源许可MIT如果这个项目对你有帮助欢迎到 GitHub 给个 ⭐ Star 支持一下github.com/skylerhu/py-img-processor你的 Star 是持续维护的最大动力也欢迎提 Issue 和 PR 一起完善