【1.6万字】连续抓屏保存为Gif动图 【keyboard库、PIL库、imageio库和pygifsicle库 探索】

一、抓屏保存为Gif

保存的GIF动图:
请添加图片描述

完整代码:

# -*- encoding: utf-8 -*-
"""
@Time    : 2021/5/21 14:19
@Author  : 岳涛
@Software: VS Code
"""
import keyboard
import imageio
from time import sleep, time
from PIL import ImageGrab, Image,ImageFont,ImageDraw


t_capture = 60      # 最长抓屏时间
frame = 5          # 每秒帧数
sleepTime = 1.0 / frame # 抓屏休眠时间

def word_to_image():
    """ 绘制最后一帧,提示观众播放完毕 """

    text1 = r"The End !"
    text2 = r'-- Make by YueTao'
    # 创建一个RGB(0, 150, 255)模式、1440*900dpi的图像
    image = Image.new("RGB", (1440, 900), (0, 150, 255))
    # 实例化一个绘图对象
    drawer = ImageDraw.Draw(image)
    # 设置字体字号
    font1 = ImageFont.truetype(font  = r'C:\Windows\Fonts\Arial.ttf', size = 240)
    # 文字转换为图像,参数分别为起始位置(x,y)、文字、字体字号、颜色
    drawer.text((200, 200), text1, font=font1, fill="#FFF")
    font2 = ImageFont.truetype(font  = r'C:\Windows\Fonts\simsun.ttc', size = 100)
    drawer.text((300, 600), text2, font=font2, fill="#FFF")
    image.save(r'output.png')     # 保存图片
    return image


def takeSnap():
    """ 抓取屏幕的指定区域,保存为RGB图像列表 """

    print(f'F10 开始抓屏 ...')
    keyboard.wait('F10')
    # 开始计时
    t0 = time()

    i = 0
    imgList = []
    print(f'正在抓屏,{t_capture} 秒后或按 F12 停止 ...')

    while i < (frame * t_capture):
        # 实例化
        image = ImageGrab.grab()
        # 获取屏幕分辨率
        screen_w, screen_h = image.size
        # print(f'屏幕分辨率:{screen_w} * {screen_h} dpi')
        # 抓取当前屏幕的快照,返回一个模式为“RGB”的图像。参数边界框用于限制只拷贝当前屏幕的一部分区域。
        cap_im = image.crop((0, 0, screen_w, screen_h))  # 截取全屏
        imgList.append(cap_im)
        # cap_im.save(f'{n}.jpg')   # 截图保存到当前目录

        i += 1
        sleep(sleepTime)
        t1 = time()
        if i % (frame * 4) == 0 or keyboard.is_pressed('F12'):
            print(f'已经抓屏时间:{round(t1 - t0, 1)} 秒')
            # 按下 F12 停止抓屏
            if keyboard.is_pressed('F12'):
                break

    # 添加结束帧图像
    end_img = word_to_image()
    imgList.append(end_img)

    return imgList


def compress_gif(gif_file):
    """ 压缩Gif文件的体积 
    环境配置:1、pip install pygifsicle
            2、https://www.lcdf.org/gifsicle  点击Windows ports,下载windows版的gifsicle.exe文件
            3、gifsicle.exe文件放到当前文件夹
    """
    from pygifsicle import optimize
    print(f'正在压缩Gif文件...')
    optimize(gif_file, f"{gif_file.split()[0]}_压缩.gif") # For creating a new one
    # optimize(gif_path) # For overwriting the original one


def make_gif():
    """ 合并单帧图片为GIF动图 """

    # 抓屏保存为图像列表
    imgList = takeSnap()    
    print(f'正在合并 {len(imgList)} 帧图片为GIF动图,请稍候 ...')
    
    # 保存为Gif文件 
    gif_file = 'hello.gif'
    imageio.mimsave(gif_file, imgList, loop=1, fps=frame)

    # 优化Gif,压缩体积
    compress_gif(gif_file)
    return


if __name__ == '__main__':
    make_gif()
    print('done!')

二、keyboard库

本例中主要用到两个功能:按F10开始抓屏和按F12停止抓屏。

print(f'F10 开始抓屏 ...')
keyboard.wait('F10')
... ....
# 按下 F12 停止抓屏
if keyboard.is_pressed('F12'):
    break

官方文档:https://pypi.org/project/keyboard/
在这里插入图片描述
API接口:https://github.com/boppreh/keyboard#api

keyboard.KEY_DOWN
keyboard.KEY_UP
keyboard.KeyboardEvent
keyboard.all_modifiers
keyboard.sided_modifiers
keyboard.version
keyboard.is_modifier
keyboard.key_to_scan_codes
keyboard.parse_hotkey
keyboard.send (aliases: press_and_release)
keyboard.press
keyboard.release
keyboard.is_pressed
keyboard.call_later
keyboard.hook
keyboard.on_press
keyboard.on_release
keyboard.hook_key
keyboard.on_press_key
keyboard.on_release_key
keyboard.unhook (aliases: unblock_key, unhook_key, unremap_key)
keyboard.unhook_all
keyboard.block_key
keyboard.remap_key
keyboard.parse_hotkey_combinations
keyboard.add_hotkey (aliases: register_hotkey)
keyboard.remove_hotkey (aliases: clear_hotkey, unregister_hotkey, unremap_hotkey)
keyboard.unhook_all_hotkeys (aliases: clear_all_hotkeys, remove_all_hotkeys, unregister_all_hotkeys)
keyboard.remap_hotkey
keyboard.stash_state
keyboard.restore_state
keyboard.restore_modifiers
keyboard.write
keyboard.wait
keyboard.get_hotkey_name
keyboard.read_event
keyboard.read_key
keyboard.read_hotkey
keyboard.get_typed_strings
keyboard.start_recording
keyboard.stop_recording
keyboard.record
keyboard.play (aliases: replay)
keyboard.add_word_listener (aliases: register_word_listener)
keyboard.remove_word_listener (aliases: remove_abbreviation)
keyboard.add_abbreviation (aliases: register_abbreviation)
keyboard.normalize_name

另一个键盘监听和检测库

""" pip install pynput """
import sys, os
from pynput.keyboard import Controller,Key,Listener

# 监听按压
def on_press(key):
    try:
        print("正在按压:",format(key.char))
    except AttributeError:
        print("正在按压:",format(key))

# 监听释放
def on_release(key):
    print("已经释放:",format(key))

    if key==Key.esc:
        # 停止监听
        return False

# 开始监听
def start_listen():
    with Listener(on_press=on_press,on_release=on_release) as listener:
        listener.join()

if __name__ == '__main__':

    # 实例化键盘
    kb=Controller()

    # 使用键盘输入一个字母
    kb.press('a')
    kb.release('a')

    # 使用键盘输入字符串,注意当前键盘调成英文
    kb.type("hello world")

    # 使用Key.xxx输入
    kb.press(Key.space)

    # 开始监听,按esc退出监听
    print('开始监听,按esc退出监听 ... ')
    start_listen()

三、PIL 库

Pillow库是一个Python的第三方库。
在Python2中,PIL(Python Imaging Library)是一个非常好用的图像处理库,但PIL不支持Python3,所以有人(Alex Clark和Contributors)提供了Pillow,可以在Python3中使用。

3.0 安装Pillow

pip install pillow

Pillow库安装成功后,导包时要用PIL来导入,而不能用pillow或Pillow。

import PIL
from PIL import Image

在Pillow库中,除了有二十多个模块,还支持非常多的插件。其中最常用的是Image模块中同名的Image类,其他很多模块都是在Image模块的基础上对图像做进一步的特殊处理,Image模块中会导入部分来使用。本文介绍Image模块的常用方法。

3.1 打开本地图片

# coding=utf-8
from PIL import Image
 
image = Image.open("hello.jpg")
image.show()

open(fp, mode=‘r’): 打开一张图片,是Image模块中的函数。如果图片与当前代码在同一目录下,可以只写图片的文件名,其他情况需要拼接图片的路径。mode默认为’r’,也必须为’r’。
show(): 调用图片显示软件打开图片。打开后程序会阻塞,需要手动关闭。

3.2 创建一张新图片

from PIL import Image

image = Image.new('RGB', (160, 90), (0, 0, 255))
image.show()

new(mode, size, color=0): 创建一张图片(画布),用于绘图,是Image模块中的函数。有3个参数。

  • mode, 图片的模式,如“RGB”(red,green,blue三原色的缩写,真彩图像)、“L”(灰度,黑白图像)等。
  • size, 图片的尺寸。是一个长度为2的元组(width, height),表示的是像素大小。
  • color, 图片的颜色,默认值为0表示黑色。可以传入长度为3的元组表示颜色,也可以传入颜色的十六进制,在版本1.1.4后,还可以直接传入颜色的英文单词,如上面代码中的(0, 0, 255)可以换成‘#0000FF’或‘blue’,都是表示蓝色。

3.3 Image模块的常用属性

from PIL import Image

image = Image.open("hello.png")
print('width: ', image.width)
print('height: ', image.height)
print('size: ', image.size)
print('mode: ', image.mode)
print('format: ', image.format)
print('category: ', image.category)
print('readonly: ', image.readonly)
print('info: ', image.info)

结果如下

width:  1440
height:  900
size:  (1440, 900)
mode:  RGBA
format:  PNG
category:  0
readonly:  1
info:  {'dpi': (120, 120), 'Software': 'Snipaste'}
  • width属性表示图片的像素宽度,height属性表示图片的像素高度,width和height组成了size属性,size是一个元组。
  • mode属性表示图片的模式,如RGBA,RGB,P,L等。
  • format属性表示图片的格式,格式一般与图片的后缀扩展名相关。category属性表示图片的的类别。
  • readonly属性表述图片是否为只读,值为1或0,表示的是布尔值。
  • info属性表示图片的信息,是一个字典。

3.4 图片的模式和模式转换

3.4.1 图片的模式

图片有很多模式,支持以下标准模式,参考:https://pillow.readthedocs.io/en/latest/handbook/concepts.html#concept-modes

mode描述
11位像素,黑白,每字节存储一个像素
L8位像素,黑白
P8位像素,使用调色板映射到任何其他模式
RGB3x8位像素,真彩
RGBA4x8位像素,带透明蒙版的真彩
CMYK4x8位像素,分色
YCbCr3x8位像素,彩色视频格式
LAB3x8位像素,L * a * b颜色空间
HSV3x8位像素,色相,饱和度,值颜色空间
I32位有符号整数像素
F32位浮点像素

1位像素的范围是0-1,0表示黑1表示白,中间表示灰。8位像素的范围是0-255,如RGB的(0, 0, 0)表示黑,(255, 255, 255)表示白,依此类推。

3.4.2 图片的模式转换
from PIL import Image

image = Image.open("hello.jpg")
print(image.mode)
image1 = image.convert('1')
print(image1.mode)
# image1.show()
image_l = image.convert('L')
print(image_l.mode)
# image_l.show()
image_p = image.convert('P')
print(image_p.mode)
image_p.show()

convert(self, mode=None, matrix=None, dither=None, palette=WEB, colors=256): 将图片转换为指定的模式,并且返回转换后的图片副本。如果不指定模式,则自动选择一种能保留图片所有信息且不使用调色板的模式(通常的结果是不转换)。将彩色图像转换为灰度(‘L’)时,使用ITU-R 601-2进行亮度转换:L = R * 299/1000 + G * 587/1000 + B * 114/1000 。将灰度(‘L’)或真彩(‘RGB’)转换为模式’1’时,如果dither参数为’NONE’,所有大于128的值均设置为255(白色),所有其他值都设为0(黑色)。
convert()方法有5个参数。

  • mode, 图片的模式,传入需要转换的模式。部分模式之间不支持转换,代码会报错。
  • matrix, 转换矩阵。传入该参数时,应该传入由浮点数构成的元组,元组长度为4或12。matrix只支持从少数模式转换成’L’或’RGB’。
  • dither, 高频振动,用于控制颜色抖动。从模式’RGB’转换为’P’或从’RGB’或’L’转换为’1’时使用。可用的方法:‘NONE’或’FLOYDSTEINBERG’(默认)。当提供了matrix参数时不使用此功能。
  • palette, 调色板,用于控制调色板的产生。从模式’RGB’转换为’P’时使用,可用的方法有’WEB’(默认)或’ADAPTIVE’。'ADAPTIVE’表示使用自适应的调色板。
  • colors, 自适应调色板使用的颜色数。当palette参数为’ADAPTIVE’时,用于控制调色板的颜色数目。默认是最大值,即256种颜色。
3.4.2.1 matrix参数的效果对比
from PIL import Image
 
 
image = Image.open("hello.jpg")
image_rgb = image.convert('RGB')
print(image_rgb.mode)
image_l = image_rgb.convert('L')
image_l.show()
matrix = (0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6)
image_l2 = image_rgb.convert('L', matrix=matrix)
image_l2.show()

上面的代码中,给matrix参数传入了一个长度为12的元组,matrix的值改变了转换的效果,变化程度取决于传入的元组中浮点数的值。注意,有些模式是不支持的,如’RGBA’,且传入的元组长度必须为4或12,否则报错。

3.4.2.2 palette参数的效果对比
from PIL import Image

image = Image.open("hello.jpg")
image_p = image.convert('P')
# image_l.show()
image_p2 = image.convert('P', palette='ADAPTIVE', colors=256)
image_p2.show()

上面的代码中,将palette参数改为了’ADAPTIVE’,图片的差异不大,不过,如果将colors变小差异会比较大,但那样会将图片效果变差。

3.5 图片拷贝粘贴和保存

from PIL import Image

image = Image.open("hello.jpg")
image_copy = image.copy()
# image_copy.show()
image_new = Image.new('RGB', (160, 90), (0, 0, 255))
image_new2 = Image.new('L', (160, 90), '#646464')
image_copy.paste(image_new, (100, 100, 260, 190), mask=image_new2)
image_copy.save('duck.png')
image_save = Image.open('duck.png')
print(image_save.format, image_save.mode)
image_copy.show()
  1. copy(): 拷贝当前的图片,拷贝出来的图片与原图一模一样。如果想在图片上粘贴一些内容,又想保留原图时,可以使用此方法。
  2. paste(im, box=None, mask=None): 将另一张图片粘贴到当前图片中,如果粘贴的模式不匹配,则将被粘贴图片的模式转换成当前图片的模式。有3个参数。
  • im, 被粘贴的图片。传入一张图片,当第二个参数box指定的是一个区域时,im参数也可以是一个整数或颜色值(元组表示,16进制表示和颜色名都可以,如上面代码中的image_new可以换成(0, 0, 255), ‘#0000FF’, ‘blue’)。
  • box, 图片粘贴的位置或区域。传入一个长度为2或4的元组,如果不传值,默认为(0, 0),图片被粘贴在当前图片的左上角。如果传入长度为2的元组(x, y),表示被粘贴图片的左上角坐标位置。如果传入长度为4的元组(x0, y0, x1, y1),表示图片粘贴的区域,此时区域的大小必须与被粘贴图片一致,否则会报错,传入的元组长度为其他值也会报错。
  • mask, 蒙版。传入一张与被粘贴图片尺寸一样的图片,可以使用模式为’1’、'L’或者’RGBA’的图像。如果mask图像的颜色值为255,则直接按被粘贴图片的颜色粘贴,如果mask图像的颜色值为0,则保留当前图片的颜色(相当于没有粘贴),如果mask图像的颜色值为0~255之间的值,则将im与mask进行混合后再粘贴。
  1. save(fp, format=None, **params): 将当前图片按指定的文件名保存,运行后会将图片按新名字保存在当前路径下(也可以指定路径)。文件名最好带扩展名,方便打开,
  • 传入一个带扩展名的文件名即可。
  • format表示图片的格式,没有指定format则会根据扩展名来解析(如果能解析出来),一般不需要指定format。

3.6 图片的裁剪和缩放

from PIL import Image

image = Image.open("hello.jpg")
image_crop = image.crop(box=(300, 300, 800, 700))
# image_crop.show()
print('before resize: ', image.size)
image_resize = image.resize((500, 400), resample=Image.LANCZOS, box=(100, 100, 1200, 800), reducing_gap=5.0)
print('after resize: ', image_resize.size)
image_resize.show()
  1. crop(box=None): 裁剪图片,返回裁剪区域的图片。box表示裁剪的区域,传入长度为4的元组(x0, y0, x1, y1),不传默认为拷贝原图,相当于copy()方法,如果裁剪的区域超过了原图的区域,超出部分用像素格填充。
  2. resize(size, resample=BICUBIC, box=None, reducing_gap=None): 缩放图片,返回缩放后的图片副本。有4个参数。
  • size, 图片缩放后的尺寸,传入一个长度为2的元组(width, height)。
  • resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BOX, Image.BILINEAR, Image.HAMMING, Image.BICUBIC, Image.LANCZOS。默认为Image.BICUBIC。如果图像的模式为’1’或’P’,则始终设置为Image.NEAREST。
  • box, 缩放图片的区域。传入长度为4的元组(x0, y0, x1, y1),这个区域必须在原图的(0, 0, width, height)范围内,如果超出范围会报错,如果不传值则默认将整张原图进行缩放。
  • reducing_gap, 减少间隙。传入一个浮点数,用于优化图片缩放效果,默认不进行优化,值大于3.0时优化效果基本已经是公平的重采样。

3.7 图片的变换

# coding=utf-8
from PIL import Image

image = Image.open("hello.jpg")
data = (200, 300, 1100, 1200)
image_trans = image.transform((500, 400), Image.EXTENT, data=data, resample=Image.NEAREST, fillcolor='blue')
image_trans.show()

transform(size, method, data=None, resample=NEAREST, fill=1, fillcolor=None): 对图片进行变换,截取的同时进行缩放和填充等。返回指定大小的图片副本,图片的模式与原图相同。有6个参数。

  • size, 返回图片的尺寸。传入一个长度为2的元组(width, height)。
  • method, 转换方法。可以传入Image.EXTENT(一个矩形区), Image.AFFINE(仿射变换), Image.PERSPECTIVE(透视变换), Image.QUAD(一个四边形映射到一个矩形), Image.MESH(图源的四边形在一个操作)。
  • data, 转换方法需要的额外数据。需要根据method的不同传入不同的数据,这个参数是辅助method的,强依赖于转换方法method,格式不匹配会报错(格式详见源码中的__transformer()方法)。
    (1) method为Image.EXTENT时,data格式为(x0, y0, x1, y1),传入截取矩形区域的坐标,可以超出原图的边界。
    (2) method为Image.AFFINE时,data格式为(a, b, c, d, e, f),将原图中(ax+by+c, dx+ey+f)坐标的点映射到返回图片的(x, y)坐标。
    (3) method为Image.PERSPECTIVE时,data格式为(a, b, c, d, e, f, g, h),将原图中((ax+by+c)/(gx+hy+1), (dx+ey+f)/(gx+hy+1))坐标的点映射到返回图片的(x, y)坐标,如果后面两个数g, h为0,则效果与Image.AFFINE相同,其实g, h一般都用0,因为随着x和y变大,相当于要除一个很大的数,原图基本会被缩成一个点。
    (4) method为Image.QUAD时,data格式为(x0, y0, x1, y1, x2, y2, x3, y3),传入一个四边形的四个坐标(西北,西南,东南,东北),将这个四边形映射到返回的矩形图片中。
    (5) method为Image.MESH时,其实MESH转换方法的源码(for box, quad in data:)中有错误,需要自己修改后才能用。
  • resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BILINEAR, Image.BICUBIC。默认为Image.NEAREST。如果图像的模式为’1’或’P’,则始终设置为Image.NEAREST。
  • fill, 填充。如果method参数是一个Image.ImageTransformHandler对象,fill是传给转换方法的一个参数,否则,fill无效。
  • fillcolor, 填充颜色。超出原图区域的部分使用此颜色填充。

3.7.1 不同转换方法method的效果进行对比

from PIL import Image

image = Image.open("hello.jpg")
# data = (200, 300, 1100, 1200)
# image_trans = image.transform((500, 400), Image.NEAREST, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
# data = (0, 1, 300, 1, 0, 400)
# image_trans = image.transform((500, 400), Image.AFFINE, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
# data = (0, 1, 500, 1, 0, 400, 0, 0)
# image_trans = image.transform((500, 400), Image.PERSPECTIVE, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
data = (300, 200, 300, 500, 800, 800, 1100, 0)
image_trans = image.transform((500, 400), Image.QUAD, data=data, resample=Image.NEAREST, fillcolor='blue')
image_trans.show()

3.8 图片的分离

from PIL import Image

image = Image.open("hello.jpg")
print(image.mode)
r, g, b, a = image.split()
print(r.mode, r.size)
print(g.mode, g.size)
print(b.mode, b.size)
print(a.mode, a.size)
# r.show()
# g.show()
# b.show()
a.show()

split(): 对图片进行分离提取。将此图片分离成单独的颜色通道。返回组成原图的单颜色通道图片元组。如分离’RGB’图片会返回三张新图片,每张图片是一个颜色通道(红色,绿色,蓝色)的副本,都是灰度的图片。同理,'RGBA’返回四张新图片。
如果只需要提取其中一种颜色的图片,可以使用getchannel(channel)方法。

r = image.getchannel('R')
print(r.mode, r.size)
r.show()

getchannel(channel): 分离出原图中的一个颜色通道。如分离’RGB’图片中的某个通道时可以传入’R’, ‘G’, ‘B’或0, 1, 2来进行分离。分离’RGBA’中的’A’时只能传入’A’,不能传入3。

3.9 图片的合并

from PIL import Image

image = Image.open("hello.jpg")
r, g, b, a = image.split()
image_merge = Image.merge('RGB', (r, g, a))
print(image_merge.mode, image_merge.size)
image_merge.show()

merge(mode, bands): 将多个单通道的图片合并成一张多通道的图片。merge()是Image模块中的一个函数,不是Image类中的方法,有两个参数。

  • mode, 需要合成的目标图片的模式。如’RGB’,‘RGBA’。
  • bands, 用于合并的单通道图片列表。传入一个列表或元组,列表长度与目标图片的模式要对应,如’RGB’需要传入长度为3的列表,'RGBA’需要传入长度为4的列表。列表中的每张单通道图片尺寸必须相同,否则报错。

3.10 图片的过滤

3.10.1 图片过滤器

Pillow提供了以下预定义的图片过滤器,参考:https://pillow.readthedocs.io/en/latest/reference/ImageFilter.html#module-PIL.ImageFilter

filter描述
BLUR模糊
CONTOUR轮廓
DETAIL详情
EDGE_ENHANCE边缘增强
EDGE_ENHANCE_MORE边缘增强更多
EMBOSS电磁波
FIND_EDGES寻找边缘
SHARPEN夏普
SMOOTH光滑
SMOOTH_MORE更光滑

3.10.2 图片的过滤

from PIL import Image, ImageFilter

image = Image.open("hello.jpg")
# image_blur = image.filter(ImageFilter.BLUR)
# image_blur.show()
# image_contour = image.filter(ImageFilter.CONTOUR)
# image_contour.show()
# image_edge = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
# image_edge.show()
image_emboss = image.filter(ImageFilter.EMBOSS)
image_emboss.show()

filter(filter): 使用指定的过滤器对图片进行过滤。传入一个ImageFilter过滤器,上面表格中的过滤器都支持。

3.11 图片的混合

为了体现出混合的效果,需要使用两张图片,所以再加入一张图片。

from PIL import Image
 
 
image = Image.open('hello.jpg').crop((100, 100, 1300, 900))
image2 = Image.open('hi.jpg').crop((100, 0, 1300, 800))
image.save('hello.png')
image2.save('hi.png')
duck1 = Image.open('hello.png')
duck2 = Image.open('hi.png')
print(hello.size, hello.mode)
print(hi.size, hi.mode)
image_blend = Image.blend(hello, hi, 0.7)
image_blend.show()

blend(im1, im2, alpha): 将两张图片混合成一张图片。blend()是Image模块中的一个函数,不是Image类中的方法,有3个参数。

  • im1, 混合的第一张图片。
  • im2, 混合的第二张图片。图片的尺寸和模式必须与第一张图片相同,否则报错。
  • alpha, 混合的因子。一般传入一个01的浮点数,如果alpha等于0.0,混合结果为第一张图片,如果alpha等于1.0,混合结果为第二张图片。如果alpha为01之间的数,则混合的图片out=im1*(1.0-alpha) + image2*alpha,效果为两张图片的叠加。如果传入其他值,则混合出来的图片效果比较混乱。

3.12 图片的复合

from PIL import Image

duck1 = Image.open('hello.png')
duck2 = Image.open('hi.png')
r, g, b, a = hi.split()
image_compo = Image.composite(hello, hi, r)
image_compo.show()

composite(image1, image2, mask): 将两张图片复合成一张图片,使用蒙版。composite()是Image模块中的一个函数,不是Image类中的方法,有3个参数。

  • image1, 复合的第一张图片。
  • image2, 复合的第二张图片。图片的尺寸和模式必须与第一张图片相同,否则报错。
  • mask, 蒙版。也是一张图片,这张图片的模式为’1’, ‘L’或’RGBA’,尺寸必须与前两张图片相同。
    此方法其实是将第一张图片粘贴到第二张图片上,相当于image2.paste(image1, None, mask),可以参考Image类中paste()方法的用法。

3.13 图片的旋转

from PIL import Image

hello= Image.open('hello.png')
print(hello.size)
image = hello.rotate(15, center=(0, 0), expand=1, translate=(100, 100), fillcolor=(0, 0, 255))
print(image.size)
image.show()

rotate(angle, resample=NEAREST, expand=0, center=None, translate=None, fillcolor=None): 对图片进行旋转,返回一张旋转后的图片副本。有6个参数。

  • angle, 旋转的角度。这个参数是一个必传参数,按角度制计算,按逆时针方向旋转。
  • resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BILINEAR, Image.BICUBIC。默认为Image.NEAREST。如果图像的模式为’1’或’P’,则始终设置为Image.NEAREST。
  • expand, 可扩展性。传入数字0或1,表示布尔值,默认为0。如果值为0,对图片旋转后,返回图片的尺寸与原图尺寸一样。如果值为1,则旋转后,返回图片的尺寸会根据旋转角度自动调整(如果旋转中心保持默认和没有进行平移,则返回图片中可以看到完整的原图)。
  • center, 旋转的中心。传入长度为2的元组(x, y),表示旋转中心的像素点。默认为原图的几何中心。
  • translate, 平移的坐标。传入长度为2的元组(x, y),将原图按(x, y)进行平移,默认为(0, 0)。
  • fillcolor, 填充颜色。传入一个颜色值,颜色值可以是元组表示法,也可以是颜色的十六进制表示法或颜色英文。如上面的(0, 0, 255)可以换成’#0000FF’或’blue’。当图片旋转后,原图变斜了,但返回图片还是矩形的,所以空出的部分需要进行填充,默认为黑色。

3.14 图片的转置和翻转

from PIL import Image

image = Image.open("hello.jpg")
image1 = image.transpose(Image.FLIP_LEFT_RIGHT)
# image1.show()
image2 = image.transpose(Image.FLIP_TOP_BOTTOM)
# image2.show()
image3 = image.transpose(Image.ROTATE_180)
# image3.show()
image4 = image.transpose(Image.TRANSVERSE)
image4.show()

transpose(method): 转置或翻转图片,返回转置后的图片副本。

  • method可以传入Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM, Image.ROTATE_90, Image.ROTATE_180, Image.ROTATE_270, Image.TRANSPOSE, Image.TRANSVERSE。这些方法都是旋转90度和翻转组合的结果。

3.15 改变图片的像素点位置

from PIL import Image

image = Image.open("hello.jpg")
image_effect = image.effect_spread(7)
image_effect.show()

effect_spread(distance): 随机改变图片中像素点的位置,返回处理后的图片副本。将每个像素点随机移动到指定距离范围内的另一个点,distance表示每个像素点的随机变化距离,处理后的图片有“粒度”的变化。

3.16 结语与致敬

在Image模块中,还有很多对图片处理的方法和函数,如有一组以get和put开头的方法,用于获取或修改图片的属性,有将图片与字节等互相转换的方法,有对动图的处理方法等。这里就不继续一一介绍了,感兴趣可以看看源码和官方文档,并多做尝试。
致敬:
https://blog.csdn.net/weixin_43790276/article/details/108478270
https://blog.csdn.net/weixin_43790276/article/details/108673454

四、imageio库

IMAIO是一个Python库,它提供了一个简单的接口来读取和写入大量的图像数据,包括动画图像、体积数据和科学格式。它是跨平台的,运行在Python 2 .x和3。x上,并且易于安装。
在这里插入图片描述

五、pygifsicle库

gif优化压缩大小时用到pygifsicle库,通过优化算法,只保存差异像素,可以大幅度压缩gif文件的体积,而不损失gif的清晰度。
pygifsicle库需要gifsicle.exe文件的支持。

5.1 gifsicle.exe文件下载

官方网址:https://www.lcdf.org/gifsicle/
在这里插入图片描述
在这里插入图片描述
下载后解压得到gifdiff.exe和gifsicle.exe,复制到当前项目文件夹即可。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岳涛@心馨电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值