URLhttps://learnscript.net/zh/pygame/image/
    复制链接转到说明  示例

    如何加载和保存游戏图像?以及图像与字节序列的转换等问题

    我被代码海扁署名-非商业-禁演绎
    阅读 16:56·字数 5082·更新 

    虽然本节的示例中包含绘制图像的代码,但本节不会讲解与图像绘制相关的问题,要了解绘制,请查看如何绘制表面(图像,字体)?以及颜色混合模式,剪辑区域,锁定等问题一节。

    Pygame 中的 image 模块

    Pygame 包的image模块,包含了与图像相关的功能,主要涉及图像的载入,图像的保存,以及图像的转换,当你导入pygame模块时,image模块会被pygame模块导入。事实上,Pygame 包并不包含一个名称为Image的类,image模块只会返回或操作绘制了图像的Surface对象。

    判断游戏是否支持扩展的图像格式

    image模块的get_extended函数,可用于判断游戏是否支持扩展的图像格式,这通常取决于你所安装的 Pygame 版本,但无论如何,Pygame 总是支持未压缩的bmp图像格式。

    get_extended()

    返回值

    如果get_extended函数返回True,那么表示游戏支持扩展的图像格式。

    extended.py
    from pygame import image
    
    print(f'支持扩展的图像格式?{image.get_extended()}')
    支持扩展的图像格式?True

    为游戏加载图像

    image模块的loadload_basicload_extended函数,可用于加载图像并返回一个绘制了图像的Surface表面对象,其中,loadload_extended函数可以自行判断图像的格式,但有时需要通过文件的扩展名来完成此目标,load_basic函数则只能加载bmp格式的图像。

    当 Pygame 不支持扩展的图像格式时,image模块的load_extended函数会引发异常NotImplementedError: loading images of extended format is not available。至于如何判断 Pygame 是否支持扩展的图像格式,你可以查看判断游戏是否支持扩展的图像格式一段。

    load(filename, namehint='')
    load_basic(filename)
    load_extended(filename, namehint='')

    filename 参数

    filename参数是表示图像文件路径的字符串,或包含图像文件路径的类路径(path-like)对象,或包含图像数据的IO对象。

    namehint 参数

    namehint参数是一个用于提示文件扩展名的字符串,如果filename参数是一个IO对象,并且你希望传递文件扩展名的话。

    返回值

    loadload_basicload_extended函数的返回值是绘制了图像的Surface表面对象。

    load,load_extended 函数能够加载的图像格式有哪些?

    如果 Pygame 支持完整的扩展图像格式,那么loadload_extended函数能够加载以下的图像格式,bmpgif(不支持动画),jpegjpg),lbmpbmpgmppm),pcxpngpnmsvg(有限的支持),tga(非压缩),tifftif),webpxpm

    load,load_basic,load_extended 函数所返回的 Surface 对象需要进行转换

    在大部分情况下,你需要对loadload_basicload_extended函数所返回的Surface对象进行转换,调用他们的convertconvert_alpha方法,以便在窗口中快速进行绘制。

    在下面的示例中,我们使用 Python 的open函数打开了图像文件sky.webp,并将返回的IO对象传递给了load函数。

    load.py
    # 在运行脚本前,请将命令行跳转至 load.py 所在的目录
    from pygame import image, display
    
    # 通过 IO 对象加载图像文件 sky.webp data = open('sky.webp', 'rb') sky = image.load(data)
    # 直接加载图像文件 candy.png candy = image.load_extended('candy.png')
    # 创建游戏窗口,绘制天空和糖果,并等待 2 秒钟 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) s.blit(candy, (100, 100)) display.flip()
    import time time.sleep(2)

    将游戏画面保存为图像

    image模块的savesave_extended函数,可用于将绘制了图像的Surface表面对象保存为文件或IO对象。一个游戏中可能包含多个Surface对象,他们也许绘制了游戏中的某个角色或窗口的整个显示区域。savesave_extended函数可根据文件的扩展名来决定图像格式,如果无法得知文件扩展名,那么图像格式将被认定为tga(非压缩)。

    当 Pygame 不支持扩展的图像格式时,save_extended函数会引发异常NotImplementedError: saving images of extended format is not available。至于如何判断 Pygame 是否支持扩展的图像格式,你可以查看判断游戏是否支持扩展的图像格式一段。

    save(surface, filename, namehint='')
    save_extended(surface, filename, namehint='')

    surface 参数

    surface参数是需要被转换的Surface表面对象。

    filename 参数

    filename参数是表示图像文件路径的字符串,或包含图像文件路径的类路径(path-like)对象,或可存储图像数据的IO对象。

    namehint 参数

    namehint参数是一个用于提示文件扩展名的字符串,如果filename参数是一个IO对象,并且你希望传递文件扩展名的话。

    save,save_extended 函数能够保存的图像格式有哪些?

    如果 Pygame 支持完整的扩展图像格式,那么savesave_extended函数能够将Surface表面对象保存为以下的图像格式,bmpjpegjpg),pngtga(非压缩)。

    save.py
    # 在运行脚本前,请将命令行跳转至 save.py 所在的目录
    from pygame import image, Surface
    
    # 加载图像文件,并将他们绘制在表面对象 surface 中 sky = image.load('sky.webp') candy = image.load_extended('candy.png')
    surface = Surface((800, 600)) surface.blit(sky, (0, 0)) surface.blit(candy, (100, 100))

    # 将 surface 保存至文件,图像格式为 jpg image.save(surface, 'combine.jpg')

    save,save_extended 函数所使用的 IO 对象需要改变指针位置才能被重新加载

    如果使用savesave_extended函数,将Surface表面对象保存至某个IO对象,那么可能需要将IO对象的指针移动至开头,才能使用image模块重新加载该IO对象。

    在下面的示例中,我们将Surface对象保存到了IO对象中,之后需要调用IO对象的seek方法将指针移动至开头,否则重新加载IO对象可能会导致异常pygame.error: Unsupported image format

    reload.py
    # 在运行脚本前,请将命令行跳转至 reload.py 所在的目录
    from pygame import image
    
    # 将 surface 保存至 IO 对象 import io bs = io.BytesIO() sky = image.load('sky.webp') # 指定图像格式为 png image.save(sky, bs, '.png')
    # 重新加载 IO 对象之前,需要将指针移动至开头 bs.seek(0) new_sky = image.load(bs, '.png')

    将图像转换为字节序列对象

    image模块的tobytes函数,可用于将绘制了图像的Surface表面对象转换为一个bytes字节序列对象。当你使用该函数时,通常是希望将游戏图像传递给其他 Python 包进行处理。

    image模块的tostring函数与tobytes函数相同,你可以将其中一个视为另一个的别名,但建议采用tobytes

    tobytes(surface, format, flipped=False)

    surface 参数

    surface参数是被转换为bytes字节序列的Surface表面对象。

    format 参数

    format参数是一个字符串,表示转换所采用的颜色格式,拥有以下有效取值,'P'(采用 8 位调色板表示颜色),'RGB'(使用 24 个 bit 表示颜色,按照红绿蓝的顺序),'RGBX'(使用 32 个 bit 表示颜色,按照红绿蓝的顺序,末尾的 8 个比特不被使用),'RGBA'(使用 32 个 bit 表示颜色,按照红绿蓝透明度的顺序),'ARGB'(使用 32 个 bit 表示颜色,按照透明度红绿蓝的顺序),'BGRA'(使用 32 个 bit 表示颜色,按照蓝绿红透明度的顺序),'RGBA_PREMULT'(使用 32 个 bit 表示颜色,按照红绿蓝透明度的顺序,其中红绿蓝已经预先与透明度进行了计算),'ARGB_PREMULT'(使用 32 个 bit 表示颜色,按照透明度红绿蓝的顺序,其中红绿蓝已经预先与透明度进行了计算)。

    flipped 参数

    flipped参数是一个布尔值(默认为False),如果为True,则相当于先将Surface对象表示的图像进行垂直翻转,然后再转换为bytes字节序列(这对于 Python PyOpenGL 包可能是有效的)。

    在下面的示例中,我们使用tobytes函数将Surface对象转换为bytes对象,然后使用PIL模块(需要安装)将bytes对象存储为图像文件pil.sky.webp

    to_bytes.py
    # 在运行脚本前,请将命令行跳转至 to_bytes.py 所在的目录
    from pygame import image
    
    # 将 Surface 对象转换为 bytes,颜色格式为 RGBA sky = image.load('sky.webp') bs = image.tobytes(sky, 'RGBA')
    # 使用 PIL 读取 bytes,并将图像保存为文件 pil.sky.webp import PIL.Image i = PIL.Image.frombytes('RGBA', (729, 1296), bs) i.save('pil.sky.webp')

    将字节序列对象转换为图像

    image模块的frombytes函数,可用于将bytes字节序列对象转换为一个表示图像的Surface表面对象。当你使用该函数时,bytes字节序列对象通常来自于其他 Python 包,这意味着要将其他包处理的图像转换为Surface对象。

    image模块的fromstring函数与frombytes函数相同,你可以将其中一个视为另一个的别名,但建议采用frombytes

    frombytes(bytes, size, format, flipped=False)

    bytes 参数

    bytes参数是被转换为Surface表面对象的bytes字节序列。

    size 参数

    size参数是一个形式类似于(width,height)的元组,或形式类似于[width,height]的列表,其中width为图像的宽度,height为图像的高度。

    你不能随意设置size参数,其表示的大小必须与bytes参数对应的图像的大小相同。

    format 参数

    format参数是一个字符串,表示转换所采用的颜色格式,拥有以下有效取值,'P'(采用 8 位调色板表示颜色),'RGB'(使用 24 个 bit 表示颜色,按照红绿蓝的顺序),'RGBX'(使用 32 个 bit 表示颜色,按照红绿蓝的顺序,末尾的 8 个比特不被使用),'RGBA'(使用 32 个 bit 表示颜色,按照红绿蓝透明度的顺序),'ARGB'(使用 32 个 bit 表示颜色,按照透明度红绿蓝的顺序),'BGRA'(使用 32 个 bit 表示颜色,按照蓝绿红透明度的顺序)。

    flipped 参数

    flipped参数是一个布尔值(默认为False),如果为True,则转换后的Surface对象所表示的图像会被垂直翻转。

    在下面的示例中,我们使用frombytes函数,将包含天空图像的bytes对象转换为了Surface对象,并对图像进行了垂直翻转。

    from_bytes.py
    # 在运行脚本前,请将命令行跳转至 from_bytes.py 所在的目录
    from pygame import image, display
    
    # 使用 PIL 读取图像文件,并转换为 bytes 对象 import PIL.Image bs = PIL.Image.open('sky.webp').tobytes()
    # 将 bytes 对象转换为 Surface 对象 sky = image.frombytes(bs, (729, 1296), 'RGB', True)
    # 创建游戏窗口,绘制天空,并等待 2 秒钟 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) display.flip()
    import time time.sleep(2)

    将字节缓冲转换为图像

    image模块的frombuffer函数,可用于将字节缓冲区中的内容转换为一个表示图像的Surface表面对象,该函数的参数的作用与frombytes函数类似,但存在以下不同。

    image模块的frombuffer函数的bytes参数可以是一个BufferProxybytesbytearraymemoryview,或遵守缓冲协议的对象。相对于frombytes函数,frombuffer函数的bytes参数额外支持'BGR'(使用 24 个 bit 表示颜色,按照蓝绿红的顺序)。

    frombuffer(bytes, size, format)

    frombuffer 函数拥有更高的执行效率

    相对于frombytes函数,frombuffer函数拥有更高的执行效率,因为没有分配和复制图像像素数据的过程。

    from_buffer.py
    # 在运行脚本前,请将命令行跳转至 from_buffer.py 所在的目录
    from pygame import image, display
    
    # 使用 PIL 读取图像文件,并转换为 bytes 对象 import PIL.Image bs = PIL.Image.open('sky.webp').tobytes()
    # 将 bytes 对象转换为 Surface 对象 sky = image.frombuffer(bs, (729, 1296), 'RGB', True)
    # 创建游戏窗口,绘制天空,并等待 2 秒钟 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) display.flip()
    import time time.sleep(2)

    获取 SDL_Image 的版本信息

    image模块的get_sdl_image_version函数,其返回值是一个元组,该元组包含了 SDL_Image 的版本信息。

    get_sdl_image_version(linked=True)

    linked 参数

    如果linked参数为True,则函数get_sdl_image_version返回当前所使用的 SDL_Image 的版本信息,否则返回 Pygame 包在编译时所针对的 SDL_Image 版本。

    返回值

    get_sdl_image_version函数的返回值是一个形式类似于(major,minor,patch)的 Python 元组,其中major表示主要版本号,minor表示次要版本号,patch表示补丁号。

    当你所安装的 Pygame 版本不支持扩展图像格式时,get_sdl_image_version函数将返回空值None,这反映了扩展图像格式的实现需要 SDL_Image。

    version.py
    from pygame import image
    
    # 获取 SDL_Image 版本 print(f'当前使用的 SDL_Image 版本:{image.get_sdl_image_version()}') print(f'编译时针对的 SDL_Image 版本:{image.get_sdl_image_version(False)}')
    当前使用的 SDL_Image 版本:(2, 0, 5)
    编译时针对的 SDL_Image 版本:(2, 0, 5)

    源码

    src/zh/image·codebeatme/pygame·GitHub

    讲解视频

    如何在 Pygame 中加载图像·YouTube如何在 Pygame 中加载图像·Bilibili