庆国庆微信头像处理这么简单?几行代码一秒出图

850 阅读10分钟

小知识,大挑战!本文正在参与“  程序员必备小知识  ”创作活动

在本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

前面说说

本文是对两年前文章你还在@微信官方?我来教你用Python生成你想要的微信头像 的一个优化,同时更新了素材。

提前祝大家国庆节快乐。

我记得当时事情是这样的,那是19年的国庆,举国欢庆建国70周年,不知怎么的,朋友圈出现了很多@微信官方给自己头像加五星红旗。 差点点信以为真,其实是假的,所以,咱还是老老实实自己动手。

看到这,如果你只是想快速生成一个庆国庆的微信头像,不想了解相关技术,很简单,直接点击下方卡片,关注公众号:外卖电影娱乐通,菜单栏点击国庆头像,即可生成。

2019年截图

当时经过需求分析,最终选择了图像合并的方法,今天主要基于之前程序做了如下几点优化:

1、增加图片模板,目前有6个模板

2、控制台增加文字菜单,自动读取头像、模板文件,想选谁就选谁

3、增加GUI程序软件界面,自己选择要上传什么头像图片,选择什么模板

4、增加web端口,自己选择要上传什么头像图片,选择什么模板

最近悟出个道理,文章太长其实不利于大家学习、阅读,在这个碎片化学习的时代,除了学生,可能很难有人能专心花几个小时学习,更别说是对着微信技术文章了,密密麻麻的代码也能把你给看昏。

所以后面每次有项目,我会尽量分块来分享,做成一个个小系列,这样对于系列里的每一部分我也能更仔细的去打磨,毕竟要做到大家都能读懂嘛。

微信头像处理系列也将分为很多篇,比如现在就有明确的三篇:

  • 庆国庆微信头像处理这么简单?几行代码一秒出图
  • 给庆国庆微信头像处理程序写个GUI界面
  • flask实现庆国庆微信头像处理程序web借口

庆国庆微信头像处理这么简单?几行代码一秒出图

现在我们要写的是最简单也是最核心的部分,根据需求编写代码,再啰嗦下需求,并进行功能拆分:

# 需求:将模板图片粘贴到微信头像上,保存处理好的文件

需求功能拆分:
1、读取微信头像和模板图片
2、调整两个图像尺寸为一致(700*700)
3、将模板图片粘贴到微信头像上
4、保存处理好的文件

根据上面的功能拆分,我们可以一步步实现代码。 0)导入相关包

from PIL import Image

1)读取微信头像和模板图片

# 打开图片模版
img1 = Image.open("./img/7.jpg")
img1 = img1.convert('RGBA')
# 打开原来的微信头像
img2 = Image.open("./img/Avatar/old/3.jpeg")
img2 = img2.convert('RGBA')

读取图片我们直接利用PIL中image对象的open函数即可,只需传入图片路径即可。

然后我们还调用convert函数将图片颜色格式转为了RGBA,这样的好处一是统一图片颜色格式,方便后面图片合并,另外就是RGBA是有透明通道的真彩色模式,合并时我们可以设置mask,那么合并时透明部分就不会被复制粘贴到原图像上了,。其他模式还有:

  • RGB : 24位彩色图像
  • 1 :1位像素,黑白,存储的时候每个像素存储为8bit
  • L :8位像素,灰色

2)调整两个图像尺寸为一致(700*700)

size = (700, 700)
if img1.size != size:  # 判断图片大小,统一改为 700*700
    # 修改图片尺寸
    img1.thumbnail(size)
    
if img2.size != size:  # 判断图片大小,统一改为 700*700
    # 修改图片尺寸
    img2.thumbnail(size)

这里我们调用Image中的size属性,获取图片的尺寸,长*宽(像素),然后判断并统一修改尺寸,这里我们使用了thumbnail函数对图片进行缩放,这个函数会根据我们设置的size进行长宽等比例缩放,图片内容不会变形。

当然我们也可以利用resize这个函数重新设置size,但是可能会导致图片内容变形。

3)将模板图片粘贴到微信头像上

# 图片粘贴选区
loc = (0, 0, 700, 700)
# 将img1 粘贴到 img2
img2.paste(img1, loc, img1)

两个图像的合并,我们这里的操作就是直接将模板图片粘贴到原微信头像上,这里我们利用了Image中paste函数,有三个参数,第一个是被粘贴的图片,第二个是粘贴的位置,可以设置左上角像素坐标(x,y),也可以设置粘贴区域(a,b,c,d)。

还有一个可选参数mask,设置遮罩,设置后图片粘贴会按遮罩指定区域进行粘贴,在RGBA模式图片下,alpha(透明通道)波段用作遮罩,这样粘贴模板到原微信头像上时,模板中透明部分就不会被粘贴过去了。

4)保存处理好的文件

img2.show()   # 显示图片
img2.save("./img//Avatar/new/3.png")   # 保存生成的头像图片

保存图片我们利用的是Image的save函数,直接指定保存路径即可,另外我们还调用了show函数来显式的展现处理后的图片。

通过上面四步处理,我们就完成了庆国庆微信头像的生成。

完成第一次优化,程序控制台输出菜单,用户自己选择处理哪个微信头像,选择哪个模板,直接上代码。

第一版,手动输入原微信头像目录,并固定print模板名字
from PIL import Image
import os

"""
需求:给图片右下角添加中国国旗,欢迎国庆,表达对祖国的热爱
"""

# 定义一个图片处理类
class Picture:
    
    '''
    打印菜单
    '''
    def print_menu_national_day_picture(self):
        # 1、打印菜单
        print('******欢迎进入国庆微信头像生成程序******')
        # 首先输入原微信头像地址
        old_img_path = input('******请输入你的微信头像路径:')
        while not os.path.isfile(old_img_path):
            print('你输入的图片路径不存在,请重新输入')
            old_img_path = input('******请输入你的微信头像路径:')
        while True:
            # 这里我们固定几个模板
            print('******请选择图像模板,目前的模板设计类型有******')
            print('***1、国旗')
            print('***2、透明国旗')
            print('***3、祖国生日快乐')
            print('***4、庆国庆')
            print('***5、给你小红旗')
            print('***6、天安门')
            print('***7、天安门国旗')
            print('******您还可以输入:0,直接退出程序******')
            img_template_st = input('请输入您的选择:(输入数字序号即可)')
            # 2、判断输入情况
            if img_template_str == '1':
                return old_img_path, './img/1.png'
            elif img_template_str == '2':
                return old_img_path, './img/2.png'
            elif img_template_str == '3':
                return old_img_path, './img/3.png'
            elif img_template_str == '4':
                return old_img_path, './img/4.png'
            elif img_template_str == '5':
                return old_img_path, './img/5.png'
            elif img_template_str == '6':
                return old_img_path, './img/6.png'
            elif img_template_str == '7':
                return old_img_path, './img/7.png'
            elif img_template_str == '0':  # 退出,返回''空字符串
                print('******您已退出国庆头像P图处理程序******')
                return '', ''
            else:
                print('没有你输入的头像模板:%s'% img_template_str)
        
         
    
    '''
    处理合并图片
    '''
    def handle_national_day_picture(self):
        # 获取原微信头像路径和模板路径
        old_img_path, img_template_path = self.print_menu_national_day_picture()
        
        if img_template_path == '':  # 表示用户选择了退出程序 0
            return ''    # 直接return结束程序
        
        # 否则开始进行处理
        # 打开图片模版
        img1 = Image.open(img_template_path)
        img1 = img1.convert('RGBA')
        if img1.size != (700, 700):  # 判断图片大小,统一改为 700*700
            # 修改图片尺寸
            size = (700, 700)
            img1.thumbnail(size)
            
        # 打开原来的微信头像
        img2 = Image.open(old_img_path)
        img2 = img2.convert('RGBA')
        print('img2', img2.size)
        if img2.size != (700, 700):  # 判断图片大小,统一改为 700*700
            # 修改图片尺寸
            size = (700, 700)
            img2.thumbnail(size)
        
        # 图片粘贴选区
        loc = (0, 0, 700, 700)
        # 将img1 粘贴到 img2(模板图片在上)
        img2.paste(img1, loc, img1)
        img2.show()   # 显示图片
        old_name = os.path.basename(old_img_path).split('.')[0] 
        template_name = os.path.basename(img_template_path).split('.')[0]
        new_pic_path = "./img/Avatar/new/{0}_{1}.png".format(old_name, template_name)
        img2.save(new_pic_path)  # 保存生成的头像图片
        print('******新头像文件目录:%s******'%new_pic_path )
        print('******恭喜你成功生成了属于自己的国庆微信信头像******')
        return 'success'

第二版,自动读取文件目录,打印头像和模板目录,选择序号即可

from PIL import Image
import os

"""
需求:给图片右下角添加中国国旗,欢迎国庆,表达对祖国的热爱
"""

# 定义一个图片处理类
class Picture:
    
    # 模板名称:序号
    template_dicts = {
        '国旗':'1',
        '透明国旗':'2',
        '祖国生日快乐':'3',
        '庆国庆':'4',
        '给你小红旗':'5',
        '天安门':'6',
        '天安门国旗':'7'
        # 更多模板可以自己添加
        # 格式 模板名称:序号,模板文件名:序号.png
    }
    # 文件目录路径
    template_root_path = './img/'
    wx_avatar_old_path = './img/Avatar/old/'
    wx_avatar_new_path = './img/Avatar/new/'
    # 图片文件后缀,如有其他格式可以添加
    image_suffixes = {'png', 'jpg', 'jpeg', 'gif', 'JPG', 'PNG', 'GPEG', 'GIF'}
    '''
    打印菜单
    '''
    def print_menu_national_day_picture(self):
        '''
        1、打印菜单
        '''
        print('******欢迎进入国庆微信头像生成程序******')
        
        '''
        2、原微信头像打印+选择
        '''
        print('******请选择您要处理的微信头像图片名******')
        # 1)获取微信原头像目录下所有图片文件,并打印出文件名
        index = 1
        temp_dict = {}
        for i in os.listdir(self.wx_avatar_old_path):
            file_suffix = i.split('.')[1]
            if file_suffix in self.image_suffixes:  # 过滤非图片文件
                print('******{0}、{1}'.format(index, i))
                temp_dict = {str(index): i}
                index+=1
        print('******您还可以输入:0,直接退出程序******')
        
        # 2)用户选择图像
        old_img_index = input('******请输入您要处理的微信头像序号(输入数字序号即可):')
        # 是否退出程序
        if old_img_index == '0':
            print('******您已退出国庆头像P图处理程序******')
            return '', ''
        # 文件是否存在
        while old_img_index not in temp_dict:
            print('您输入的序号不存在,请重新输入')
            old_img_index = input('******请输入您要处理的微信头像序号(输入数字序号即可):')
        old_img_path = self.wx_avatar_old_path + temp_dict[old_img_index]
        
        '''
        3、模板打印+选择
        '''
        while True:
            # 1)打印已存在模板
            print('******请选择图像模板,目前的模板设计类型有******')
            # 遍历字典自动打印模板名称
            for k,v in self.template_dicts.items():
                print('******{1}、{0}'.format(k, v))
            
            # 2)用户选择模板
            img_template_str = input('请输入您想用的模板:(输入数字序号即可)')
            # 判断用户输入是否有效
            while img_template_str not in self.template_dicts.values():
                print('您输入的序号不存在,请重新输入')
                img_template_str = input('******请输入您想用的模板:(输入数字序号即可)')
                
            # 3)根据用户输入,返回原图片路径和模板路径
            if img_template_str in self.template_dicts.values():
                return old_img_path, self.template_root_path + img_template_str + '.png'
            else:
                print('没有你输入的头像模板序号:%s'% img_template_str)
        
    
    '''
    处理合并图片
    '''
    def handle_national_day_picture(self):
        # 1) 获取原微信头像路径和模板路径
        old_img_path, img_template_path = self.print_menu_national_day_picture()
        
        if img_template_path == '':  # 表示用户选择了退出程序 0
            return ''    # 直接return结束程序
        
        
        # 2)开始进行处理
        # 打开图片模版
        img1 = Image.open(img_template_path)
        img1 = img1.convert('RGBA')
        size = (700, 700)  # 判断图片大小,统一改为 700*700
        if img1.size != size:  
            # 修改图片尺寸
            img1.thumbnail(size)
            
        # 打开原来的微信头像
        img2 = Image.open(old_img_path)
        img2 = img2.convert('RGBA')
        if img2.size != size:  
            # 修改图片尺寸
            img2.thumbnail(size)
        
        # 3)图片粘贴选区
        loc = (0, 0, 700, 700)
        # 将img1 粘贴到 img2(模板图片在上)
        img2.paste(img1, loc, img1)
        img2.show()   # 显示图片
        old_name = os.path.basename(old_img_path).split('.')[0] 
        # 取出原头像名称和模板名称,合起来作为新头像的名称
        template_name = os.path.basename(img_template_path).split('.')[0]
        new_pic_path = self.wx_avatar_new_path + "{0}_{1}.png".format(old_name, template_name)
        img2.save(new_pic_path)  # 保存生成的头像图片
        print('******新头像文件目录:%s******'%new_pic_path )
        print('******恭喜你成功生成了属于自己的国庆微信信头像******')
        print('')
        print('******你可以选择继续处理其他头像,或者输入0,退出程序')
        print('')
        print('')
        return 'success'

实力化一个对象,然后调用函数

t0 = Picture()

while True:
    # 开始程序
    sucess = t0.handle_national_day_picture()
    # ./img/Avatar/old/3.jpeg
    if sucess == '':
        print('******感谢你的使用,国庆微信头像制作程序已结束******')
        break

生成效果图

素材文件获取方式:直接网络上找下,然后处理下即可,或者加我微信pythonbrief,备注:掘金,即可获取。

下集预告

给庆国庆微信头像处理程序写个GUI界面。

效果图如下(类似哈~):