韩梅梅学Python之四:一行命令,图片全灰

650 阅读6分钟

2020年4月4日,一大早,老板急冲冲的打电话给韩梅梅。

李老板:“全国网站都灰了,为啥我们自己的网站还这么鲜艳。”

韩梅梅:“好多图改不过来。”

李老板:“本来你应该提前准备的。结果搞成现在这么被动。 我们是创业公司,每个员工都应该是创业者。 作为一个合格的创业者,要有远见,有自驱, 不要什么都不考虑,不要什么都等安排。

如果你觉得自己不想当创业者,那就去找份大厂的工作。 如果你是个创业者,就拿出创业者的劲头加个班搞定吧。”

还没等韩梅梅回答,电话就被挂断了。

韩梅梅内心是崩溃的,只好找李雷去诉苦。

李雷:“别担心梅梅,包在我身上。我早就想到如何应对大批量改图的紧急情况,所以我准备了一个命令行处理图片的工具。还写了文章《一行命令PS你的图片》,只不过还没有加变灰的功能”

于是李雷开始忙碌起来,首先打开EzPP的源码考虑怎样添加批量事图片变灰的功能。

可不可以用现有的recolor功能,传递一个灰色的颜色呢?

李雷做了个实验

ezpp recolor -i docs/icon.png -c '#999999'

发现结果不是想要的,图片变红了。

原图-c 999999
原图s-=0.5

为什么呢?原来ezpp recolor功能,目前的算法是这样的:

先将-c后面的颜色参数转化成HSV(Hue,Saturation,Value)数值,

然后,用这里面的Hue,替换图片的每个像素的HSV中的Hue,

再将每个像素的新HSV值转化为色值保存。

Hue 是色相,Saturation是饱和度,Value是亮度

HSV模型

想要使图像变灰,修改Hue是无论如何也办不到的。只能改饱和度

当灰色的色值被转成HSV的时候,灰色是没有对应的色相(Hue)的,因此色相会被转成默认值0,也就是红色。

看来需要专门添加一个灰度调节功能了。

让用户可以直接调整HSV。

比如输入这样的命令

ezpp recolor -i docs/test.jpg -s 0.5

得到这样的结果

原图饱和度变化 -0.5
原图s-=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=1s+=1
s=0.5s+=0.5
s=0.3s+=0.3
s=0.1s+=0.1
s=0(原图)原图
s=-0.1s-=0.1
s=-0.3s-=0.3
s=-0.5s-=0.5
s=-1s-=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日,一大早,老板急冲冲的打电话给韩梅梅。

李老板:“全国网站都灰了,为啥我们自己的网站还这么鲜艳。”

韩梅梅:“好多图改不过来。”

李老板:“本来你应该提前准备的。结果搞成现在这么被动。
我们是创业公司,每个员工都应该是创业者。
作为一个合格的创业者,要有远见,有自驱,
不要什么都不考虑,不要什么都等安排。

如果你觉得自己不想当创业者,那就去找份大厂的工作。
如果你是个创业者,就拿出创业者的劲头加个班搞定吧。”

还没等韩梅梅回答,电话就被挂断了。