Icons in AmigaOS and its derivatives (MorphOS, AROS), are basically the same thing as on other operating systems – a small images identifying files, directories, disks and so on. Except of image data, Amiga icons contain some additional informations. File icons can contain a path to an application used to open the project file when it is doubleclicked (the default tool). They can also contain so-called tooltypes, which are just strings used as program parameters. Dawer (folder) and disk icons contain position, size and viewmode of a window opened on the desktop after clicking the icon. All icons can store their position in parent drawer (or desktop) window.
I've decided to write this unofficial specification, after I've found none on the Internet. While Amiga icons are not very popular, as AmigaOS itself is rather a niche, hobby OS, someone may find this article useful. Note that there are a few kinds of Amiga icons. This article describes an old, bitplane based format. Later NewIcons and PNG icons (as used in AmigaOS 4, MorphOS and AROS) are not described here.
Icons in AmigaOS are separate files, with the same name as the 'main' file, and '.info' extension at the end. Note that if a file has an extension by itself (for example 'archive.lha'), the '.info' extension does not replace file extension, but is appended at the end, so an icon for 'archive.lha' has the name 'archive.lha.info'. It may look strange for a Windows user, but comes from the fact, that Amiga system does not use extensions for file type recognition at all. An executable file without an '.exe' is perfectly OK for example. To say more, executable files on Amiga have no extension at all usually.
When a file has no icon associated, it is invisible in Workbench window until "Show all files" viewmode is selected. Then a default icon for the file is used. Older AmigaOS versions have stored default icons in "ENVARC:sys/def_xxxx.info", where xxxx is 'drawer', 'project', 'tool' or 'disk'. Some extensions to this system have been developed, which allowed different icons for different file types. What is important here, default icons have the same file format as real ones. One can easily create a real icon from a default one, using system tools, or just by copying the icon and changing its name.
The icon file is composed directly of some system structures. It has an advantage of fast icon loading and displaying, the file is just loaded to memory, structures addresses are extracted and may be passed directly to Intuition, the main Amiga UI library. On the other hand many fields of these system structures are unused or redundant, making the icon file bigger. Some data in these structures are referenced via pointers in memory, in an icon file, the data are stored after structures in a defined order.
The selected state of an Amiga icon is not generated programatically, but is specified in the icon itself. Often the selected state is a second, separate image, sometimes it is specified as palette entries swap.
| DiskObject | DrawerData | Image 1 | raster data for Image 1 |
Image 2 | raster data for Image 2 |
default tool | tooltypes |
NOTE: All multi-byte fields of an Amiga icon are big-endian. x86 programmers have to swap bytes.
| 0000 | uint16 | do_Magic | A file identifier. All icons have 0xE310 here. |
| 0002 | uint16 | do_Version | Icon version. The current version is 1. |
| 0004 | uint32 | do_Gadget.NextGadget | Unused. Contains 0 usually. |
| 0008 | int16 | do_Gadget.LeftEdge | Horizontal position of the icon left edge relative to its parent window left edge. This field is only used when an icon is loaded into memory. |
| 0010 | int16 | do_Gadget.TopEdge | Vertical position of the icon top edge relative to its parent window top edge. This field is only used when an icon is loaded into memory. |
| 0012 | uint16 | do_Gadget.Width | Icon width in pixels. |
| 0014 | uint16 | do_Gadget.Height | Icon height in pixels. |
| 0016 | uint16 | do_Gadget.Flags | Gadget flags. Used only by Intuition, when the icon is loaded into memory. Usually set to 5. |
| 0018 | uint16 | do_Gadget.Activation | Gadget activation flags. The usual value is 3 here (both 'immediate' and 'relverify' activation methods set). |
| 0020 | uint16 | do_Gadget.GadgetType | Gadget type. The usual value is 1 here (means boolean gadget). |
| 0022 | uint32 | do_Gadget.GadgetRender | In memory a pointer to the first Image, used for not selected state. In file it should be any non-zero value. Zero here should not happen. |
| 0026 | uint32 | do_Gadget.SelectRender | In memory a pointer to the second Image, used for selected state. In file non-zero value means that the icon has the second Image and raster data. |
| 0030 | uint32 | do_Gadget.GadgetText | Unused. Usually 0. |
| 0034 | uint32 | do_Gadget.MutualExclude | Unused. Usually 0. |
| 0038 | uint32 | do_Gadget.SpecialInfo | Unused. Usually 0. |
| 0042 | uint16 | do_Gadget.GadgetID | Unused. Usually 0. |
| 0044 | uint32 | do_Gadget.UserData | Used for icon revision. 0 for OS 1.x icons. 1 for OS 2.x/3.x icons. |
| 0048 | uint8 | do_Type | A type of icon:
|
| 0049 | uint8 | padding | Just padding byte. |
| 0050 | uint32 | do_DefaultTool | In memory a pointer to a default tool path string. In file should be interpreted as boolean field indicating default tool presence. |
| 0054 | uint32 | do_ToolTypes | In memory a pointer to a table containing pointers to tooltype strings. In file should be interptered as boolean field indicating tooltypes table presence. |
| 0058 | int32 | do_CurrentX | Virtual horizontal position of the icon in the drawer window. |
| 0062 | int32 | do_CurrentY | Virtual vertical position of the icon in the drawer window. |
| 0066 | uint32 | do_DrawerData | In memory a pointer to DrawerData structure. In file should be interpreted as a boolean field indicating DrawerData presence. |
| 0070 | uint32 | do_ToolWindow | Unused. |
| 0074 | uint32 | do_StackSize | Task stack size for an application. (in case of project file, this size is for default tool application). |
| Total size: 78 bytes. | |||
The structure starts from a NewWindow structure. Note that DrawerData may be just skipped when only icon image is to be decoded. I've put the information here just for completness.
| 0000 | int16 | dd_NewWindow.LeftEdge | Drawer window left edge relative to the Workbench screen. |
| 0002 | int16 | dd_NewWindow.TopEdge | Drawer window top edge relative to the Workbench screen. |
| 0004 | int16 | dd_NewWindow.Width | Drawer window width. |
| 0006 | int32 | dd_NewWindow.Height | Drawer window height. |
| 0008 | uint8 | dd_NewWindow.DetailPen | Number of graphics pen used to render window details. |
| 0009 | uint8 | dd_NewWindow.BlockPen | Number of graphics pen used to render window frame background. |
| 0010 | uint32 | dd_NewWindow.IDCMPFlags | Kinds of IDCMP (GUI -> application) events requested. |
| 0014 | uint32 | dd_NewWindow.Flags | Various window flags (borders, system gadgets etc.). |
| 0018 | uint32 | dd_NewWindow.FirstGadget | In memory a pointer to the first window gadget in a linked list. Unused in an icon file. |
| 0022 | uint32 | dd_NewWindow.CheckMark | In memory a pointer to checkmark imagery for the window. Unused in an icon file. |
| 0026 | uint32 | dd_NewWindow.Title | In memory a pointer to the window title string. Unused in an icon file. |
| 0030 | uint32 | dd_NewWindow.Screen | In memory a pointer to system Screen a window is to be opened on. Unused in an icon file. |
| 0034 | uint32 | dd_NewWindow.BitMap | In memory points to a system BitMap for the window. Unused in an icon file. |
| 0038 | int16 | dd_NewWindow.MinWidth | Minimum width for the window. |
| 0040 | int16 | dd_NewWindow.MinHeight | Minimum height for the window. |
| 0042 | uint16 | dd_NewWindow.MaxWidth | Maximum width for the window. |
| 0044 | uint16 | dd_NewWindow.MaxHeight | Maximum height for the window. |
| 0046 | uint16 | dd_NewWindow.Type | Window type (public/custom screen). |
| 0048 | int32 | dd_CurrentX | Horizontal position of originating icon. |
| 0052 | int32 | dd_CurrentY | Vertical position of originating icon. |
| Total size: 56 bytes. | |||
| 0000 | int16 | LeftEdge | Image left edge position relative to the icon left edge. Image clipping should be done for negative values. |
| 0002 | int16 | TopEdge | Image top edge position relative to the icon top edge. Image clipping should be done for negative values. |
| 0004 | uint16 | Width | Image width in pixels. May be less than icon width (stored in DiskObject.Gadget), missing columns use color 0. If it is bigger than icon width I recommend to clip the image. |
| 0006 | uint16 | Height | Image height in pixels. May be less than icon height (stored in DiskObject.Gadget), missing rows use color 0. If it is bigger than icon height I recommend to clip the image. |
| 0008 | uint16 | Depth | Number of image bitplanes (see chapter 3. 5.). |
| 0010 | uint32 | ImageData | In memory it is a pointer to bitplanes, in file it should be treated as a boolean value (if not zero, bitplane data are stored as shown on fig. 1.). |
| 0014 | uint8 | PlanePick | A bitfield controlling which image bitplane is copied to which screen bitplane. Used only by classic Amiga graphics chipset. Meaningless in a file, as it is interpreted in Amiga chipset context displaying particular screen. |
| 0015 | uint8 | PlaneOnOff | A bitfield controlling screen bitplanes not fed with icon data. They may be either filled by zeros or by ones. Used only by classic Amiga graphics chipset. Meaningless in a file, as it is interpreted in Amiga chipset context displaying particular screen. |
| 0016 | uint32 | NextImage | Unused. Usually 0. |
| Total size: 20 bytes. | |||
Icon image data are stored as bitplanes. While a bit cumbersome for nowadays display devices, this format is a native one for Amiga graphics chipsets. Then image data, once loaded into, graphics ("chip") memory, can be directly blitted to a screen. On bitplanes, every pixel occupies one bit, regardless of number of palette colors. Palette size is determined by a number of bitplanes, for N bitplanes there are 2N colors available. To determine a pixel color, one has to gather this pixel bits from all bitplanes (bitplane 0, which comes first in the data, is the most significant one) as shown on fig. 2, form a number and use it as an index to the palette table.

Amiga icon bitplanes are not interleaved, complete planes are stored one after one. Pixel scanning order is usual left-to-right, top-to-bottom. Plane rows are padded to 16-bit words, there is no vertical padding.
In spite of image data are palette-based, there is no palette stored in the icon, just some standard palette is assumed. Unfortunately there are a few "standard" palettes used:
There were some other palettes proposed, usually extending MagicWB with more colors, but they have not gained popularity. NewIcons format solved the problem finally, storing a palette inside an icon. Which palette one should use converting the icon image to RGB color space? If we limit possibilities to palettes shown above, icon revision allows to choose between OS 1.x and OS 2.x palette. Then if revision is 1 and number of bitplanes is 3, the icon is MagicWB one.
Usually you will be only interested in extracting images from an icon, and convert them to the RGB color space (unless you are writing an Amiga Workbench replacement...). Here is a short guide how to do it: