2012-01-05 22:45:03 +00:00
|
|
|
ASE Files (.ASE) Format description
|
2014-09-17 13:08:19 +00:00
|
|
|
Copyright (C) 2001-2014 by David Capello
|
2012-01-05 22:45:03 +00:00
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
|
|
|
1. References
|
|
|
|
2. Introduction
|
|
|
|
3. Header
|
|
|
|
4. Frames
|
|
|
|
5. New chunk types
|
|
|
|
6. File Format Changes
|
|
|
|
|
|
|
|
========================================
|
|
|
|
1. References
|
|
|
|
========================================
|
|
|
|
|
|
|
|
ASE files use Intel (little-endian) byte order.
|
|
|
|
|
|
|
|
BYTE An 8-bit unsigned integer value
|
|
|
|
WORD A 16-bit unsigned integer value
|
|
|
|
DWORD A 32-bit unsigned integer value
|
|
|
|
LONG A 32-bit signed integer value
|
|
|
|
BYTE[n] "n" bytes.
|
|
|
|
RECT Four LONGs (in the order: x-pos, y-pos, width, heigth)
|
|
|
|
STRING length=WORD (how many characters to read next)
|
|
|
|
string=BYTE[length]
|
|
|
|
The \0 character isn't included.
|
|
|
|
PIXEL Pixel format:
|
|
|
|
- In RGB images, each pixel have 4 bytes in
|
|
|
|
this order Red, Green, Blue, Alpha.
|
|
|
|
- In Grayscale images, each pixel have 2 bytes
|
|
|
|
in the order Value, Alpha.
|
|
|
|
- In Indexed images, each pixel uses 1 byte (the index).
|
|
|
|
|
|
|
|
|
|
|
|
========================================
|
|
|
|
2. Introduction
|
|
|
|
========================================
|
|
|
|
|
|
|
|
The format is much like FLI/FLC files, but with different magic number
|
|
|
|
and differents chunks. Also, the color depth can be 8, 16 or 32 for
|
|
|
|
Indexed, Grayscale and RGB respectively, and the images are more easy
|
2014-09-17 13:08:19 +00:00
|
|
|
to read (there aren't differences with old frames). Color palettes
|
|
|
|
are in FLI color chunks (it could be type=11 or type=4). For color
|
|
|
|
depths more than 8bpp, palettes are optional. See fli.txt for details.
|
2012-01-05 22:45:03 +00:00
|
|
|
|
|
|
|
To read the sprite, just do this:
|
|
|
|
* Read the ASE header (section 3)
|
|
|
|
* For each frame do (how many frames? the ASE header has that
|
|
|
|
information):
|
|
|
|
+ Read the frame header (section 4)
|
|
|
|
+ For each chunk in this frame (how many chunks? the frame header
|
|
|
|
has that information)
|
|
|
|
- Read the chunk (it should be layer information, a cel or a
|
|
|
|
palette)
|
|
|
|
|
|
|
|
|
|
|
|
========================================
|
|
|
|
3. Header
|
|
|
|
========================================
|
|
|
|
|
|
|
|
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 (must be 0)
|
|
|
|
WORD Speed (milliseconds between frame, like in FLC files)
|
|
|
|
DEPRECATED: You should use the frame duration
|
|
|
|
field from each frame header
|
|
|
|
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[94] For future (set to zero)
|
|
|
|
|
|
|
|
|
|
|
|
========================================
|
|
|
|
4. 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 Number of "chunks" in this frame
|
|
|
|
WORD Frame duration (in milliseconds)
|
|
|
|
BYTE[6] For future (set to zero)
|
|
|
|
|
|
|
|
Then each chunk format is:
|
|
|
|
|
|
|
|
DWORD Chunk size
|
|
|
|
WORD Chunk type
|
|
|
|
BYTE[] Chunk data
|
|
|
|
|
|
|
|
|
|
|
|
========================================
|
|
|
|
5. New chunk types
|
|
|
|
========================================
|
|
|
|
|
|
|
|
Layer Chunk (0x2004)
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
In the first frame should be a set of layer chunks to determine the
|
|
|
|
entire layers layout:
|
|
|
|
|
|
|
|
WORD Flags:
|
|
|
|
LAYER_IS_READABLE = 0x0001
|
|
|
|
LAYER_IS_WRITABLE = 0x0002
|
|
|
|
LAYER_IS_LOCKMOVE = 0x0004
|
|
|
|
LAYER_IS_BACKGROUND = 0x0008
|
|
|
|
WORD Layer type (0=normal (image) layer, 1=layer set)
|
|
|
|
WORD Layer child level (see NOTE.1)
|
|
|
|
WORD Default layer width in pixels (ignored)
|
|
|
|
WORD Default layer height in pixels (ignored)
|
|
|
|
WORD DEPRECATED This field is not used anymore.
|
|
|
|
Blend mode (always 0 for layer set)
|
|
|
|
BLEND_MODE_NORMAL = 0
|
|
|
|
BLEND_MODE_DISSOLVE = 1
|
|
|
|
BLEND_MODE_MULTIPLY = 2
|
|
|
|
BLEND_MODE_SCREEN = 3
|
|
|
|
BLEND_MODE_OVERLAY = 4
|
|
|
|
BLEND_MODE_HARD_LIGHT = 5
|
|
|
|
BLEND_MODE_DODGE = 6
|
|
|
|
BLEND_MODE_BURN = 7
|
|
|
|
BLEND_MODE_DARKEN = 8
|
|
|
|
BLEND_MODE_LIGHTEN = 9
|
|
|
|
BLEND_MODE_ADDITION = 10
|
|
|
|
BLEND_MODE_SUBTRACT = 11
|
|
|
|
BLEND_MODE_DIFFERENCE = 12
|
|
|
|
BLEND_MODE_HUE = 13
|
|
|
|
BLEND_MODE_SATURATION = 14
|
|
|
|
BLEND_MODE_COLOR = 15
|
|
|
|
BLEND_MODE_LUMINOSITY = 16
|
|
|
|
BLEND_MODE_COPY = 17
|
|
|
|
BYTE[4] For future (set to zero)
|
|
|
|
STRING Layer name
|
|
|
|
|
|
|
|
|
|
|
|
Cel Chunk (0x2005)
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
This chunk determine where to put a cel in the specified
|
|
|
|
layer/frame.
|
|
|
|
|
|
|
|
WORD Layer index (see NOTE.2)
|
|
|
|
WORD X position
|
|
|
|
WORD Y position
|
|
|
|
BYTE Opacity level
|
|
|
|
WORD Cel type
|
|
|
|
BYTE[7] For future (set to zero)
|
|
|
|
|
|
|
|
+ For cel type = 0 (Raw Cel):
|
|
|
|
|
|
|
|
WORD Width in pixels
|
|
|
|
WORD Height in pixels
|
|
|
|
PIXEL[] Raw pixel data: row by row from top to bottom,
|
|
|
|
for each scanline read pixels from left to right.
|
|
|
|
|
|
|
|
+ For cel type = 1 (Linked Cel):
|
|
|
|
|
|
|
|
WORD Frame position to link with
|
|
|
|
|
|
|
|
+ For cel type = 2 (compressed image):
|
|
|
|
|
|
|
|
WORD Width in pixels
|
|
|
|
WORD Height in pixels
|
|
|
|
BYTE[] Compressed "Raw Cel" data. Details about the
|
|
|
|
compression method:
|
|
|
|
http://www.ietf.org/rfc/rfc1951.txt
|
|
|
|
|
|
|
|
|
|
|
|
Mask Chunk (0x2016) DEPRECATED
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
WORD X position
|
|
|
|
WORD Y position
|
|
|
|
WORD Width
|
|
|
|
WORD Height
|
|
|
|
BYTE[8] For future (set to zero)
|
|
|
|
STRING Mask name
|
|
|
|
BYTE[] Bit map data (size = height*((width+7)/8))
|
|
|
|
Each byte contains 8 pixels (the leftmost pixels are
|
|
|
|
packed into the high order bits)
|
|
|
|
|
|
|
|
|
|
|
|
Path Chunk (0x2017)
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
Never used.
|
|
|
|
|
|
|
|
|
|
|
|
Notes
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
NOTE.1: The child level is used to show the relationship of this
|
|
|
|
layer with the last one read, for example:
|
|
|
|
|
|
|
|
Layer name and hierarchy Child Level
|
|
|
|
-----------------------------------------------
|
|
|
|
- Background 0
|
|
|
|
`- Layer1 1
|
|
|
|
- Foreground 0
|
|
|
|
|- My set1 1
|
|
|
|
| `- Layer2 2
|
|
|
|
`- Layer3 1
|
|
|
|
|
|
|
|
|
|
|
|
NOTE.2: The layer index is a number to identify any layer in the
|
|
|
|
sprite, for example:
|
|
|
|
|
|
|
|
Layer name and hierarchy Layer index
|
|
|
|
-----------------------------------------------
|
|
|
|
- Background 0
|
|
|
|
`- Layer1 1
|
|
|
|
- Foreground 2
|
|
|
|
|- My set1 3
|
|
|
|
| `- Layer2 4
|
|
|
|
`- Layer3 5
|
|
|
|
|
|
|
|
|
|
|
|
========================================
|
|
|
|
File Format Changes
|
|
|
|
========================================
|
|
|
|
|
|
|
|
1) 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.
|