Trim (crop) alpha for sprites in atlases (DEF-2858)

5 years already. Is there any news about it?
I surprised that so important thing is still not finished.

Itā€™s been a while since weā€™ve seen Dmi7ry ā€” their last post was 2 years ago.

Welcome back @Dmi7ry !

No. Not really.

Weā€™ve worked on a lot of other things instead.

Also, related but not exactly what you are looking for:

  • Sprite trimming to reduce overdraw #4350
  • Improved texture compression using BasisU (v 1.2.180)
  • Texture Manipulation API #5948 - IN PROGRESS

With Sprite trimming and the new texture manipulation API we have basically everything in place to also add support for trimming alpha from atlas image.

3 Likes

Another year later.
Still needed!

There are so many cases where itā€™s convenient to be able to import untrimmed sprites (so that they maintain an offset) into an atlas and have them be trimmed and efficiently packed. There is already an in engine trim feature, but itā€™s only for reducing overdraw and not adjusting waste of textures in memory.

Please :+1:the issue.

Here is a Python script for my needs, it loops through images, trims them, and saves offsets in a JSON file. Then when using a sprite Iā€™ll attempt to load its offset to know how to adjust its parent GO. Hopefully not too many more years before this is unnecessary!

If you use this make sure you keep a backup folder of original files.

from PIL import Image
import os
import json

def trim_image(img_path):
    with Image.open(img_path) as img:
        if img.mode != "RGBA":
            return img, None
        bbox = img.convert("RGBa").getbbox()
        if not bbox:
            return img, (0, 0)
        trimmed_img = img.crop(bbox)
        offset = (bbox[0], img.height - bbox[3])
        return trimmed_img, offset

def process_images_in_folder(folder_path):
    offsets = {
        "full_path": {},
        "filenames": {},
    }
    for dirpath, dirnames, filenames in os.walk(folder_path):
        for filename in filenames:
            if filename.endswith(".png"):
                img_path = os.path.join(dirpath, filename)
                trimmed_img, offset = trim_image(img_path)
                if offset and trimmed_img.size != Image.open(img_path).size:
                    trimmed_img.save(img_path)
                    relative_path = os.path.relpath(img_path, folder_path)
                    offsets["full_path"][relative_path] = {
                        "x_offset": offset[0],
                        "y_offset": offset[1]
                    }
                    offsets["filenames"][filename[:-4]] = relative_path
                    print(f"Processed: {relative_path} with Offset: {offset}")
    with open("offsets.json", "w") as outfile:
        json.dump(offsets, outfile, indent=4)
    return offsets

if __name__ == "__main__":
    folder_path = input("Enter the path to the images folder: ")
    process_images_in_folder(folder_path)
    print("\nProcessing complete. Check offsets.json for recorded offsets.")
1 Like

For sure itā€™s needed.
And after my current task (sprite multi textures), Iā€™m scheduled to start this task.

5 Likes

Heh, I already made something for this, I made an exporter in Python that takes whole linear animations from subfolders (exported as png frames from Aseprite), crops out the blank space, retains the position info, then replaces duplicates with references to the same cell, again maintaining the offset, writes all that into an anim file and packs the cells in the smallest power of 2 texture it can, and the position and size of each cell is recorded in the anim file.

Then I make my own animation player - in Kha it was a matter of using draw image and specifying the source rect, in Unity it was a matter of generating ā€œunity spritesā€ at runtime from that atlas using the anim infoā€¦ and in Defold it looks like I might be able to write the atlas file myself. Not sure if I can rely on Defoldā€™s anim system yet, perhaps this issue means Defold flipbook animations have to be uniform sized, but so long as I can set what sub image a sprite uses from an atlas, and position the sprite manually, I can use my own animation system.

Iā€™m just used to having to make my own pixel art workflow, engines typically donā€™t have a built in workflow for pixel art games and the way they work. And in an animation heavy game like classic Prince of Persia rotoscoped animation, you have a lot of frames with a lot of extreme sudden changes in sizes to their bounding box and you donā€™t want to have to incur that whole giant frame size for every single frame of animation when most of them are not that big.

3 Likes

I do remember having successfully used flipbook animation with different sized frames in Defold. But I was not using pixel art.

Weā€™d benefit from the equivalent functionality for textured GUI nodes. Our game allows users to select from multiple cosmetic items to decorate a scene rendered in GUI, and we maintain multiple lookup tables to control placement. It would be great if instead we could author textures with the correct padding.

1 Like