Python pygame(GUI编程)模块最完整教程(3)

上一篇文章:https://blog.csdn.net/qq_48979387/article/details/128784116

9 颜色

参考资料:https://pyga.me/docs/ref/color.html

9.1 关于计算机中的颜色

RGB是最常用的颜色表示方式之一。R,G,B分别表示光学中的三原色:红、绿、蓝,范围一般在[0,255]之间,也就是十六进制的[0x00,0xff]。常见的颜色如:(255, 255, 255)表示白色,(0,0,0)表示黑色,(255,0,0)表示红色,(0,255,0)表示绿色,(0,0,255)表示蓝色,(128,128,128)表示灰色。

9.2 Color对象

pg.color.Color对象提供了一些关于颜色的基本操作。在pygame中表示颜色,使用的颜色空间一般是RGB和RGBA(红、绿、蓝、不透明度)。R,G,B,A的范围都是0-255之间。A=255表示该像素点完全不透明,A=0表示该像素点完全透明,如果不单独注明透明度,则默认为255。

pygame支持的颜色表示方式有:

  • 颜色名称的字符串。如:"red", "green"。关于pygame支持的颜色名称请参考下一节。

  • HTML格式颜色字符串,形如"#rrggbbaa"。如"#ff0000"表示红色(不透明),"#000000"表示黑色。

  • 十六进制格式字符串,形如"0xrrggbbaa"。如"0xff0000"表示红色

  • RGB或RGBA格式元组。如(255, 255, 255)表示白色。

下面是Color的原形,参数非常容易理解。

Color(r, g, b) -> Color
Color(r, g, b, a=255) -> Color
Color(color_value) -> Color

Color对象可以直接传递给需要颜色值作为参数的方法,比如Surface.fill。

颜色支持一些基本的二进制运算,如+, -, *, //, %, ~。颜色的运算中不会出现ZeroDivisionError,如果除以0,则得到0。

下面列举了Color对象的属性和方法。

r -> int

颜色的红色值。

g -> int

颜色的绿色值。

b -> int

颜色的蓝色值。

a -> int

颜色的不透明程度。

cmy -> tuple

获取和设置颜色(通过CMY色彩空间)。CMY即青色、品红色、黄色。C, M, Y值的范围都在0-1之间。

hsva -> tuple

获取和设置颜色(通过HSVA色彩空间)。HSVA即色调、饱和度、亮度、不透明度。各个值的范围是H = [0, 360], S = [0, 100], V = [0, 100], A = [0, 100]

hsla -> tuple

获取和设置颜色(通过HSLA色彩空间)。HSLA和HSVA类似。各个值的范围是 H = [0, 360], S = [0, 100], L = [0, 100], A = [0, 100]。

i1i2i3 -> tuple

获取和设置颜色(通过I1I2I3)。各个值的范围是I1 = [0,1], I2 = [-0.5, 0.5], I3 =[-0.5, 0.5]

normalize() -> tuple

返回颜色的RGBA形式,每个值都在0-1之间(注意:不是0-255之间)。

correct_gamma (gamma) -> Color

应用颜色伽马值并返回一个新的颜色对象。

lerp(Color, float) -> Color

返回当前颜色和给定颜色的线性插值。float是一个[0, 1]之间的浮点数,表示当前颜色和给定颜色的距离。例如float设为0则返回当前颜色本身,设为1则返回给定颜色,设为0.5则返回两个颜色的平均值。

premul_alpha() -> Color

返回一个新的颜色对象,A值和原本的颜色一样,而其中R, G, B值为原RGB值分别乘以A/255的结果。(用于预乘混合)

update(r, g, b) -> None

update(r, g, b, a=255) -> None

update(color_value) -> None

重设颜色。

9.3 颜色列表

pg.color模块中还提供了一个字典属性THECOLORS,键为颜色名称,值为颜色的RGBA元组。形如:

{'aliceblue': (240, 248, 255, 255), 
 'antiquewhite': (250, 235, 215, 255),
 ...

关于pygame所有颜色已经整理到了此PDF文件中,点击前往查看:pygame_colors.pdf

10 进阶表面操作

参考资料:

https://pyga.me/docs/ref/surface.html

https://pyga.me/docs/ref/image.html

https://pyga.me/docs/ref/transform.html

https://pyga.me/docs/ref/mask.html

10.1 Surface

pygame表面对象用于表示任何的图像,有固定的分辨率和格式。表面对象的每个像素占8位,通过调色板映射到24位颜色。在载入不同的图片时可能会有不同。

Surface((width, height), flags=0, depth=0, masks=None) -> Surface
Surface((width, height), flags=0, Surface) -> Surface

pg.Surface创建一个表面对象。默认是全黑的,唯一需要的参数是表面的大小。如果没有指定其他额外的参数,将以最佳的格式创建。

flags指定表面的附加特征。可以用一些常量通过按位或运算符进行组合,然后传递给flags参数。可选参数有SRCALPHA,表示给表面的单个像素添加透明通道。

同时表面还包括一些额外的属性,如颜色键、透明平面、剪裁矩形。

pygame表面支持三种类型的透明设置:颜色键、表面透明度、单个像素透明度。颜色键即colorkey,可以让指定颜色显示为完全透明的状态。表面透明度即整个Surface表面的像素透明度。单个像素透明度的设置也是支持的。

10.2 表面格式转换

操作表面之前,有时需要进行格式的转换,特别是较大的图片。这样可以使表面的绘制最优化,提高绘制的性能。

表面的convert和convert_alpha就提供了这样的功能,同时会对表面进行优化,使其绘制速度更快。返回经过优化的Surface对象。不同的是,convert方法在转换时会去掉表面所有的alpha通道,这意味着透明背景的图片载入进来后调用convert后,背景会变得不透明。而convert_alpha会保留原有图片的alpha通道,同时还允许像素进行透明度设置,相当于添加了SRCALPHA。

convert方法常用于载入较大的无需透明通道的背景图片。例如:

bg = pg.image.load("bg.png").convert()

10.3 表面透明度

set_alpha用于设置整个表面的透明度。范围是0-255,255表示不透明,0表示完全透明。

Surface.set_alpha(value, flags=0) -> None
Surface.set_alpha(None) -> None

如果设为None,则表示禁用所有alpha,包括单个像素的透明度。

flags参数如果设为pg. RLEACCEL,在更改透明度时速度会稍慢,但是绘制时的速度会更快。

此外还有一个函数get_alpha(),用于返回当前表面的透明度。

表面透明度常用于制作淡出淡入动画,如下示例:

import pygame as pg 

class FadeIn:
    def __init__(self, surf):
        self.surf = surf
        self.surf.set_alpha(0) #先隐藏

    def draw(self, screen, dest):
        screen.blit(self.surf, dest)
        
    def update(self):
        alpha = self.surf.get_alpha() + 2 #获取透明度并+2
        if alpha < 255:
            self.surf.set_alpha(alpha)
        
pg.init()
screen = pg.display.set_mode((400, 400))
clock = pg.time.Clock()

image = pg.image.load("logo.png")
fadein = FadeIn(image)

while True:
    screen.fill((0, 0, 0))

    fadein.draw(screen, (50, 50))
    fadein.update()
    
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()

    clock.tick(60)
    pg.display.flip()

运行效果:

Python pygame(GUI编程)模块最完整教程(3)_第1张图片

10.4 颜色键

颜色键可以将某个颜色变为透明色。但颜色键的功能更主要是用于精准碰撞检测(见后文)。颜色键设置使用set_colorkey方法。

Surface.set_colorkey(Color, flags=0) -> None
Surface.set_colorkey(None) -> None

Color是设为透明色的颜色对象,如果为None则表示取消所有colorkey设置。

和set_alpha一样,set_colorkey方法的flags参数同样支持传入pg. RLEACCEL,在绘制时获取更快的速度,但调用set_colorkey时速度稍慢。

示例如下:

import pygame as pg 

pg.init()
screen = pg.display.set_mode((450, 200))
clock = pg.time.Clock()

image = pg.image.load("logo.png")
image.set_colorkey((255, 255, 255)) #设置白色为透明色

while True:
    screen.fill((255, 0, 0)) #红色背景
    screen.blit(image, (20, 20))

    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()

    clock.tick(60)
    pg.display.flip()
Python pygame(GUI编程)模块最完整教程(3)_第2张图片

10.5 绘制表面

blit方法用于在一个表面上绘制另一个表面。

Surface.blit(source, dest, area=None, special_flags=0) -> Rect

其中source是当前表面上绘制的表面对象。dest是绘制的位置(相对于当前表面),可以是(x, y)元组或Rect之类的对象。area是一个矩形对象,表示将source进行剪裁后再绘制。special_flags是绘制图像的混合模式,类似于PS中图层混合。special_flags可通过一系列标识符进行按位或组合。

常用的混合模式有如下几种:

常量

解释

公式

BLEND_RGB_ADD

将两个表面的各个像素的颜色相加运算

BLEND_RGB_SUB

相减运算

BLEND_RGB_MULT

正片叠底

BLEND_RGB_MIN

变暗

BLEND_RGB_MAX

变亮

注意:P是运算后像素颜色值,A是当前表面的像素颜色值,B是source表面的像素颜色值,(x,y)是运算后的位置
参考资料: https://baike.baidu.com/item/%E6%B7%B7%E5%90%88%E6%A8%A1%E5%BC%8F/6700481

以上列举的常量只对RGB三个通道有效。如果想在计算时把Alpha通道算进来,可以用BLEND_RGBA_前缀的几个常量,其余后缀不变。

示例如下:

import pygame as pg
from pygame.locals import *

pg.init()
screen = pg.display.set_mode((450, 200))

image = pg.image.load("logo.png")
image.blit(image, (20, 20), special_flags=BLEND_RGB_MULT) #正片叠底

while True:
    screen.fill((255, 0, 0)) #红色背景
    screen.blit(image, (20, 20))

    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()

    pg.display.flip()
Python pygame(GUI编程)模块最完整教程(3)_第3张图片

除了blit,Surface还提供了blits方法快捷地绘制多张图片。

Surface.blits(blit_sequence=((source, dest), ...), doreturn=1) -> [Rect, ...] or None
Surface.blits(((source, dest, area), ...)) -> [Rect, ...]
Surface.blits(((source, dest, area, special_flags), ...)) -> [Rect, ...]

可以传递一个列表,其中包含一系列用于blit的参数元组。如果doreturn设为True,则返回所有表面的矩形对象。

10.6 剪裁矩形

通过设置剪裁矩形,可以在一个表面上划定一个矩形的范围,只能修改这个范围内的像素,而超出这个范围的像素不能被修改。

Surface.set_clip(rect) -> None
Surface.set_clip(None) -> None

set_clip方法用于设置剪裁矩形,如果设为None则取消设置剪裁矩形。

import pygame as pg
from pygame.locals import *

pg.init()
screen = pg.display.set_mode((450, 200))

image = pg.image.load("logo.png")
image.set_clip(pg.Rect(50, 50, 100, 100))
image.fill((255, 255, 255))

while True:
    screen.fill((0, 0, 0))
    screen.blit(image, (20, 20))

    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()

    pg.display.flip()
Python pygame(GUI编程)模块最完整教程(3)_第4张图片

上面的代码设置了一个剪裁区域,位于(50, 50),宽高都是100(区域超出范围的部分将忽略)。接下来调用fill方法,只修改了剪裁区域的部分,并没有将整个表面都涂成白色。

10.7 子表面

在pygame中支持子表面,也就是与父表面共享像素的一个表面。通过子表面可以实现图像裁剪。

Surface.subsurface(Rect) -> Surface

subsurface方法返回一个子表面对象。subsurface将当前表面的Rect指定的面积部分剪裁下来,形成一个新的表面对象。但是这个新的表面对象和原来的父表面是共享像素的,这意味着修改父表面与子表面重合的像素部分会同时影响两个表面(如果想要去掉这个限制可以使用Surface.copy()方法复制表面)。

一个父表面可以有多个子表面,子表面也可以有自己的子表面。

以下是关于子表面实现图像裁剪的实例:

import pygame as pg
from pygame.locals import *

pg.init()
screen = pg.display.set_mode((450, 200))

image = pg.image.load("logo.png").subsurface((0, 0, 200, 100))

while True:
    screen.fill((0, 0, 0))
    screen.blit(image, (20, 20))

    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()

    pg.display.flip()
Python pygame(GUI编程)模块最完整教程(3)_第5张图片

10.8 调色板

对于简单的8-bit表面(如gif图片),pygame提供了调色板功能,可以快速地替换颜色。

注意:如果不是8-bit的表面无法使用调色板,需要使用convert进行转换后才能使用调色板。但是这种方法会把较复杂的图片转换成纯色表面,所以不是8-bit图片不建议使用调色板。
转换方式如下:
image = image.convert(8)

首先需要理解调色板的意思。在8-bit深度的表面中,支持的颜色一共有256色(并不多)。每个颜色都储存在一个调色板集合中,每一项都是一个颜色值。只要更改调色板中的颜色值,就可以替换调色板中的颜色了。

Surface.get_palette() -> [RGB, RGB, RGB, ...]
Surface.set_palette([RGB, RGB, RGB, ...]) -> None
Surface.get_palette_at(index) -> RGB
Surface.set_palette_at(index, RGB) -> None

get_palette方法返回调色板列表对象,set_palette方法设置调色板列表对象。get_palette_at方法需要一个索引,返回调色板列表中位于index位置的颜色值;set_palette_at则用于设置在调色板中位于index位置的颜色值。

示例如下:

import pygame as pg
from pygame.locals import *

pg.init()
screen = pg.display.set_mode((450, 200))

image = pg.image.load("logo.gif")

p = image.get_palette() #获取调色板
image.set_palette_at(p.index((255, 255, 255)), (0, 0, 0)) #替换颜色

while True:
    screen.fill((0, 0, 0))
    screen.blit(image, (20, 20))

    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()

    pg.display.flip()

运行后,所有白色的部分变成了黑色。

Python pygame(GUI编程)模块最完整教程(3)_第6张图片

注意调色板只对8-bit颜色表面有效,所以对于png这样的文件不管用。

10.9 Surface对象方法索引

blit(source, dest, area=None, special_flags=0) -> Rect

绘制表面

blits(blit_sequence=((source, dest), ...), doreturn=1) -> [Rect, ...] or None

blits(((source, dest, area), ...)) -> [Rect, ...]

blits(((source, dest, area, special_flags), ...)) -> [Rect, ...]

绘制多个表面

convert(Surface=None) -> Surface

convert(depth, flags=0) -> Surface

convert(masks, flags=0) -> Surface

转换表面像素格式,depth表示深度,如:depth=8表示使用8-bit的颜色。

convert_alpha(Surface) -> Surface

convert_alpha() -> Surface

使表面包括Alpha功能。

copy() -> Surface

复制表面。

fill(color, rect=None, special_flags=0) -> Rect

填充表面,rect是填充范围,speical_flags和blit的speical_flags一样。

scroll(dx=0, dy=0) -> None

将表面中的像素移动(dx, dy)。

set_colorkey(Color, flags=0) -> None

set_colorkey(None) -> None

设置颜色键,None为取消颜色键。

get_colorkey() -> RGB or None

获取颜色键

set_alpha(value, flags=0) -> None

set_alpha(None) -> None

设置表面透明度

get_alpha() -> int_value

获取表面透明度

get_at((x, y)) -> Color

获取某个像素点的颜色

set_at((x, y), Color) -> None

设置某个像素点的颜色

get_palette() -> [RGB, RGB, RGB, ...]

获取depth=8表面中的调色板

get_palette_at(index) -> RGB

获取depth=8表面调色板中位于index索引位置的值

set_palette([RGB, RGB, RGB, ...]) -> None

设置depth=8表面中的调色板

set_palette_at(index, RGB) -> None

设置depth=8表面调色板中位于index索引位置的值

set_clip(rect) -> None

set_clip(None) -> None

设置剪裁区域,None表示取消剪裁区域。

get_clip() -> Rect

获取剪裁区域

subsurface(Rect) -> Surface

返回共享像素的子表面

get_parent() -> Surface

获取父表面

get_abs_parent() -> Surface

获取最顶层的父表面

get_offset() -> (x, y)

获取子表面相对于父表面的位置偏移距离

get_abs_offset() -> (x, y)

获取子表面相对于最顶层父表面的位置偏移距离

get_size() -> (width, height), get_width() -> width, get_height() -> height

分别表示:获取表面的宽高元组、获取表面的宽、获取表面的高。

get_rect(**kwargs) -> Rect

获取表面的矩形对象,**kwargs中可设置位置,如: center=5。

get_bounding_rect(min_alpha = 1) -> Rect

获取表面的最小矩形对象。表面外围透明度低于min_alpha的部分将会被去掉。

get_bitsize() -> int, get_bytesize() -> int

分别获取每个像素的位数(bit)和字节数(byte),8 bit = 1 byte。位数也就是图像的depth。

get_view(='2') -> BufferProxy

将表面的内部像素缓冲区导出为数组。kind参数是长度为1的字符串'0','1','2','3','r', 'g', 'b',或'a'。'0'返回连续的非结构化字节视图,'1'返回一个(表面宽度*表面高度)连续像素数组,'2'返回一个(surface-width, surface-height)原始像素数组(默认值),'3'返回一个(surface-width, surface-height, 3) RGB颜色数组,'r','g','b','a'分别表示返回单个颜色平面数组。只有depth=32的表面且表面的flags参数设为SRCALPHA才支持'a'。

注:像素缓冲区中包含一个图片所有像素的颜色信息。如下图是一张3x3大小的PNG图片,第一列被填充为红色,第二列被填充为绿色,第三列被填充为蓝色。
如果将它的像素缓冲区导出,原始码是这样的:
b'\xff\x00\x00\xff\x00\xff\x00\xff\x00\x00\xff\xff\xff\x00\x00\xff\x00\xff\x00\xff\x00\x00\xff\xff\xff\x00\x00\xff\x00\xff\x00\xff\x00\x00\xff\xff'
可以看出,在PNG图像像素缓冲区的原始码中,四个十六进制数代表了一个像素(\x00表示十六进制数0,\xff表示十六进制数255),分别表示每个像素的RGBA四个值,从左到右,从上到下排列。通过分析原始码可以发现\xff\x00\x00\xff也就是前4个数刚好对应位于(0, 0)的红色。
如果图片更大更复杂,原理也是一样的。
像OpenCV这样的图像处理模块,将像素缓冲区导出后会形成一个numpy.array数组,每个项目都是一个像素的颜色值,可能这样更容易理解。
get_view和下面的get_buffer方法都返回时一个BufferProxy对象,将在后面讲解。BufferProxy对象有一个raw属性表示像素缓冲区导出后的原始码。以下方式可以查看:
print(img.get_view().raw)
像素缓冲区的原始码的应用主要是在网络传输时。Surface不能直接进行网络通信,但是转换成字节码就可以。关于像素缓冲区和表面的转换将在10.11详解。

get_buffer() -> BufferProxy

为表面生成一个像素缓冲区。

10.10 图像载入与保存

pg.image.load用于载入图像,pg.image.save用于保存图像。load方法需要提供一个文件名参数,save方法需要提供一个表面对象和文件名参数。

示例:

import pygame as pg

img = pg.image.load("logo.png")
img.fill((255, 0, 0))
pg.image.save(img, "red.png")

运行后当前目录下出现一个红色的图片red.png。

10.11 像素缓冲区和表面的转换

除了Surface的方法get_view和get_buffer可以用于表面转换为像素缓冲区外,image模块有一些更高级的转换方法。pg.image.tobytes和frombytes在表面、像素缓冲区的原始码之间转换;frombuffer函数直接通过像素缓冲区导入表面。

tobytes(Surface, format, flipped=False) -> bytes
frombytes(bytes, size, format, flipped=False) -> Surface
frombuffer(buffer, size, format) -> Surface

flipped参数指定是否将表面垂直翻转,这是由于部分图像模块(如OpenGL)使用从下到上的模式。

format参数指定缓冲区的格式,是一个字符串,可用参数如下表:

参数(字符串)

解释

P

8-bit使用调色板的表面(只适用于depth=8的表面,而下面的24-bit和32-bit并不代表只适用于24位和32位的表面)

RGB

24-bit图像,像素顺序为RGB

BGR

24-bit图像,像素顺序为BGR(只适用于frombuffer方法)

RGBX

32-bit图像,像素顺序为RGBA,未使用空间

RGBA

32-bit图像,像素顺序为RGBA

ARGB

32-bit图像,像素顺序为ARGB(即透明通道放在每个像素首位)

BGRA

32-bit图像,像素顺序为BGRA

RGBA_PREMULT

32-bit图像,像素顺序为RGBA,且经过预乘。(只适用于frombytes和tobytes)

ARGB_PREMULT

32-bit图像,像素顺序为ARGB,且经过预乘。(只适用于frombytes和tobytes)

在导入像素缓冲区为表面时,还需要指定size,这是一个元组表示宽和高。需要这个参数的原因是,在像素缓冲区导出时是不会区分每一行每一列的。

10.12 image模块索引-图像操作

load(filename) -> Surface

load(fileobj, namehint="") -> Surface

载入图片

save(Surface, filename) -> None

save(Surface, fileobj, namehint="") -> None

保存图片

tobytes(Surface, format, flipped=False) -> bytes

将表面导出为字节码

frombytes(bytes, size, format, flipped=False) -> Surface

将字节码导入为表面

frombuffer(buffer, size, format) -> Surface

将像素缓冲区对象BufferProxy转换为表面。

10.13 transform模块索引-变换表面

pygame.transform模块提供了变换表面的操作,如旋转、缩放等,并返回新的Surface对象。下面列举该模块中主要函数。

flip(surface, flip_x, flip_y) -> Surface

翻转表面,flip_x表示是否水平翻转,flip_y表示是否垂直翻转。

scale(surface, size, dest_surface=None) -> Surface

缩放表面,size表示缩放后的宽和高。dest_surface是可选的,如果指定dest_surface(和surface必须同样像素格式和大小)将不会重新创建一个表面而是将结果输出到dest_surface。

scale_by(surface, factor, dest_surface=None) -> Surface

按比例缩放表面。例如factor=2则表示放大为原来的2倍,factor=(2, 3)表示宽放大为原来的2倍但是高放大为原来的3倍。

rotate(surface, angle) -> Surface

旋转表面,angle表示角度。正数为逆时针旋转,负数为顺时针旋转。

rotozoom(surface, angle, scale) -> Surface

同时进行旋转和缩放运算。angle表示逆时针旋转的角度(相当于rotate的angle),scale表示缩放的比例(相当于scale_by的factor)。

scale2x(surface, dest_surface=None) -> Surface

将表面放大2倍。相当于scale_by(surface, 2, dest_surface=None) -> Surface

smoothscale(surface, size, dest_surface=None) -> Surface

平滑地缩放表面,size是缩放后的宽高。

smoothscale_by(surface, factor, dest_surface=None) -> Surface

平滑地缩放表面,factor是缩放比例。

chop(surface, rect) -> Surface

按指定rect矩形裁剪表面。相当于surface.subsurface(rect).copy() -> Surface。

laplacian(surface, dest_surface=None) -> Surface

对表面进行拉普拉斯运算(是一个获得图像边缘信息的算法)。

average_surfaces(surfaces, dest_surface=None, palette_colors=1) -> Surface

通过给定的表面列表surfaces,返回多个表面像素颜色的平均值。

average_color(surface, rect=None, consider_alpha=False) -> Color

对指定surface中rect矩形区域的像素计算颜色的平均值并返回。如果consider_alpha=True,则透明度值也会被算进来。

threshold(dest_surface, surface, search_color, threshold=(0,0,0,0), set_color=(0,0,0,0), set_behavior=1, search_surf=None, inverse_set=False) -> num_threshold_pixels

表面阈值处理,这个函数将会在一个表面中搜索符合一个范围内的颜色,根据参数,将匹配或不匹配颜色范围的像素更改到目标表面上。这个函数会返回匹配颜色范围的像素数量。

surface参数表示进行阈值搜索的表面。dest_surface表示目标表面。

search_color是在这个表面中搜索的颜色。

threshold是需要搜索的颜色与search_color之间的容差。例如search_color=(255, 255, 255, 255),,threshold=(0, 30, 30, 0),那么可以匹配颜色值在(255,225-285,225-285,225)这个范围内的颜色。

set_behavior设置做出的行为,默认为1。set_behavior=1表示将surface搜索到的像素输出到dest_surface。设为0表示只计算不进行表面的更改,此时需要设置dest_surface=None。设为2表示原地修改,即将搜索到的像素输出到surface,此时也需要设置dest_surface=None。

search_surf参数可以替代search_color,两个参数只能设定一个。如果指定了search_surf(一个表面对象),那么进行阈值搜索的表面像素将会和search_surf的表面像素对应搜索。surface表面位于(0, 0)和search_surf表面位于(0, 0)的颜色进行匹配,位于(1, 0)和(1, 0)的像素进行匹配,以此类推。这个参数可以得到两个表面颜色相同的部分。

inverse_set参数表示输出在目标表面上的结果是匹配的结果还是不匹配的结果。如果为False(默认),则目标表面上的结果是搜索匹配的结果,为True则表示不匹配的结果。

下面通过logo.png进行不同阈值运算后的结果进一步说明。

代码

效果

pg.transform.threshold(image, image, (255, 255, 255))

#显示匹配到白色的部分

Python pygame(GUI编程)模块最完整教程(3)_第7张图片

pg.transform.threshold(image, image, (255, 255, 255), inverse_set=True)

#显示不匹配到白色的部分

Python pygame(GUI编程)模块最完整教程(3)_第8张图片

pg.transform.threshold(image, image, (255, 255, 255), threshold=(50, 50, 50), inverse_set=True)

#包括一些近似白色的颜色(和白色的颜色值相差在50以内)也匹配进来,显示不匹配到的部分

Python pygame(GUI编程)模块最完整教程(3)_第9张图片

10.14 mask模块索引-掩码

pygame.mask模块提供了一些有关图像掩码(蒙版)的操作。通过mask的方法,可以生成一个掩码对象,这个对象类似于表面,但是一个二值图,每个像素点都是一个二进制数字的1或0(而不是一个颜色)。1或0分别表示图像中不透明的部分和完全透明的部分。

from_surface(surface) -> Mask

from_surface(surface, threshold=127) -> Mask

通过表面生成一个Mask对象,threshold是阈值,表示透明度大于这个数字的会被记作1(设置了colorkey将忽略这个参数)。

计算公式:

from_threshold(surface, color) -> Mask

from_threshold(surface, color, threshold=(0, 0, 0, 255), othersurface=None, palette_colors=1) -> Mask

通过阈值生成掩码对象。color类似于transform.threshold方法中的search_color,othersurface类似于search_surf。

Mask(size=(width, height)) -> Mask

Mask(size=(width, height), fill=False) -> Mask

掩码对象。

Mask.copy() -> Mask

复制掩码。

计算公式:

Mask.get_size() -> (width, height)

获取掩码的尺寸。

Mask.get_rect(**kwargs) -> Rect

获取掩码的矩形。

Mask.get_at(pos) -> int

获取掩码位于pos的值(是否为不透明),返回1或0。

Mask.set_at(pos) -> None

Mask.set_at(pos, value=1) -> None

设置掩码位于pos的值,value可以是1或0。

计算公式:

Mask.overlap(other, offset) -> (x, y)

Mask.overlap(other, offset) -> None

返回两个掩码的第一个交点,offset是偏移量(将在后文碰撞检测一章详解)。

注意:offset是两个掩码位置的偏移,是将other掩码的位置与调用这个方法的掩码的位置相减得到的向量结果。也可以理解为是other掩码在当前掩码上的位置。

Mask.overlap_area(other, offset) -> numbits

返回重叠掩码的数量。

Mask.overlap_mask(other, offset) -> Mask

返回重叠掩码组成的新掩码对象。

计算公式:

将对应像素进行按位与计算。

Mask.fill() -> None

将所有的掩码值设为1。

计算公式:

Mask.clear() -> None

将所有的掩码值设为0。

计算公式:

Mask.invert() -> None

将所有的掩码值进行取反操作(0变成1,1变成0)

计算公式:

Mask.scale((width, height)) -> Mask

缩放掩码对象。

Mask.draw(other, offset) -> None

把一个掩码对象绘制到当前掩码对象,offset是位置。

计算公式:

将对应像素进行按位或计算。

Mask.erase(other, offset) -> None

把一个掩码对象从当前掩码上减去,offset是位置。

计算公式:

将对应像素进行按位异或运算。

Mask.count() -> bits

返回当前掩码上设为1的掩码数量。如果没有设为1的掩码则返回(0, 0)

Mask.centroid() -> (x, y)

返回掩码上设为1的掩码的中心点位置。

Mask.angle() -> theta

通过一种算法计算掩码中设为1的掩码的大致方向(从-90度到90度)。如果没有为1的掩码则返回0。

Python pygame(GUI编程)模块最完整教程(3)_第10张图片

angle() -> -45.0

angle() -> 6.8(约等于)

Python pygame(GUI编程)模块最完整教程(3)_第11张图片

angle() -> -20.9(约等于)

Mask.outline() -> [(x, y), ...]

Mask.outline(every=1) -> [(x, y), ...]

返回选中点的轮廓像素点的列表。如果指定every,那么将会跳过一部分的像素点。

Python pygame(GUI编程)模块最完整教程(3)_第12张图片

every=1(默认)

Python pygame(GUI编程)模块最完整教程(3)_第13张图片

every=10(以10为步长跳过了一些像素点)

Mask.convolve(other, output=None, offset=(0, 0)) -> Mask

卷积运算。

Mask.connected_component() -> Mask

Mask.connected_component(pos) -> Mask

通过Mask中设为1并且相互连接的点(通常称作组件)生成一个新的Mask对象(通过计算8点相邻的SAUF算法)。如果给定pos,则通过与pos相连接的点生成Mask对象。

Python pygame(GUI编程)模块最完整教程(3)_第14张图片

原图

Python pygame(GUI编程)模块最完整教程(3)_第15张图片

pos=(20, 20)得到的结果(20,20在三角形上)

Mask.connected_components() -> [Mask, ...]

Mask.connected_components(minimum=0) -> [Mask, ...]

返回一系列连接组件的Mask对象。minimum表示如果连接的点的数量小于这个值则被忽略(用于过滤一些噪声)。例如对于上图,则会返回一个包含两个Mask的列表,一个列表记录了三角形图案的Mask,另一个记录了圆形图案的Mask。

Mask.get_bounding_rects() -> [Rect, ...]

返回一个列表,包含所有连接组件的矩形信息。

Mask.to_surface() -> Surface

Mask.to_surface(surface=None, setsurface=None, unsetsurface=None, setcolor=(255, 255, 255, 255), unsetcolor=(0, 0, 0, 255), dest=(0, 0)) -> Surface

将Mask对象转换为Surface对象。

如果给定surface参数和dest参数,则将转换后得到的表面绘制到该表面上,位于dest处。

如果指定setcolor和unsetcolor,则将所有为1的点在转换为表面后用setcolor颜色进行填充,所有为0的点用unsetcolor填充。

如果指定setsurface和unsetsurface(两个表面对象),则将值为1的点用处于setsurface相同位置的像素点的颜色填充,将为0的点用处于unsetsurface相同位置的像素点的颜色填充。

import pygame as pg 
from pygame.locals import *

pg.init()
screen = pg.display.set_mode((440, 200), pg.RESIZABLE)

image = pg.image.load("logo2.png")
mask = pg.mask.from_surface(image)
image = mask.to_surface(setcolor=(255, 0, 0), unsetcolor=(255, 0, 0, 150))

while True:
    screen.fill((0, 0, 0))
    screen.blit(image, (20, 20))
    
    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()

    pg.display.flip()
Python pygame(GUI编程)模块最完整教程(3)_第16张图片

下一篇文章

https://blog.csdn.net/qq_48979387/article/details/128994501

你可能感兴趣的:(Python,pygame,python)