Texture Atlas

class arcade.texture_atlas.base.TextureAtlasBase(ctx: ArcadeContext | None)[source]

Bases: ABC

Abstract base class for texture atlases.

A texture atlas is a large texture containing several textures so OpenGL can easily batch draw thousands or hundreds of thousands of sprites on one draw operation.

abstract add(texture: Texture) tuple[int, AtlasRegion][source]

Add a texture to the atlas.

Parameters:

texture – The texture to add

Returns:

texture_id, AtlasRegion tuple

Raises:

AllocatorException – If there are no room for the texture

property ctx: ArcadeContext

The global Arcade OpenGL context.

property fbo: Framebuffer

The framebuffer object for this atlas.

This framebuffer has the atlas texture attached to it so we can render directly into the atlas texture.

abstract get_image_region_info(hash: str) AtlasRegion[source]

Get the region info for and image by has

Parameters:

hash – The hash of the image

abstract get_texture_id(texture: Texture) int[source]

Get the internal id for a Texture in the atlas

Parameters:

texture – The texture to get

abstract get_texture_region_info(atlas_name: str) AtlasRegion[source]

Get the region info for a texture by atlas name

Parameters:

atlas_name – The name of the texture in the atlas

abstract has_image(image_data: ImageData) bool[source]

Check if an image is already in the atlas

Parameters:

image_data – The image data to check

abstract has_texture(texture: Texture) bool[source]

Check if a texture is already in the atlas.

Parameters:

texture – The texture to check

abstract has_unique_texture(texture: Texture) bool[source]

Check if the atlas already have a texture with the same image data and vertex order

Parameters:

texture – The texture to check

property height: int

Width of the atlas in pixels.

property layers: int

Number of layers in the atlas. Only relevant for atlases using texture arrays.

abstract read_texture_image_from_atlas(texture: Texture) PIL.Image.Image[source]

Read the pixel data for a texture directly from the atlas texture on the GPU. The contents of this image can be altered by rendering into the atlas and is useful in situations were you need the updated pixel data on the python side.

Parameters:

texture – The texture to get the image for

Returns:

A pillow image containing the pixel data in the atlas

abstract rebuild() None[source]

Rebuild the underlying atlas texture.

This method also tries to organize the textures more efficiently ordering them by size. The texture ids will persist so the sprite list doesn’t need to be rebuilt.

abstract remove(texture: Texture) None[source]

Remove a texture from the atlas.

This is only supported by static atlases. Dynamic atlases with garbage collection will remove texture using python’s garbage collector.

Parameters:

texture – The texture to remove

abstract render_into(texture: Texture, projection: tuple[float, float, float, float] | None = None)[source]

Render directly into a sub-section of the atlas. The sub-section is defined by the already allocated space of the texture supplied in this method.

By default the projection will be set to match the texture area size were 0, 0 is the lower left corner and width, height (of texture) is the upper right corner.

This method should should be used with the with statement:

with atlas.render_into(texture):
    # Draw commands here

# Specify projection
with atlas.render_into(texture, projection=(0, 100, 0, 100))
    # Draw geometry
Parameters:
  • texture – The texture area to render into

  • projection – The ortho projection to render with. This parameter can be left blank if no projection changes are needed. The tuple values are: (left, right, button, top)

abstract resize(size: tuple[int, int], force=False) None[source]

Resize the atlas.

This will re-allocate all the images in the atlas to better fit the new size. Pixel data will be copied from the old atlas to the new one on the gpu meaning it will also persist anything that was rendered to the atlas.

A failed resize will result in an AllocatorException. Unless the atlas is resized again to a working size the atlas will be in an undefined state.

Parameters:
  • size – The new size

  • force – Force a resize even if the size is the same

abstract save(path: str | Path, flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) None[source]

Save the texture atlas to a png.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • path – The path to save the atlas on disk

  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

abstract show(flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) None[source]

Show the texture atlas using Pillow.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

property size: tuple[int, int]

The width and height of the texture atlas in pixels

property texture: Texture2D

The OpenGL texture for this atlas.

abstract to_image(flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) Image[source]

Convert the atlas to a Pillow image.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

Returns:

A pillow image containing the atlas texture

abstract update_texture_image(texture: Texture)[source]

Updates the internal image of a texture in the atlas texture. The new image needs to be the exact same size as the original one meaning the texture already need to exist in the atlas.

This can be used in cases were the image is manipulated in some way and we need a quick way to sync these changes to graphics memory. This operation is fairly expensive, but still orders of magnitude faster than removing the old texture, adding the new one and re-building the entire atlas.

Parameters:

texture – The texture to update

abstract update_texture_image_from_atlas(texture: Texture) None[source]

Update the Arcade Texture’s internal image with the pixel data content from the atlas texture on the GPU. This can be useful if you render into the atlas and need to update the texture with the new pixel data.

Parameters:

texture – The texture to update

abstract use_uv_texture(unit: int = 0) None[source]

Bind the texture coordinate texture to a channel. In addition this method writes the texture coordinate to the texture if the data is stale. This is to avoid a full update every time a texture is added to the atlas.

Parameters:

unit – The texture unit to bind the uv texture

property width: int

Hight of the atlas in pixels.

abstract write_image(image: Image, x: int, y: int) None[source]

Write a PIL image to the atlas in a specific region.

Parameters:
  • image – The pillow image

  • x – The x position to write the texture

  • y – The y position to write the texture

class arcade.DefaultTextureAtlas(size: tuple[int, int], *, border: int = 1, textures: Sequence[Texture] | None = None, auto_resize: bool = True, ctx: ArcadeContext | None = None, capacity: int = 2)[source]

Bases: TextureAtlasBase

A texture atlas with a size in a context.

A texture atlas is a large texture containing several textures so OpenGL can easily batch draw thousands or hundreds of thousands of sprites on one draw operation.

The atlas is auto-GCed meaning that textures and images are removed when the user removes all references to them. This is the only way to remove textures and images from the atlas.

This is a fairly simple atlas that stores horizontal strips were the height of the strip is the texture/image with the larges height. This is done for performance reasons.

Adding a texture to this atlas generates a texture id. This id is used the sprite list vertex data to reference what texture each sprite is using. The actual texture coordinates are located in a float32 texture this atlas is responsible for keeping up to date.

The atlas deals with image and textures. The image is the actual image data. The texture is the Arcade texture object that contains the image and other information about such as transforms. Several textures can share the same image with different transforms applied. The transforms are simply changing the order of the texture coordinates to flip, rotate or mirror the image.

Parameters:
  • size – The width and height of the atlas in pixels

  • border – The number of edge pixels to repeat around images in the atlas. This kind of padding is important to avoid edge artifacts. Default is 1 pixel.

  • textures (optional) – Optional sequence of textures to add to the atlas on creation

  • auto_resize – Automatically resize the atlas when full. Default is True.

  • ctx (optional) – The context for this atlas (will use window context if left empty)

  • capacity – The number of textures the atlas keeps track of. This is multiplied by 4096. Meaning capacity=2 is 8192 textures. This value can affect the performance of the atlas.

add(texture: Texture) tuple[int, AtlasRegion][source]

Add a texture to the atlas.

Add a texture to the atlas.

Parameters:

texture – The texture to add

Returns:

texture_id, AtlasRegion tuple

Raises:

AllocatorException – If there are no room for the texture

property auto_resize: bool

Get or set the auto resize flag for the atlas. If enabled the atlas will resize itself when full.

property border: int

The texture border in pixels

get_image_region_info(hash: str) AtlasRegion[source]

Get the region info for and image by has

Parameters:

hash – The hash of the image

get_texture_id(texture: Texture) int[source]

Get the internal id for a Texture in the atlas

Parameters:

texture – The texture to get.

get_texture_region_info(atlas_name: str) AtlasRegion[source]

Get the region info for a texture by atlas name

Parameters:

atlas_name – The name of the texture in the atlas

has_image(image_data: ImageData) bool[source]

Check if an image is already in the atlas

Parameters:

image_data – The image data to check

has_texture(texture: Texture) bool[source]

Check if a texture is already in the atlas.

Parameters:

texture – The texture to check

has_unique_texture(texture: Texture) bool[source]

Check if the atlas already have a texture with the same image data and vertex order

Parameters:

texture – The texture to check

property image_uv_texture: Texture2D

Texture coordinate texture for images.

property images: list[ImageData]

Return a list of all the images in the atlas.

A new list is constructed from the internal weak set of images.

property max_height: int

The maximum height of the atlas in pixels.

property max_size: tuple[int, int]

The maximum size of the atlas in pixels (x, y).

property max_width: int

The maximum width of the atlas in pixels.

read_texture_image_from_atlas(texture: Texture) Image.Image[source]

Read the pixel data for a texture directly from the atlas texture on the GPU. The contents of this image can be altered by rendering into the atlas and is useful in situations were you need the updated pixel data on the python side.

Parameters:

texture – The texture to get the image for

Returns:

A pillow image containing the pixel data in the atlas

rebuild() None[source]

Rebuild the underlying atlas texture.

This method also tries to organize the textures more efficiently ordering them by size. The texture ids will persist so the sprite list doesn’t need to be rebuilt.

remove(texture: Texture) None[source]

Remove a texture from the atlas.

This is only supported by static atlases. Dynamic atlases with garbage collection will remove texture using python’s garbage collector.

Parameters:

texture – The texture to remove

render_into(texture: Texture, projection: tuple[float, float, float, float] | None = None)[source]

Render directly into a sub-section of the atlas. The sub-section is defined by the already allocated space of the texture supplied in this method.

By default the projection will be set to match the texture area size were 0, 0 is the lower left corner and width, height (of texture) is the upper right corner.

This method should should be used with the with statement:

with atlas.render_into(texture):
    # Draw commands here

# Specify projection
with atlas.render_into(texture, projection=(0, 100, 0, 100))
    # Draw geometry
Parameters:
  • texture – The texture area to render into

  • projection – The ortho projection to render with. This parameter can be left blank if no projection changes are needed. The tuple values are: (left, right, button, top)

resize(size: tuple[int, int], force=False) None[source]

Resize the atlas.

This will re-allocate all the images in the atlas to better fit the new size. Pixel data will be copied from the old atlas to the new one on the gpu meaning it will also persist anything that was rendered to the atlas.

A failed resize will result in an AllocatorException. Unless the atlas is resized again to a working size the atlas will be in an undefined state.

Parameters:
  • size – The new size

  • force – Force a resize even if the size is the same

save(path: str | Path, flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) None[source]

Save the texture atlas to a png.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • path – The path to save the atlas on disk

  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

show(flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) None[source]

Show the texture atlas using Pillow.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

property texture_uv_texture: Texture2D

Texture coordinate texture for textures.

property textures: list[Texture]

All textures instance added to the atlas regardless of their internal state. See unique_textures`() for textures with unique image data and transformation.

to_image(flip: bool = False, components: int = 4, draw_borders: bool = False, border_color: tuple[int, int, int] = (255, 0, 0)) Image[source]

Convert the atlas to a Pillow image.

Borders can also be drawn into the image to visualize the regions of the atlas.

Parameters:
  • flip – Flip the image horizontally

  • components – Number of components. (3 = RGB, 4 = RGBA)

  • draw_borders – Draw region borders into image

  • border_color – RGB color of the borders

Returns:

A pillow image containing the atlas texture

property unique_textures: list[Texture]

All unique textures in the atlas.

These are textures using an image with the same hash and the same vertex order. The full list of all textures can be found in textures().

update_texture_image(texture: Texture)[source]

Updates the internal image of a texture in the atlas texture. The new image needs to be the exact same size as the original one meaning the texture already need to exist in the atlas.

This can be used in cases were the image is manipulated in some way and we need a quick way to sync these changes to graphics memory. This operation is fairly expensive, but still orders of magnitude faster than removing the old texture, adding the new one and re-building the entire atlas.

Parameters:

texture – The texture to update

update_texture_image_from_atlas(texture: Texture) None[source]

Update the Arcade Texture’s internal image with the pixel data content from the atlas texture on the GPU. This can be useful if you render into the atlas and need to update the texture with the new pixel data.

Parameters:

texture – The texture to update

use_uv_texture(unit: int = 0) None[source]

Bind the texture coordinate texture to a channel. In addition this method writes the texture coordinate to the texture if the data is stale. This is to avoid a full update every time a texture is added to the atlas.

Parameters:

unit – The texture unit to bind the uv texture

write_image(image: Image, x: int, y: int) None[source]

Write a PIL image to the atlas in a specific region.

Parameters:
  • image – The pillow image

  • x – The x position to write the texture

  • y – The y position to write the texture

class arcade.texture_atlas.region.AtlasRegion(atlas: TextureAtlasBase, x: int, y: int, width: int, height: int, texture_coordinates: tuple[float, float, float, float, float, float, float, float] | None = None)[source]

Bases:

Stores information about where a texture is located.

The texture coordinates are stored as a tuple of 8 floats (4 points, 2 floats each) in the following order: upper_left, upper_right, lower_left, lower_right.

Layout:

(0, 1)                                 (1, 1)
+--------------------------------------+
|          Atlas Texture               |
|                                      |
| (2)               (3)                |
+-----------------+                    |
|   Image         |                    |
|                 |                    |
|                 |                    |
|                 |                    |
|                 |                    |
| (0)             | (1)                |
+-----------------+--------------------+
(0, 0)                                 (1, 0)
Parameters:
  • atlas – The atlas this region belongs to

  • x – The x position of the texture

  • y – The y position of the texture

  • width – The width of the texture in pixels

  • height – The height of the texture in pixels

  • texture_coordinates (optional) – The texture coordinates for this region. If not provided, they will be calculated.

height

Height of the texture in pixels

texture_coordinates

The calculated texture coordinates for this region

verify_image_size(image_data: ImageData)[source]

Verify the image size.

The internal image of a texture can potentially be tampered with at any point causing an atlas update to fail.

Parameters:

image_data – The image data to verify

width

Width of the texture in pixels

x

X position of the texture in the atlas

y

Y position of the texture in the atlas

class arcade.texture_atlas.uv_data.UVData(ctx: ArcadeContext, capacity: int)[source]

Bases:

A container for float32 texture coordinates stored in a texture. Each texture coordinate has a slot/index in the texture and is looked up by a shader to obtain the texture coordinates. The shader would look up texture coordinates by the id of the texture.

The purpose of this system is to:

  • Greatly increase the performance of the texture atlas

  • Greatly simplify the system

  • Allow images to move freely around the atlas without having to update the vertex buffers. Meaning we can allow re-building and re-sizing. The resize can even be done in the GPU by rendering the old atlas into the new one.

  • Avoid spending lots of time packing texture data into buffers

  • Avoid spending lots of buffer memory

Parameters:
  • ctx – The Arcade context

  • capacity – The number of textures the atlas keeps track of. This is multiplied by 4096. Meaning capacity=2 is 8192 textures.

clone_with_slots() UVData[source]

Clone the UVData with the current slot data. The UV data itself and the opengl texture is not cloned.

This is useful when we are re-building the atlas since we can’t lost the slot data since the indices in the uv texture must not change. If they change the entire spritelist must be updated.

free_slot_by_name(name: str) None[source]

Free a slot for a texture by name. If the slot is not found no action is taken

Parameters:

name – The name of the texture

get_existing_or_free_slot(name: str) int[source]

Get the slot for a texture by name or a free slot. Getting existing slots is useful when the resize or re-build the atlas.

Parameters:

name – The name of the texture

get_slot_or_raise(name: str) int[source]

Get the slot for a texture by name or raise an exception

Parameters:

name – The name of the texture

property num_free_slots: int

The amount of free texture coordinates slots

property num_slots: int

The amount of texture coordinates (x4) this UVData can hold

set_slot_data(slot: int, data: tuple[float, float, float, float, float, float, float, float]) None[source]

Update the texture coordinates for a slot.

Parameters:
  • slot – The slot to update

  • data – The texture coordinates

property texture: Texture2D

The opengl texture containing the texture coordinates

write_to_texture() None[source]

Write the texture coordinates to the opengl texture if dirty

class arcade.texture_atlas.ref_counters.ImageDataRefCounter[source]

Bases:

Helper class to keep track of how many times an image is used by a texture in the atlas to determine when it’s safe to remove it.

Multiple Texture instances can and will use the same ImageData instance.

clear() None[source]

Clear the reference counters

count_all_refs() int[source]

Count the total number of references.

debug_print() None[source]

print the keys and counters for debugging purposes.

dec_ref(image_data: ImageData) int[source]

Decrement the reference counter for an image returning the new value.

Parameters:

image_data – The image to decrement the reference counter for

dec_ref_by_hash(hash: str) int[source]

Decrement the reference count for an image by hash returning the new value.

Raises RuntimeError if the hash is no longer tracked meaning it doesn’t exist and/or the reference count is already zero. Otherwise the updated ref counter is returned. When 0 is returned we removed the last reference to the image.

Parameters:

hash – The hash of the image to decrement the reference counter for

get_ref_count(image_data: ImageData) int[source]

Get the reference count for an image.

Parameters:

image_data – The image to get the reference count for

get_total_decref(reset=True) int[source]

Get the total number of decrefs.

This is useful for quickly checking if images was removed from the atlas. We can then determine if the atlas needs to be rebuilt. Also for debugging purposes.

Parameters:

reset – Reset the decref counter after getting the value

inc_ref(image_data: ImageData) None[source]

Increment the reference counter for an image.

Parameters:

image_data – The image to increment the reference counter for

class arcade.texture_atlas.ref_counters.UniqueTextureRefCounter[source]

Bases:

Helper class to keep track of how many times a unique texture is used.

A “unique texture” is based on the atlas_name of the texture meaning a texture using the same image and the same vertex order.

clear() None[source]

Clear the reference counters

count_all_refs() int[source]

Helper function to count the total number of references.

debug_print() None[source]

Print all the keys and counters for debugging purposes

dec_ref(image_data: Texture) int[source]

Decrement the reference counter for an image returning the new value.

Parameters:

image_data – The image to decrement the reference counter for

dec_ref_by_atlas_name(atlas_name: str) int[source]

Decrement the reference counter for an image by name returning the new value.

Raises RuntimeError if the atlas name is no longer tracked meaning it doesn’t exist and/or the reference count is already zero. Otherwise the updated ref counter is returned. When 0 is returned we removed the last reference to the texture.

Parameters:

atlas_name – The name of the texture to decrement the reference counter

get_ref_count(image_data: ImageData) int[source]

Get the reference counter for an image.

Parameters:

image_data – The image to get the reference count for

get_total_decref(reset=True) int[source]

Get the total number of decrefs.

This is useful to keep track of how many textures was removed from the atlas either for functional or debugging purposes.

Parameters:

reset – Reset the counter after getting the value

inc_ref(image_data: Texture) None[source]

Increment the reference count for an image.

Parameters:

image_data – The image to increment the reference counter for