From 0d004450544b96df2149611744bad0b3706f3a2c Mon Sep 17 00:00:00 2001 From: Phil Gilmore Date: Fri, 15 Dec 2023 13:43:13 -0700 Subject: [PATCH 1/3] Added alphaonly imageloader parameter. --- pytmx/util_pygame.py | 47 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/pytmx/util_pygame.py b/pytmx/util_pygame.py index 5489f4f..3e0b2d7 100644 --- a/pytmx/util_pygame.py +++ b/pytmx/util_pygame.py @@ -62,6 +62,7 @@ def smart_convert( original: pygame.Surface, colorkey: Optional[ColorLike], pixelalpha: bool, + alphaonly: bool ) -> pygame.Surface: """ Return new pygame Surface with optimal pixel/data format @@ -70,12 +71,15 @@ def smart_convert( flags and pixel format for each tile surface. Parameters: - original: tile surface to inspect - colorkey: optional colorkey for the tileset image - pixelalpha: if true, prefer per-pixel alpha surfaces + original: Tile surface to inspect. + colorkey: Optional colorkey for the tileset image. + pixelalpha: If true, prefer per-pixel alpha surfaces. Default is True. + alphaonly: If true, always use per-pixel alpha surfaces. Default is False. + Use this to correct a common issue where pygame .convert() + will not display black (0,0,0) pixels from your images. Returns: - new tile surface + A new tile surface. """ # tiled set a colorkey @@ -90,22 +94,30 @@ def smart_convert( threshold = 254 # the default try: - # count the number of pixels in the tile that are not transparent + # Count the number of pixels in the tile that are not transparent. + # Pygame .convert() can misbehave. Calling .mask() correctly determines there are no + # transparent pixels. But when we call .convert(), it then makes black (0,0,0) pixels + # transparent when we didn't specify alpha behavior. If this happens to you, consider + # using the alphaonly override. px = pygame.mask.from_surface(original, threshold).count() except: # pygame_sdl2 will fail because the mask module is not included # in this case, just convert_alpha and return it return original.convert_alpha() - # there are no transparent pixels in the image - if px == tile_size[0] * tile_size[1]: + # Caller wants alpha no matter what. Accommodate them. + if alphaonly: + tile = original.convert_alpha() + + # There are no transparent pixels in the image. + elif px == tile_size[0] * tile_size[1]: tile = original.convert() - # there are transparent pixels, and set for perpixel alpha + # There are transparent pixels, and set for per-pixel alpha. elif pixelalpha: tile = original.convert_alpha() - # there are transparent pixels, and we won't handle them + # There are transparent pixels, and we won't handle them. else: tile = original.convert() @@ -117,16 +129,25 @@ def pygame_image_loader(filename: str, colorkey: Optional[ColorLike], **kwargs): pytmx image loader for pygame Parameters: - filename: filename, including path, to load - colorkey: colorkey for the image + filename: The filename, including path, to be loaded. + colorkey: The colorkey for the image. + + Optional named parameters: + pixelalpha: Intelligently choose to use per-pixel alpha transparency + only if there are no fully transparent pixels in the + image and colorkey is not specified. This is overridden + if alphaonly is specified. + alphaonly : Always use alpha transparency when converting + images to target surface format. Returns: - function to load tile images + A function to load tile images. """ if colorkey: colorkey = pygame.Color("#{0}".format(colorkey)) + alphaonly = kwargs.get("alphaonly", False) pixelalpha = kwargs.get("pixelalpha", True) image = pygame.image.load(filename) @@ -143,7 +164,7 @@ def load_image(rect=None, flags=None): if flags: tile = handle_transformation(tile, flags) - tile = smart_convert(tile, colorkey, pixelalpha) + tile = smart_convert(tile, colorkey, pixelalpha, alphaonly) return tile return load_image From eae92648066b9b44e2a247b5d129ffb1d8b6b924 Mon Sep 17 00:00:00 2001 From: Phil Gilmore Date: Fri, 15 Dec 2023 18:09:03 -0700 Subject: [PATCH 2/3] Fixed bug where kwargs aren't passed to image_loader. --- pytmx/pytmx.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pytmx/pytmx.py b/pytmx/pytmx.py index ba26ff4..0a70546 100644 --- a/pytmx/pytmx.py +++ b/pytmx/pytmx.py @@ -496,6 +496,7 @@ def __init__( self.filename = filename self.custom_property_filename = custom_property_filename self.image_loader = image_loader + self.image_loader_kwargs = kwargs # optional keyword arguments checked here self.optional_gids = kwargs.get("optional_gids", set()) @@ -651,7 +652,9 @@ def reload_images(self) -> None: path = os.path.join(os.path.dirname(self.filename), ts.source) colorkey = getattr(ts, "trans", None) - loader = self.image_loader(path, colorkey, tileset=ts) + kwargs_to_pass = self.image_loader_kwargs.copy() + kwargs_to_pass["tileset"] = "ts" + loader = self.image_loader(path, colorkey, **kwargs_to_pass) p = product( range( @@ -698,7 +701,7 @@ def reload_images(self) -> None: gid = self.register_gid(real_gid) layer.gid = gid path = os.path.join(os.path.dirname(self.filename), source) - loader = self.image_loader(path, colorkey) + loader = self.image_loader(path, colorkey, **self.image_loader_kwargs) image = loader() self.images.append(image) @@ -710,7 +713,7 @@ def reload_images(self) -> None: if source: colorkey = props.get("trans", None) path = os.path.join(os.path.dirname(self.filename), source) - loader = self.image_loader(path, colorkey) + loader = self.image_loader(path, colorkey, **self.image_loader_kwargs) image = loader() self.images[real_gid] = image From 9f2957f95c930602d114a8eb31cfc9ee20e010fb Mon Sep 17 00:00:00 2001 From: Phil Gilmore Date: Fri, 19 Jan 2024 14:37:22 -0700 Subject: [PATCH 3/3] Removed superfluous dict creation, reverted comment changes. --- pytmx/pytmx.py | 5 ++--- pytmx/util_pygame.py | 28 ++++++++++------------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/pytmx/pytmx.py b/pytmx/pytmx.py index 0a70546..274c3dd 100644 --- a/pytmx/pytmx.py +++ b/pytmx/pytmx.py @@ -652,9 +652,8 @@ def reload_images(self) -> None: path = os.path.join(os.path.dirname(self.filename), ts.source) colorkey = getattr(ts, "trans", None) - kwargs_to_pass = self.image_loader_kwargs.copy() - kwargs_to_pass["tileset"] = "ts" - loader = self.image_loader(path, colorkey, **kwargs_to_pass) + self.image_loader_kwargs["tileset"] = "ts" + loader = self.image_loader(path, colorkey, **self.image_loader_kwargs) p = product( range( diff --git a/pytmx/util_pygame.py b/pytmx/util_pygame.py index 3e0b2d7..c09e955 100644 --- a/pytmx/util_pygame.py +++ b/pytmx/util_pygame.py @@ -71,15 +71,13 @@ def smart_convert( flags and pixel format for each tile surface. Parameters: - original: Tile surface to inspect. - colorkey: Optional colorkey for the tileset image. - pixelalpha: If true, prefer per-pixel alpha surfaces. Default is True. - alphaonly: If true, always use per-pixel alpha surfaces. Default is False. - Use this to correct a common issue where pygame .convert() - will not display black (0,0,0) pixels from your images. + original: tile surface to inspect + colorkey: optional colorkey for the tileset image + pixelalpha: if true, prefer per-pixel alpha surfaces (default is true) + alphaonly: if true, always use per-pixel alpha surfaces (default is false) Returns: - A new tile surface. + new tile surface """ # tiled set a colorkey @@ -129,19 +127,13 @@ def pygame_image_loader(filename: str, colorkey: Optional[ColorLike], **kwargs): pytmx image loader for pygame Parameters: - filename: The filename, including path, to be loaded. - colorkey: The colorkey for the image. - - Optional named parameters: - pixelalpha: Intelligently choose to use per-pixel alpha transparency - only if there are no fully transparent pixels in the - image and colorkey is not specified. This is overridden - if alphaonly is specified. - alphaonly : Always use alpha transparency when converting - images to target surface format. + filename: filename, including path, to load + colorkey: colorkey for the image + pixelalpha: prefer per-pixel alpha surfaces + alphaonly : always use per-pixel alpha surfaces Returns: - A function to load tile images. + function to load tile images """ if colorkey: