如何使用图像的 RGBA 值列表在 Pygame 中显示图像

How to display an image in Pygame using list of RGBA values of a image

我正在尝试制作一个涉及一些图像的 pygame 项目。在这些图像中,有些非常相似,只是颜色发生了变化。所以我想出了为什么不只使用一张图像并使用 Python from this article.

更改其相应颜色的想法
from PIL import Image
import pygame as pg

img = Image.open("Assets/image.png")
img = img.convert("RGBA")
d = img.getdata()
new_image = []
for item in d:
    if item[:3] == (0,0,0):
        new_image.append((255,255,255,0))
    if item[:3] == (23,186,255):
        new_image.append((255,38,49,item[3]))
    else:
        new_image.append(item)
img.putdata(new_image)
img.save("a.png","PNG")

但是在上面代码的最后两行中,它保存了图像,我不想要那个!
我想在 Pygame 代码中使用它来显示,然后当程序退出时图像就消失了。那么如何使用 RGBA 值列表 new _image 在 Pygame.
中显示图像 任何帮助将不胜感激。

使用 pygame.image.frombuffer() to create a pygame.Surface. However you have to convert the list to a byte array. Use the ctypes 模块从列表创建字节数组:

flat_list = [e for c in new_image for e in c]
bute_array = (ctypes.c_ubyte * len(flat_list))(*flat_list)
surf = pg.image.frombuffer(bute_array, img.size, img.mode).convert_alpha()

另见 PIL and pygame.image

请注意您的算法中存在错误。您需要在中间情况下使用 elif 而不是 if

if item[:3] == (0,0,0):
    new_image.append((255,255,255,0))

#if item[:3] == (23,186,255):
elif item[:3] == (23,186,255):              # <---

    new_image.append((255,38,49,item[3]))
else:
    new_image.append(item)

注意:如果要将背景更改为白色,需要将颜色设置为不透明:

new_image.append((255,255,255,0))

new_image.append((255, 255, 255, 255))

最小示例:

左图为测试图,右图为结果:

from PIL import Image
import pygame as pg
import ctypes

img = Image.open("Assets/image.png")
img = img.convert("RGBA")
d = img.getdata()
new_image = []
for item in d:
    if item[:3] == (0, 0, 0):
        new_image.append((255, 255, 255, 0))
        #new_image.append((255, 255, 255, 255))
    elif item[:3] == (23, 186, 255):
        new_image.append((255, 38, 49, item[3]))
    else:
        new_image.append(item)

pg.init()
window = pg.display.set_mode(img.size)

flat_list = [e for c in new_image for e in c]
bute_array = (ctypes.c_ubyte * len(flat_list))(*flat_list)
surf = pg.image.frombuffer(bute_array, img.size, img.mode).convert_alpha()

run = True
while run:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False 

    window.fill(0)
    window.blit(surf, (0, 0))
    pg.display.flip()

pg.quit()

旁注:

您不需要使用 PLI 加载图像,您可以直接访问 pygame.Surface 的像素。有不同的选择:

我可能完全忽略了你问题的重点,但据我了解,你想要加载图像并更改一些颜色。我会这样做:

#!/usr/bin/env python3

from PIL import Image
import pygame as pg
import numpy as np

# Open image and ensure RGBA mode, not palette image
img = Image.open("image.png").convert('RGBA')

# Define some colours for readability
black = [0,0,0]
white = [255,255,255]
red   = [255,0,0]
blue  = [0,0,255]

# Make image into Numpy array for vectorised processing
na  = np.array(img)

# Make re-usable mask of black pixels then change them to white
mBlack = np.all(na[...,:3] == black, axis=-1)
na[mBlack,:3] = white
# Make re-usable mask of red pixels then change them to blue
mRed  = np.all(na[...,:3] == red, axis=-1)
na[mRed,:3] = blue

pg.init()
window = pg.display.set_mode(img.size)

surf = pg.image.frombuffer(na.tobytes(), img.size, img.mode)

run = True
while run:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

    window.fill(0)
    window.blit(surf, (0, 0))
    pg.display.flip()

pg.quit()

制作此图像的原因:

显示如下:

所以你可以看到我制作的面具的威力,你可以这样做:

# Make any pixels that were either red or black become magenta
na[mRed|mBlack,:3] = [255,0,255]

或者:

# Make all pixels that were not black into cyan
na[~mBlack,:3] = [0,255,255]