Documentation Index
Fetch the complete documentation index at: https://mintlify.com/aseprite/aseprite/llms.txt
Use this file to discover all available pages before exploring further.
This document describes the technical specifications of the Aseprite file format (.ase/.aseprite).
References
ASE files use Intel (little-endian) byte order.
BYTE: An 8-bit unsigned integer value
WORD: A 16-bit unsigned integer value
SHORT: A 16-bit signed integer value
DWORD: A 32-bit unsigned integer value
LONG: A 32-bit signed integer value
FIXED: A 32-bit fixed point (16.16) value
FLOAT: A 32-bit single-precision value
DOUBLE: A 64-bit double-precision value
QWORD: A 64-bit unsigned integer value
LONG64: A 64-bit signed integer value
BYTE[n]: “n” bytes
STRING:
WORD: string length (number of bytes)
BYTE[length]: characters (in UTF-8)
- The
'\0' character is not included
POINT:
LONG: X coordinate value
LONG: Y coordinate value
SIZE:
LONG: Width value
LONG: Height value
RECT:
POINT: Origin coordinates
SIZE: Rectangle size
PIXEL: One pixel, depending on the image pixel format:
- RGBA:
BYTE[4], each pixel have 4 bytes in this order Red, Green, Blue, Alpha
- Grayscale:
BYTE[2], each pixel have 2 bytes in the order Value, Alpha
- Indexed:
BYTE, each pixel uses 1 byte (the index)
TILE: Tilemaps: Each tile can be a 8-bit (BYTE), 16-bit (WORD), or 32-bit (DWORD) value and there are masks related to the meaning of each bit
UUID: A Universally Unique Identifier stored as BYTE[16]
Introduction
The format is much like FLI/FLC files, but with different magic number and different chunks. Also, the color depth can be 8, 16 or 32 for Indexed, Grayscale and RGB respectively, and images are compressed with zlib. Color palettes are in FLI color chunks (it could be type=11 or type=4). For color depths more than 8bpp, palettes are optional.
To read the sprite:
- Read the ASE header
- For each frame:
- Read the frame header
- For each chunk in this frame:
- Read the chunk (it should be layer information, a cel or a palette)
A 128-byte header (same as FLC/FLI header, but with other magic number):
DWORD File size
WORD Magic number (0xA5E0)
WORD Frames
WORD Width in pixels
WORD Height in pixels
WORD Color depth (bits per pixel)
32 bpp = RGBA
16 bpp = Grayscale
8 bpp = Indexed
DWORD Flags:
1 = Layer opacity has valid value
2 = Layer blend mode/opacity is valid for groups
4 = Layers have an UUID
WORD Speed (milliseconds between frame, like in FLC files)
DEPRECATED: You should use the frame duration field
DWORD Set be 0
DWORD Set be 0
BYTE Palette entry (index) which represent transparent color
in all non-background layers (only for Indexed sprites)
BYTE[3] Ignore these bytes
WORD Number of colors (0 means 256 for old sprites)
BYTE Pixel width (pixel ratio is "pixel width/pixel height")
BYTE Pixel height
SHORT X position of the grid
SHORT Y position of the grid
WORD Grid width (zero if there is no grid)
WORD Grid height (zero if there is no grid)
BYTE[84] For future (set to zero)
Frames
After the header come the “frames” data. Each frame has this little header of 16 bytes:
DWORD Bytes in this frame
WORD Magic number (always 0xF1FA)
WORD Old field which specifies the number of "chunks"
in this frame. If this value is 0xFFFF, we might
have more chunks to read in this frame
WORD Frame duration (in milliseconds)
BYTE[2] For future (set to zero)
DWORD New field which specifies the number of "chunks"
in this frame (if this is 0, use the old field)
Then each chunk format is:
DWORD Chunk size
WORD Chunk type
BYTE[] Chunk data
The chunk size includes the DWORD of the size itself, and the WORD of the chunk type, so a chunk size must be equal or greater than 6 bytes at least.
Chunk Types
Old Palette Chunk (0x0004)
Ignore this chunk if you find the new palette chunk (0x2019).
WORD Number of packets
+ For each packet
BYTE Number of palette entries to skip from the last packet
BYTE Number of colors in the packet (0 means 256)
+ For each color in the packet
BYTE Red (0-255)
BYTE Green (0-255)
BYTE Blue (0-255)
Layer Chunk (0x2004)
In the first frame should be a set of layer chunks to determine the entire layers layout:
WORD Flags:
1 = Visible
2 = Editable
4 = Lock movement
8 = Background
16 = Prefer linked cels
32 = The layer group should be displayed collapsed
64 = The layer is a reference layer
WORD Layer type
0 = Normal (image) layer
1 = Group
2 = Tilemap
WORD Layer child level
WORD Default layer width in pixels (ignored)
WORD Default layer height in pixels (ignored)
WORD Blend mode
BYTE Opacity
BYTE[3] For future (set to zero)
STRING Layer name
+ If layer type = 2
DWORD Tileset index
+ If file header flags have bit 4:
UUID Layer's universally unique identifier
Cel Chunk (0x2005)
This chunk determines where to put a cel in the specified layer/frame.
WORD Layer index
SHORT X position
SHORT Y position
BYTE Opacity level
WORD Cel Type
0 - Raw Image Data
1 - Linked Cel
2 - Compressed Image
3 - Compressed Tilemap
SHORT Z-Index
BYTE[5] For future (set to zero)
Tags Chunk (0x2018)
After the tags chunk, you can write one user data chunk for each tag.
WORD Number of tags
BYTE[8] For future (set to zero)
+ For each tag
WORD From frame
WORD To frame
BYTE Loop animation direction
0 = Forward
1 = Reverse
2 = Ping-pong
3 = Ping-pong Reverse
WORD Repeat N times
BYTE[6] For future (set to zero)
BYTE[3] RGB values of the tag color (deprecated)
BYTE Extra byte (zero)
STRING Tag name
Palette Chunk (0x2019)
DWORD New palette size (total number of entries)
DWORD First color index to change
DWORD Last color index to change
BYTE[8] For future (set to zero)
+ For each palette entry in [from,to] range
WORD Entry flags:
1 = Has name
BYTE Red (0-255)
BYTE Green (0-255)
BYTE Blue (0-255)
BYTE Alpha (0-255)
+ If has name bit in entry flags
STRING Color name
User Data Chunk (0x2020)
Specifies the user data (color/text/properties) to be associated with the last read chunk/object.
DWORD Flags
1 = Has text
2 = Has color
4 = Has properties
+ If flags have bit 1
STRING Text
+ If flags have bit 2
BYTE Color Red (0-255)
BYTE Color Green (0-255)
BYTE Color Blue (0-255)
BYTE Color Alpha (0-255)
+ If flags have bit 4
DWORD Size in bytes of all properties maps
DWORD Number of properties maps
...
Slice Chunk (0x2022)
DWORD Number of "slice keys"
DWORD Flags
1 = It's a 9-patches slice
2 = Has pivot information
DWORD Reserved
STRING Name
+ For each slice key
DWORD Frame number
LONG Slice X origin coordinate
LONG Slice Y origin coordinate
DWORD Slice width
DWORD Slice height
...
Tileset Chunk (0x2023)
DWORD Tileset ID
DWORD Tileset flags
DWORD Number of tiles
WORD Tile Width
WORD Tile Height
SHORT Base Index
BYTE[14] Reserved
STRING Name of the tileset
...
Notes
For complete technical details including all chunk types, compression methods, and implementation notes, please refer to the full specification document in the Aseprite repository.
File Format Changes
The first change from the first release of the new .ase format is the new frame duration field. This is because now each frame can have different duration.
How to read both formats (old and new one)? You should set all frames durations to the “speed” field read from the main ASE header. Then, if you found a frame with the frame-duration field > 0, you should update the duration of the frame with that value.