in my pygame game, to import jpeg image, I use convert()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert
then, to play with the image transparency (how much we can see trough the image), I use set_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha
However, to import my png image, which have a tranparent background, I use convert_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert_alpha
but with this way of importing, I can't play with the general transparency using set_alpha()
. Any other idea to adjust the transparency (how much we see trough the image) ?
Image -> Mode -> Convert to Color Profile... and use the defaults. Image -> Mode -> Indexed... and use the defaults.
convert and convert_alpha are both used to convert surfaces to the same pixel format as used by the screen. This ensures that you won't lose performance because of conversions when you're blitting them to the screen.
You can change the transparency of the entire surface using a individual alpha value. Use surf=pygame. Surface((size,pygame. SRCALPHA) .
When you read the documentation for set_alpha you can read this : If the Surface format contains per pixel alphas, then this alpha value will be ignored.
%In your case, with a png image, it's a per pixel alphas. So, you must manage alpha "per pixel". For example, you can do that (not the best code, but easy to understand. Work with png with no/yes transparency only):
def change_alpha(img,alpha=255):
width,height=img.get_size()
for x in range(0,width):
for y in range(0,height):
r,g,b,old_alpha=img.get_at((x,y))
if old_alpha>0:
img.set_at((x,y),(r,g,b,alpha))
Be carefull, it's "slow", because you manage each pixel which is not at 0 (transparent from your png). If your png has multiple level of transparency, you should manage the transparency with a better formula, like this:
r,g,b,old_alpha=img.get_at((x,y))
img.set_at((x,y),(r,g,b,(alpha*old_alpha)/255))
And in this case, never modify the original image, but work on a copy to never lose your original alpha.
I hope it will help
===================== EDIT =================== Add some optimisation because asking in comment
With some caching methodology:
class image_with_alpha(object):
def __init__(self,name=None):
self.img=None
self.alpha={}
if name:
self.load_image(name)
def load_image(self,name):
self.img=pygame.image.load(name)
self.alpha[255]=self.img
#self.pre_compute_alpha()
def pre_compute_alpha(self):
for alpha in range(0,10):
self.alpha[alpha]=change_alpha(self.img,alpha)
def get_img(self,a=255):
try:
return self.alpha[a]
except:
self.alpha[a]=change_alpha(self.img,a)
return self.alpha[a]
And use it like this : Load image:
image=image_with_alpha("test.png")
Blit with 60 for alpha:
screen.blit(image.get_img(60),(0,0))
And now, it's fast I hope
The fastest solution is probably to use numpy
array manipulation, it should be fast enough to avoid the need for caching. What's really slow about calculating the alpha value pixel-wise is iterating in Python, while numpy
does it all in C.
Start out by referencing the image's alpha channel into a numpy
array. This will create a lock on the image surface; let's remember that for later. Then take the minimum (pixel-wise) of your original alpha and an array full of ones (that will leave you with an array of only ones and zeros), multiply that (pixel-wise) by your desired alpha and copy the result back to the image's alpha channel (still represented by that array reference). Before you can blit the image to the screen, the array reference to the alpha array must be cleared, releasing the lock on the image surface.
def change_alpha(img, alpha=255):
chan = pygame.surfarray.pixels_alpha(img)
chan2 = numpy.minimum(chan, numpy.ones(chan.shape, dtype=chan.dtype)) * alpha
numpy.copyto(chan, chan2)
del chan
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With