Amiga Icon Formats

From www.evillabs.net
Jump to navigation Jump to search
Dirk St�cker <stoecker@epost.de>
17th February 2002

Format description of Amiga Icon Format.

This format is used by Amiga computers to display icons for each program
or project you want to access from the graphical user interface Workbench.

There are 3 different formats.
1) The OS1.x/OS2.x icons.
2) The NewIcon icon extension.
3) The OS3.5 icon extension.

A note about the used data descriptors. All elements are in Motorola byte
order (highest byte first):
APTR  - a memory pointer (usually this gets a boolean meaning on disk)
BYTE  - a single byte                   -128..127
UBYTE - an unsigned byte                   0..255
WORD  - a signed 16 bit value         -32768..32767
UWORD - an unsigned 16 bit value           0..65535
LONG  - a signed 32 bit value    -2147483648..2147483647
ULONG - a unsigned 32 bit value            0..4294967295
There are lots of elements marked with ???. These are usually filled with
values, which have no effect at all. Thus they can normally be ignored.
For some values the usual contents is described.

******************************
***** OS1.x/OS2.x format *****
******************************
The OS1.x/OS2.x format is mainly an storage of the in-memory structures on
disk. This means there is many crap in that format, which may have undefined
values. This text tries to show which values are important and which not.

0x00 UWORD ic_Magic          always 0xE310
0x00 UWORD ic_Version        always 1
0x04 struct Gadget           (described below)
0x30 UBYTE ic_Type
     1 DISK                  a disk
     2 DRAWER                a directory
     3 TOOL                  a program
     4 PROJECT               a project file with defined program to start
     5 GARBAGE               the trashcan
     6 DEVICE                should never appear
     7 KICK                  a kickstart disk
     8 APPICON               should never appear
0x31 UBYTE ic_Pad            <undefined>
0x32 APTR  ic_DefaultTool    <boolean>
0x36 APTR  ic_ToolTypes      <boolean>
0x3A LONG  ic_CurrentX       X position of icon in drawer/on WorkBench
0x3E LONG  ic_CurrentY       Y position of icon in drawer/on WorkBench
0x42 APTR  ic_DrawerData     <boolean>
0x46 APTR  ic_ToolWindow     <boolean>
0x4A LONG  ic_StackSize      the stack size for program execution
                             (values < 4096 mean 4096 is used)
This is followed by certain other data structures:
struct DrawerData            if ic_DrawerData is not zero (see below)
struct Image                 first image
struct Image                 second image if ga_SelectRender not zero
                             (see below) in gadget structure
DefaultTool text             if ic_DefaultTool not zero (format see below)
ToolTypes texts              if ic_ToolTypes not zero (format see below)
ToolWindow text              if ic_ToolWindow not zero (format see below)
                             this is an extension, which was never implemented
struct DrawerData2           if ic_DrawerData is not zero and ga_UserData
                             is 1 (see below)

Now a description of the sub-formats:

a) The text storage method (DefaultTool, ToolWindow and ToolTypes):
0x00 ULONG tx_Size           the size of tx_Text including zero byte (tx_Zero)
0x04 ...   tx_Text           the plain text
.... UBYTE tx_Zero           the finishing zero byte
This means the text "Hallo" will be encoded as \00\00\00\06Hallo\00.

As ToolTypes are an array of texts the encoding is preceeded by another
ULONG value containing the number of entries. But to make parsing more
interessting it is not the number as one would expect, but the number of
entries increased by one and multiplied by 4. Thus 10 entries will have
44 as count.

b) The Gadget structure:
0x00 APTR  ga_Next           <undefined> always 0
0x04 WORD  ga_LeftEdge       unused ???
0x06 WORD  ga_TopEdge        unused ???
0x08 WORD  ga_Width          the width of the gadget
0x0A WORD  ga_Height         the height of the gadget
0x0C UWORD ga_Flags          gadget flags
     bit 2                   always set (image 1 is an image ;-)
     bit 1                   if set, we use 2 image-mode
     bit 0                   if set we use backfill mode, else complement mode
                             complement mode: gadget colors are inverted
                             backfill mode: like complement, but region
                             outside (color 0) of image is not inverted
     As you see, it makes no sense having bit 0 and 1 set.
0x0E UWORD ga_Activation     <undefined>
0x10 UWORD ga_GadgetType     <undefined>
0x12 APTR  ga_GadgetRender   <boolean> unused??? always true
0x16 APTR  ga_SelectRender   <boolean> (true if second image present)
0x1A APTR  ga_GadgetText     <undefined> always 0 ???
0x1E LONG  ga_MutualExclude  <undefined>
0x22 APTR  ga_SpecialInfo    <undefined>
0x26 UWORD ga_GadgetID       <undefined>
0x28 APTR  ga_UserData       lower 8 bits:  0 for old, 1 for icons >= OS2.x
			     upper 24 bits: undefined

c) The DrawerData structure:
This structure is useful for drawers and disks (but there are some
icons of other types, which still have these obsolete entries).
0x00 struct NewWindow        (see below)
0x30 LONG  dd_CurrentX       the current X position of the drawer window
                             contents (this is the relative offset of the
                             drawer drawmap)
0x34 LONG  dd_CurrentY       the current Y position of the drawer window
                             contents

d) The NewWindow structure used by DrawerData:
0x00 WORD  nw_LeftEdge       left edge distance of window
0x02 WORD  nw_TopEdge        top edge distance of widndow
0x04 WORD  nw_Width          the width of the window (outer width)
0x06 WORD  nw_Height         the height of the window (outer height)
0x08 UBYTE nw_DetailPen      always 255 ???
0x09 UBYTE nw_BlockPen       always 255 ???
0x0A ULONG nw_IDCMPFlags     <undefined>
0x0E ULONG nw_Flags          <undefined>
0x12 APTR  nw_FirstGadget    <undefined>
0x16 APTR  nw_CheckMark      <undefined>
0x1A APTR  nw_Title          <undefined>
0x1E APTR  nw_Screen         <undefined>
0x22 APTR  nw_BitMap         <undefined>
0x26 WORD  nw_MinWidth       <undefined> often 94, minimum window width
0x28 WORD  nw_MinHeight      <undefined> often 65, minimum window height
0x2A UWORD nw_MaxWidth       <undefined> often 0xFFFF, maximum window width
0x2C UWORD nw_MaxHeight      <undefined> often 0xFFFF, maximum window width
0x2E UWORD nw_Type           <undefined>

e) The DrawerData2 structure for OS2.x drawers:
0x00 ULONG dd_Flags          flags for drawer display
     value 0                 handle viewmode like parent drawer current
                             setting (OS1.x compatibility mode)
     bit 0                   view icons
     bit 1                   view all files (bit 0 maybe set or unset
                             with this)
0x04 UWORD dd_ViewModes      viewmodes of drawer display
     value 0                 show icons (OS1.x compatibility mode)
     value 1                 show icons
     value 2                 show sorted by name
     value 3                 show sorted by date
     value 4                 show sorted by size
     value 5                 show sorted by type

f) And now the last element, the Image structure:
0x00 WORD  im_LeftEdge       always 0 ???
0x00 WORD  im_TopEdge        always 0 ???
0x04 WORD  im_Width          the width of the image
0x06 WORD  im_Height         the height of the image
0x08 WORD  im_Depth          the image bitmap depth
0x0A APTR  im_ImageData      <boolean> always true ???
0x0E UBYTE im_PlanePick      foreground color register index
0x0F UBYTE im_PlaneOnOff     background color register index
0x10 APTR  im_Next           always 0 ???
This is followed by the image data in planar mode. The width of the
image is always rounded to next 16bit boundary.

******************************
***** NewIcon extension ******
******************************

As the original format is very limited when using more than the 4 or 8 default
colors and also when using different palette sets than the default, there have
been ideas how to circumvent this. A Shareware author invented NewIcons
format, which uses the ToolTypes to store image data, as expanding the original
format very surely would haven broken compatibility.

The NewIcons stuff usually starts with following 2 ToolTypes text (text inside
of the "" only):
" "
"*** DON'T EDIT THE FOLLOWING LINES!! ***"

Aftwerwards the image data is encoded as ASCII. The lines for first image
always start with "IM1=". If present the second image starts with "IM2=".

The first line of each image set contains the image information and the
palette.
Example: "IM1=B}}!'��5(3%;ll����T�S9`�"

0x00 UBYTE ni_Transparency
     "B"                     transparency on
     "C"                     transparency off
0x01 UBYTE ni_Width          image width + 0x21  - "}" means width 92
0x02 UBYTE ni_Height         image height + 0x21 - "}" means height 92
0x03 UWORD ni_Colors         ASCII coded number of palette entries:
     entries are: ((buf[3]-0x21)<<6)+(buf[4]-0x21)
     "!'" means 6 entries
Afterwards the encoded palette is stored. Each element has 8 bit and colors
are stored in order red, green, blue. The encoded format is described below.
The ni_Width and ni_Height maximum values are 93. The maximum color value
is theoretically 255. I have seen images with at least 257 stored colors
(but less than 256 used).

The following lines contain the image data encoded with the same system as
the palette. The number of bits used to encode an entry depends of the number
of colors (6 colors f.e. need 3 bit). The lines have maximum 127 bytes
including the "IM1=" or "IM2=" header. Thus including the zero byte, the
string will be 128 byte.

En/Decoding algorithm:
Each byte encodes 7bit (except the RLE bytes)
Bytes 0x20 to 0x6F represent 7bit value 0x00 to 0x4F
Bytes 0xA1 to 0xD0 represent 7bit value 0x50 to 0x7F
Bytes 0xD1 to 0xFF are RLE bytes:
  0xD1 represents  1*7 zero bits,
  0xD2 represents  2*7 zero bits and the last value
  0xFF represents 47*7 zero bits.

Opposite to the original icon format, the NewIcons format uses chunky modus
to store the image data.

The encoding for images and palette stops at the string boundary (127 bytes)
with buffer flush (and adding pad bits) and is restarted with next line.

******************************
****** OS3.5 extension *******
******************************

The OS3.5 format introduces nearly the same information as in NewIcons, but
in a more usable format. The tooltypes are no longer misused, but a new data
block is appended at the end of the icon file. This data block is in IFF
format.
It consists of the standard header
0x00 UBYTE[4] ic_Header      set to "FORM"
0x04 ULONG    ic_Size        size [excluding the first 8 bytes!]
0x08 UBYTE[4] ic_Identifier  set to "ICON"

Now Chunks of different data follow. Each chunk consists of 8 header bytes
and the data bytes. If the size in header is uneven, then it is automatically
paddind with 1 byte at the end.

Currently 3 chunks are used with following data. Note that IFF generally
allows expansion and chunk reordering, so do not rely on any current size
information or chunk order, but skip unknown data based on the size
information stored in file.

1)
0x00 UBYTE[4] fc_Header      set to "FACE"
0x04 ULONG    fc_Size        size [excluding the first 8 bytes!]
0x08 UBYTE    fc_Width       icon width subtracted by 1
0x09 UBYTE    fc_Height      icon height subtracted by 1
0x0A UBYTE    fc_Flags       flags
     bit 0                   icon is frameless
0x0B UBYTE    fc_Aspect      image aspect ratio:
     upper 4 bits            x aspect
     lower 4 bits            y aspect
0x0C UWORD    fc_MaxPalBytes maximum number of bytes used in image palettes
                             subtracted by 1 (i.e. if palette 1 has 17 and
                             palette 2 has 45 entries, then this is 45)

2) Now 2 chunks of this type may come, where first chunk is image 1
and second chunk is image 2.
0x00 UBYTE[4] im_Header      set to "IMAG"
0x04 ULONG    im_Size        size [excluding the first 8 bytes!]
0x08 UBYTE    im_Transparent number of the transparent color
0x09 UBYTE    im_NumColors   number of colors subtracted by 1
0x0A UBYTE    im_Flags
     bit 0                   there exists a transparent color
     bit 1                   a palette data is attached (NOTE, that first
                             image always needs palette data, whereas the
                             second one can reuse the first palette.)
0x0B UBYTE    im_ImageFormat storage format of image data
     value 0                 uncompressed
     value 1                 run-length compressed
0x0C UBYTE    im_PalFormat   storage format of palette data (same as above)
0x0D UBYTE    im_Depth       the number of bits used to store a pixel
0x0E UWORD    im_ImageSize   number of bytes used to store image (subtracted
                             by 1)
0x10 UWORD    im_PalSize     number of bytes used to store palette
                             (subtracted by 1)
0x12 UBYTE[...]              the image data
.... UBYTE[...]              the palette data (if existing)


Now about the run-length compression. This is equal to the run-length method
in IFF-ILBM format: The input data is seen as a bit-stream, where each entry
has im_Depth bits for image or 8 bits for palette. First comes an 8 bit RLE
block with following meaning:
0x00 .. 0x7F copy the next n entries as they are, where n is "RLE-value"+1
0x80         ignore this, do nothing
0x81 .. 0xFF produce the next entry n times, where n is 256-"RLE-value"+1
             (if using signed chars n is "RLE-value"+1)

In uncompressed mode, each byte represents one pixel (even if lower depth is
used).

********************************