0

I'm using pygame for image editing (not displaying). (Yes, I know there are other options like PIL/pillow, but pygame should work for this.)

I want to draw and save an image where I'm individually setting the alpha values of each pixel according to a formula (I'm drawing a complicated RGBA profile). It seems that pixels_alpha is the right way to do this. But when I change pixels_alpha it's ignored, the image just stays transparent. Here's my code...

import pygame as pg
import os
def init_transparent(img_width, img_height):
    """
    Create a new surface with width and height, starting with transparent
    background. This part works!
    """
    os.environ['SDL_VIDEODRIVER'] = 'dummy'
    pg.init()
    pg.display.init()
    # next command enables alpha
    # see http://stackoverflow.com/questions/14948711/
    pg.display.set_mode((img_width, img_height), 0, 32)
    # pg.SRCALPHA is a flag that turns on per-pixel alpha.
    return pg.Surface((img_width, img_height), pg.SRCALPHA)

def make_semitransparent_image():
    surf = init_transparent(20, 20)
    # alphas should be a direct reference to the alpha data in surf
    alphas = pg.surfarray.pixels_alpha(surf)
    # alphas is a uint8-dtype numpy array. Right now it's all zeros.
    for i in range(20):
        for j in range(20):
            # Since pixels_alpha gave me a uint8 array, I infer that
            # alpha=255 means opaque. (Right?)
            alphas[i,j] = 200
    pg.image.save(surf, '/home/steve/Desktop/test.png')

make_semitransparent_image()

Again, it saves an image but the image looks completely transparent, no matter what value I set alphas to. What am I doing wrong here? (Using Python 2.7, pygame 1.9.1release.) (Thanks in advance!)

Steve Byrnes
  • 2,210
  • 1
  • 20
  • 25
  • Are you using pygame just to edit images, not actually display? If so, check [Pillow](http://python-imaging.github.io/) – ninMonkey Jul 06 '13 at 19:16
  • Where do you set the RGB values for the pixels in the `Surface` you save? You appear to only be setting the alpha component of them all. – martineau Jul 06 '13 at 19:17
  • monkey: thanks for the suggestion. Like you said, I'm editing not displaying, and I will indeed try pillow if pygame won't work. martineau: I'm not showing the RGB adjustment. This code SHOULD make a semitransparent white or black square (whatever's the default, I forget). When I set RGB to something else using similar code, it doesn't matter, the image is always transparent. – Steve Byrnes Jul 06 '13 at 19:22
  • The output is an image with 0 alpha ? There also is [PixelArray](http://www.pygame.org/docs/ref/pixelarray.html) Which I think is the python class wrapping `surfarray` – ninMonkey Jul 06 '13 at 19:23
  • @monkey - The output image looks transparent whatever I do, although I can't rule out that it's merely almost-transparent. (I'm not sure how to check.) At your suggestion I tried making a PixelArray then setting every pixel to pg.Color(255,255,255,255), but the image is still transparent. – Steve Byrnes Jul 06 '13 at 19:48
  • If you open an image in GIMP, color picker, check 'use info window' it will show alpha values on that pixel. [this image has multiple alpha values to test it](http://www.libpng.org/pub/png/img_png/AlphaBall.png) Is this on raspberryPi? I thought it said that somewhere? Because you could also try asking at /r/raspberry_pi/ and /r/pygame/ – ninMonkey Jul 07 '13 at 00:12
  • The Pygame docs say that `pixels_array()` locks the surface as long as the resulting array exists, and that locked surface may not be drawn correctly. It might be the case that they are not saved correctly too. Try to throw away the `alphas` surfarray object with `del alphas` before doing the `image.save()`. – Armin Rigo Jul 07 '13 at 08:29
  • @ArminRigo - Yes, `del alphas` fixes it! Thanks! You should re-post that as an answer. – Steve Byrnes Jul 07 '13 at 11:41

1 Answers1

1

The Pygame docs say that pixels_array() locks the surface as long as the resulting array exists, and that locked surface may not be drawn correctly. It seems to be the case that they are not saved correctly, too. You need to throw away the alphas surfarray object before calling image.save(). This can be done by adding del alphas just before image.save().

(Note that this is more a workaround than a proper fix. Adding del alphas can only have a reliable effect only on CPython (and not PyPy, Jython, IronPython). Maybe you can really "close" a surfarray objects, the same way you can either close a file or merely forget about it?)

Armin Rigo
  • 12,048
  • 37
  • 48
  • Thanks, `del alphas` works!! (At least, it works in CPython.) It also works if I indirectly delete `alphas` by exiting its scope before I save the surface. FYI, `type(alphas) == ` -- it seems to be an ordinary numpy array, not a special pygame object. – Steve Byrnes Jul 07 '13 at 16:14