ASE Files (.ASE) Format description Copyright (C) 2004-2005, 2007, 2008 by David A. Capello ---------------------------------------------------------------------- 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. ======================================== 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 to read (there aren't differences with old frames). The palette isn't included for color depths more than 8, but when the sprite is 8 bpp, the palette is in an old FLI color chunk (type=11). See fli.txt for details. 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[4] Background color: For 32 bpp BYTE Red BYTE Green BYTE Blue BYTE Alpha For 16 bpp: BYTE Gray BYTE Alpha BYTE[2] Padding For 8 bpp: BYTE Index BYTE[3] Padding BYTE[96] 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) [NEW FIELD!!!] 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 (1=readable, 2=writable) 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 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 BYTE[] Pixel data (see NOTE.3) + For cel type = 1 (Linked Cel): WORD Frame position to link with + For cel type = 2 (RLE compressed image, only for Indexed images): WORD Width in pixels WORD Height in pixels XXXXX -todo- 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 NOTE.3: The raw pixel data is saved row by row from top to bottom, and each scanline is from pixel by pixel from left to right. In RGB images, each pixel have 4 bytes in the order R, G, B, A. In Grayscale images, each pixel have 2 bytes in the order K, A. In Indexed images, each pixel have 1 byte (the index). ======================================== 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.