In Pygame, how can I save a transparent image head

2019-07-11 07:39发布

This follows on a question I recently asked:

In Pygame, how can I save a screen image in headless mode?

I am able to save screen images involving non-transparent surface objects. However, the technique does not work for transparent surface objects. The following code illustrates the problem:

import sys
import os
import pygame
from pygame.color import THECOLORS as RGB


class PygameProblemDemo(object):

    def __init__(self):
        screen_width, screen_height = 200, 200
        os.environ['SDL_VIDEODRIVER'] = 'dummy'

        pygame.init()
        pygame.display.init()

        self.screen = pygame.display.set_mode((screen_width, screen_height))

    def save_non_alpha_image(self):
        r = 50
        color = RGB['blue']
        img_path = '/tmp/non_alpha_image.png'

        background = pygame.Surface((200, 200), pygame.SRCALPHA, 32)
        pygame.draw.rect(background, RGB['lightgray'], (0, 0, 200, 200), 0)

        self.screen.fill(RGB['black'])
        self.screen.blit(background, (0,0))
        pygame.draw.circle(self.screen, color, (100,100), r, 0)

        pygame.image.save(self.screen, img_path)
        print "image saved to %s" % (img_path)

    def save_alpha_image(self):
        r = 50
        color = RGB['blue']
        img_path = '/tmp/alpha_image.png'

        background = pygame.Surface((200, 200), pygame.SRCALPHA, 32)
        pygame.draw.rect(background, RGB['lightgray'], (0, 0, 200, 200), 0)

        transparent_circle = self.draw_transparent_circle(r, color, 50)

        self.screen.fill(RGB['black'])
        self.screen.blit(background, (0,0))
        self.screen.blit(transparent_circle, (50,50))

        pygame.image.save(self.screen, img_path)
        print "image saved to %s" % (img_path)

    def draw_transparent_circle(self, radius, color, transparency=0):
        """transparency is value between 0 and 100, 0 is opaque,
        100 invisible"""
        width, height = radius*2, radius*2

        # transparent base surface
        flags = pygame.SRCALPHA
        depth = 32
        base = pygame.Surface((width, height), flags, depth)

        # alpha surface
        alpha = int(round(255 * (100-transparency) / 100.0))
        alpha_surface = pygame.Surface((width, height))
        alpha_surface.set_colorkey(RGB['black'])
        alpha_surface.set_alpha(alpha)

        # draw circle (to alpha surface)
        pygame.draw.circle(alpha_surface, color, (radius,radius), radius)

        # draw alpha surface to base surface
        base.blit(alpha_surface, (0,0))

        return base


demo = PygameProblemDemo()
demo.save_non_alpha_image()
demo.save_alpha_image()

Here are the results:

non_alpha_image.png

non_alpha_image.png

alpha_image.png

alpha_image.png


Update

If I comment out the line os.environ['SDL_VIDEODRIVER'] = 'dummy' in the constructor, the transparent image is successfully saved:

alpha_image.png

alpha_image.png

However, that is the line the suppresses the window from opening up, so the script can no longer run headlessly. :\

1条回答
forever°为你锁心
2楼-- · 2019-07-11 08:30

I've figured it out. Pygame display needed to be initiated with alpha channel enabled. To fix my example above, simply replace this line in the constructor:

self.screen = pygame.display.set_mode((screen_width, screen_height))

With this:

self.screen = pygame.display.set_mode((screen_width, screen_height), 0, 32)
查看更多
登录 后发表回答