I am trying to make a pygame project which involves some images. In these images some are very similar and there is just a change of colour. So I came up with idea that why not to use only one image and change its corresponding colour using 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")
But in the last two lines of the above code its saving the image and I don't want that!
I want to use it in the Pygame code for displaying and then when the program exits the image is gone. So how can I use a list of RGBA values new _image
to display an image in Pygame.
Any help would be appreciated.
Use pygame.image.frombuffer()
to create a pygame.Surface
. However you have to convert the list to a byte array. Use the ctypes
module to make a byte array from a list:
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()
See also PIL and pygame.image.
Notice that there is a bug in your algorithm. You need to use elif
instead of if
in the middle case:
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)
Note: if you want to change the background to a white color, you need to make the color opaque:
new_image.append((255,255,255,0))
new_image.append((255, 255, 255, 255))
Minimal example:
The left image is the test image and the right image is the result:
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()
Side note:
You don't need to load the image using PLI you can access the pixels of a pygame.Surface
directly. There are different options:
get_at
/ set_at
pygame.PixelArray
objectpygame.surfarray
module