2020年4月4日,一大早,老板急冲冲的打电话给韩梅梅。
李老板:“全国网站都灰了,为啥我们自己的网站还这么鲜艳。”
韩梅梅:“好多图改不过来。”
李老板:“本来你应该提前准备的。结果搞成现在这么被动。 我们是创业公司,每个员工都应该是创业者。 作为一个合格的创业者,要有远见,有自驱, 不要什么都不考虑,不要什么都等安排。
如果你觉得自己不想当创业者,那就去找份大厂的工作。 如果你是个创业者,就拿出创业者的劲头加个班搞定吧。”
还没等韩梅梅回答,电话就被挂断了。
韩梅梅内心是崩溃的,只好找李雷去诉苦。
李雷:“别担心梅梅,包在我身上。我早就想到如何应对大批量改图的紧急情况,所以我准备了一个命令行处理图片的工具。还写了文章《一行命令PS你的图片》,只不过还没有加变灰的功能”
于是李雷开始忙碌起来,首先打开EzPP的源码考虑怎样添加批量事图片变灰的功能。
可不可以用现有的recolor功能,传递一个灰色的颜色呢?
李雷做了个实验
ezpp recolor -i docs/icon.png -c '#999999'
发现结果不是想要的,图片变红了。
原图 | -c 999999 |
---|---|
为什么呢?原来ezpp recolor功能,目前的算法是这样的:
先将-c后面的颜色参数转化成HSV(Hue,Saturation,Value)数值,
然后,用这里面的Hue,替换图片的每个像素的HSV中的Hue,
再将每个像素的新HSV值转化为色值保存。
Hue 是色相,Saturation是饱和度,Value是亮度
想要使图像变灰,修改Hue是无论如何也办不到的。只能改饱和度
当灰色的色值被转成HSV的时候,灰色是没有对应的色相(Hue)的,因此色相会被转成默认值0,也就是红色。
看来需要专门添加一个灰度调节功能了。
让用户可以直接调整HSV。
比如输入这样的命令
ezpp recolor -i docs/test.jpg -s 0.5
得到这样的结果
原图 | 饱和度变化 -0.5 |
---|---|
有了算法代码就好实现了:
def deta_float(origin, deta):
return max(min(origin + deta, 1.0), 0.0)
def recolor_hsv(filename, outfile, dst_h, dst_s, dst_v):
# name of new file
# 确定用什么样的文件名来保存图片
new_filename = outfile
if outfile == None:
bar_filename, ext = os.path.splitext(filename)
print(f"dst_h:{dst_h}, dst_s:{dst_s}, dst_v:{dst_v}")
hsv_name = f"_h({dst_h})" if dst_h != None else f""
hsv_name += f"_s({dst_s})" if dst_s != None else f""
hsv_name += f"_v({dst_v})" if dst_v != None else f""
new_filename = f"{bar_filename}{hsv_name}{ext}"
print(f"{filename} + hsv{hsv_name} -> {new_filename}")
# load pixel from image.
# 打开图片,加载像素值
with open(filename, 'rb') as imgf:
img = Image.open(imgf).convert('RGBA')
width = img.width
height = img.height
px = img.load()
# new file to save result of recolor
# 创造一个新图片用来保存变换结果
img_new = Image.new('RGBA', (width, height))
px_new = img_new.load()
# recolor every pixel
# 逐个像素变换
for y in range(0, height):
for x in range(0, width):
r, g, b, a = px[x, y]
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
new_s = s if r == g and g == b else (
deta_float(s, float(dst_s)) if dst_s != None else s
)
rn, gn, bn = colorsys.hsv_to_rgb(
float(dst_h)/float(360) if dst_h != None else h,
new_s,
deta_float(v, float(dst_v)) if dst_v != None else v)
px_new[x, y] = (int(255*rn), int(255*gn), int(255*bn), a)
# RGBA for png ,And RGB for other ext
# 如果输入文件是PNG保留RGBA格式,其他文件使用RGB格式。
if ext.lower == '.png':
img_new.save(new_filename)
else:
img_new.convert('RGB').save(new_filename)
效果如下:
饱和度变化 | 效果 |
---|---|
原图 | |
s=1 | |
s=0.5 | |
s=0.3 | |
s=0.1 | |
s=0(原图) | |
s=-0.1 | |
s=-0.3 | |
s=-0.5 | |
s=-1 |
如果想把任意图片变成灰度图只要将其饱和度-1.0就可以了。
ezpp recolor -i playground/test.jpg -s 1.0
但是韩梅梅需要的是全站图片都变灰呀。 李雷又加了一个遍历工程下所有图片的参数。
-r
当用户传递了参数-r的时候,通过这个函数遍历目录,找出所有图片文件然后处理。
def get_recursive_pic_infiles(indir):
file_exts = ['jpeg', 'jpg', 'png', 'webp', 'JPEG', 'JPG', 'PNG', 'WEBP']
paths = []
for file_ext in file_exts:
type_filter_str = os.path.join(
f'{indir}', f'**/*.{file_ext}')
picfiles = glob.glob(type_filter_str, recursive=True)
paths.extend(picfiles)
return paths
当看到整个网站的所有图片都变灰的那一刻,韩梅梅热泪盈眶...
源码
如果想要深入了解EzPP,可以看官方文档完整源码 EzPP@github
全部故事:
韩梅梅学python之序章:一行命令,更新flutter工程下所有图标
李雷经过一个月的奋战,终于完成了一个flutter应用的开发。
打算上线了才发现,图标还是flutter自带的图标呢,赶紧向设计师韩梅梅求救。
设计师韩梅梅拿出准备已久的Logo丢给李雷,李雷傻眼了。
李雷:“怎么只有一个?”
韩梅梅:“难道安卓和iOS要用不同的图标?”
李雷:“不是啊。同样的图标不同的尺寸。
安卓图标五六个 ,iOS图标十几个吧。
我给你列个列表吧,尺寸都告诉你。你帮忙resize一下吧。”
韩梅梅:”宝宝心里苦...“
李雷:“嗯,我想想办法吧...”
韩梅梅学python之一:python3中f-string 格式化固定宽度的数字
书接上回
看到工程师李雷能用一行命令,更新flutter工程下所有图标,
韩梅梅深刻的体会到,这(zhe)门(ge)语(nan)言(ren)如此优秀,一定不能错过。
于是找到李雷:
韩梅梅:“李雷,上次见到你用python更新图标,感觉好棒啊”
李雷:“Python确实是很好用的”
韩梅梅:“我能学会吗”
李雷:“有我在,怎么可能学不会呢?我们先从最简单的Hello world开始吧”
......
韩梅梅学python之二:黄金分割和五角星
学完python3中f-string 格式化固定宽度的数字,
李雷如约上门安装安装python,折腾了很大一通李雷和韩梅梅都感觉很累。
于是李雷提议到公园玩耍,他提前做足了功课,
学习了很多拍照到知识,终于用上了,尤其是构图比例,一律黄金分割。 ...
韩梅梅学Python之三:斐波那契
经过上次的授课经历,李雷发觉,韩梅梅对图形绘制这块很感兴趣。
于是绞尽脑汁,谷歌百度,寻找各种素材。经过反复实验终于完成了备课工作。
于是乎掰着手指头,从周一盼到了周六。
“梅梅,我们先看一个神奇的公式,以及如何用python实现它”
韩梅梅学Python之四:一行命令,图片全灰
2020年4月4日,一大早,老板急冲冲的打电话给韩梅梅。
李老板:“全国网站都灰了,为啥我们自己的网站还这么鲜艳。”
韩梅梅:“好多图改不过来。”
李老板:“本来你应该提前准备的。结果搞成现在这么被动。
我们是创业公司,每个员工都应该是创业者。
作为一个合格的创业者,要有远见,有自驱,
不要什么都不考虑,不要什么都等安排。
如果你觉得自己不想当创业者,那就去找份大厂的工作。
如果你是个创业者,就拿出创业者的劲头加个班搞定吧。”
还没等韩梅梅回答,电话就被挂断了。