问题:
之前遇到一个需求 批量eps矢量图转成 4000*4000 以上的jpg图片, 然后我就开始研究了
思路:
总的来说大致方案有两个:
一个是傻瓜式教程: 直接用Adobe Illustrator打开eps, 然后ctrl + alt + shift + s 存储为web格式, 然后选jpg 高质量填写宽高其中小的值, 把他改成4000以上, 按比例缩放然后点击保存即可(缺点明显, 一个一个太慢了, 需要点好久)
另一个是Pillow库的实现, 今天主要讲主要解决方案
介绍
PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。
由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。
安装上手吧
pip install pillow
然后就是熟悉API了
这里偷个懒:
然后就是代码实现阶段
from PIL import Image, ImageFilter
if __name__ == '__main__':
file = rb"D:\eps\0.eps"
# 缩放后的像素阈值
scale_threshold = 5000
# 加载图片到Image里面
im = Image.open(file)
wd = im.width
ht = im.height
scale = 0
if wd > ht:
scale = scale_threshold / ht
elif wd <= ht:
scale = scale_threshold / wd
# 这里采用缩放的方式而不是直接采用resize直接调整尺寸, 其优点是可以保持宽高比例防止变形
# scale 属性只能是整数好像, 那就向上取整
im.load(scale=math.ceil(scale))
# 保存为.jpg格式才需要填写这个模式, png不需要这一句
img_deal = im.convert('RGB')
# 抗锯齿, 可以考虑从这里入手 Image.ANTIALIAS, 效果感觉没啥变化
# img_deal = img_deal.resize((int(ht*scale), int(wd*scale)), Image.ANTIALIAS)
# 这里就厉害了, Pillow为我们添加了很多处理图像的滤波,具体可以参考
# 详情见知乎: https://zhuanlan.zhihu.com/p/62737338
img_deal = img_deal.filter(ImageFilter.SMOOTH)
# 保存, 这里需要几个参数:
# dpi决定的是图片的最小显示粒度, 这里设置9000*9000没啥明显效果
# quality质量一般为 0-95,填写100会有点"优化过头"适得其反的效果---别人说的, 没验证过
# subsampling参数:子采样,通过实现色度信息的分辨率低于亮度信息来对图像进行编码的实践。 可能的子采样值是0,1和2,正常0可以满足图片大小增大的需求
img_deal.save("D:/eps/EPS_SMOOTH.jpg", "JPEG", quality=100, subsampling=0)
我们转换后的图片详情直接上图:
实现出来的效果图片如下:
先放一张 AI (Adobe Illustrator)处理的
然后放一张我们处理的平滑滤波的效果图:
no~~ 咱处理的总的看起来也差不多吧, 但是吧, 是骡子是马拉出来溜溜就知道了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这里我们放大后看细节, 下面两张图依次为AI, Pillow处理的
在我们图片的分辨率为4000 * 4000 放大后还是不能和AI处理的结果比较, 虽然总的图片放到到200%看起来没啥差距, 但当我们放大到最细节看起来, 还是AI的图像处理更胜一筹, 氮素 !!!!
我们要做的是批量啊, Python 在不考虑最大细节优化的话可以批量操作我们的eps文件, 无疑是个不错的选择 !!!
附上我们的批量代码:
from PIL import Image, ImageFilter
import glob
# eps 转 jpg
def eps_to_jpg(file):
# 缩放后的像素阈值
scale_threshold = 5000
im = Image.open(file)
wd = im.width
ht = im.height
scale = 0
if wd > ht:
scale = scale_threshold/ht
elif wd <= ht:
scale = scale_threshold / wd
im.load(scale=scale)
# 保存为.jpg格式才需要
img_deal = im.convert('RGB')
img_deal = img_deal.filter(ImageFilter.SMOOTH)
img_deal.save("D:/eps/EPS_EXAMPLE.jpg", "JPEG", quality=95, subsampling=0)
if __name__ == '__main__':
file_path = "D:/eps/"
files = glob.glob(file_path + "*.eps")
for file in files:
eps_to_jpg(file)
总结
其中需要优化的点:
图片质量比不上AI处理(硬伤), 但是可以考虑将分辨率调的比目标值大来缩小差距, 目前试过好多种滤波和图像增强API都无法达到满意的效果, 请懂行的老司机带带我这个菜鸟, 怎么才能将图片质量优化到和AI媲美
后续
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
其实吧我们选第一种方案的话也是有办法的, PyAutoGUI 直接傻瓜式划水操作电脑, 就是有点耗时, 优点是, 图片质量完美, 这里考虑下还是不要附上源码, 就直接说思路吧
win + d 桌面打开 AI
ctrl + o 输入eps文件夹路径, 找到第一张图片的位置, 将坐标记录下来 (前置工作有很多: 配置图片一行和一列的数量, 总的数量 每张图的大小, 以及右间距和下间距)
加载图片后 ctrl + alt + shift + s 存储为web格式
然后找到选择图片质量 - 高, 图片格式 - jpg, 点击存储, 然后输入存储路径, 保存即可
很繁琐啊, 截图很累的, 而且还要计算每行每列的像素, 以及滚动的实现...总的来说, 心累
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
教程到这里就差不多结束了, 我也再找找看下有没有具体优化图像细节质量的办法
有兴趣的小伙伴我给点建议: 可以考虑从滤波和增强器来结合实现, 毕竟人的精力是有限的, 我也没有挨个试 !! 搞定后可以@我将代码发送至评论区, 我会给你加鸡腿!!!