ASE Files (.ASE) Format description

Copyright (C) 2001-2012 by David 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.

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

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 a FLI color chunk (it could be type=11 or type=4).

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            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.

