Add Icon/cursor files


Hi, I'm Bart Meijer. I created many programs the last few years, including SnIco Edit ( and a few components. As I didn't find many complete documentation on icons, I decided to create this document. It is also available in DOC format: I hope you will find it usefull.


Although the format described in this document is used by SnIco Edit there is no 100% guarantee this description is in any way complete or accurate. There is, at least to my knowledge, no official ICO specification made by Microsoft nor any patent or copyright regarding using/editing this format. Use of this information is at your own risk. Comments and suggestions can be sent to

Assumed knowledge of the reader:

- You know what bytes, bits and files are.
- You know somewhat of pixels, colors, palettes, etc.
- You can count :)

Format description

Almost every small image in Windows is an icon. ICO files are small files with small images inside. These images are based on the Bitmap file format. Why not using Bitmaps then? In the early days of Windows 3.11 video cards were expensive and not capable of showing 32-bit colors on a 1024x768 resolution. Because 256 color images would draw awful on a 16 color screen, there was need for images that could be adjusted to the computers. ICO files consist of images in different color depths and Windows can choose the one that best fits the system.

The cursor has CUR as extension. A cursor is an icon that can be used as pointer for you mouse. CUR files are almost identical to icons with exception of the iconinfo structure.


- Up to 65535 images in one file.
- Maximum of 255x255 pixels for each image
- Only one image for each format.

The ICO file

This part of the document describes the ICO file format.

The first 6 bytes in the file is the header. It describes the type and number of icons in this file.

FileHeader (6 bytes)
Reserved (2 bytes), always 0
IconType (2 bytes), if the image is an icon itís 1, for cursors the value is 2.
IconCount (2 bytes), number of icons in this file.

Icon info

After the header for each image in this file there is a 16 byte description. This is useful to determine which image to load rather then browsing the file for each image. If the Icontype is an icon it uses this iconinfo:

IconInfo (icons) (16 bytes)
Width (1 byte), Width of Icon (1 to 255)
Height (1 byte), Height of Icon (1 to 255)
ColorCount (1 byte), Number of colors, either 0 for 24 bit or higher, 2 for monochrome or 16 for 16 color images.
Reserved (1 byte), Not used (always 0)
Planes (2 bytes), always 1
BitCount (2 bytes), number of bits per pixel (1 for monochrome, 4 for 16 colors, 8 for 256 colors, 24 for true colors, 32 for true colors + alpha channel)
ImageSize (4 bytes), Length of resource in bytes
ImageOffset (4 bytes), start of the image in the file.

For cursor files the planes is replaced by the x coordinate of the cursor and the bitcount replaced by the y coordinate.

After the image descriptions the actual image data follows. For each image there is a bitmap header, xor-map (referred as color map) and and-map (referred as transparent map).

Image data

First we take a look at the bitmap header. Itís 40 bytes in length and tells us something about the color map.

BitmapHeader (40 bytes)
Size (4 bytes), size of this structure (always 40)
Width (4 bytes), width of the image (same as iconinfo.width)
Height (4 bytes), scanlines in the color map + transparent map (iconinfo.height * 2)
Planes (2 bytes), always 1
BitCount (2 bytes), 1,4,8,24,32 (see iconinfo for details)
Compression (4 bytes), we donít use this (0)
SizeImage (4 bytes), we donít use this (0)
XPelsPerMeter (4 bytes), we donít use this (0)
YPelsPerMeter (4 bytes), we donít use this (0)
ColorsUsed (4 bytes), we donít use this (0)
ColorsImportant (4 bytes), we donít use this (0)

We can conclude that this structure is basically added only for compatibility with the bitmap format. If we would add 1 byte to the iconinfo structure we could save 39 bytes for each image. Terrible waste of your disk space ;)

The reading of an image is rather complicated, so I will use the following example to explain: We have a monochrome image (2 colors/1 bit each pixel) with a width and height of 15 pixels.

Following the bitmap header is the palette. This is only used in images with a color depth or 1 (2 colors), 4 (16 colors) or 8 bits (256 colors). I recommend using always the black and white color, because these are necessary for determining inversed transparent pixels. The palette contains for each color 4 bytes (blue, green, red, and not used).

Next the color map. This map contains the color information of every pixel in the image. But watch it: itís build from bottom up or in other words the first pixel is the bottom-left one.

The value of a pixel in the image is depending on the bitcount either an index of the color in the palette, or an rgb value. For example a bitcount of 1 would every pixel have 2 possibilities: 0 or 1. If the value is 0 the color of the pixel is color 0 in the palette, same goes for a bitcount of 4 or 8. A bitcount of 24 results in 4 bytes for each pixel (blue, green, red, not used). A bitcount of 32 would give the same result as 24 bpp, but the byte Ďnot usedí contains the opacity value (0-255) where 0 is fully transparent.

You should read the color map in scanlines. The width of each scanline is (bitcount * width) / 8 bytes rounded up to whole bytes + the number of bytes rounded up to a number dividable by 4, called padding.

The size of the scanline would be
15 pixels x 1 bit = 15 bits
Rounded to whole bytes this makes 2 bytes (16 bits).
The padding of the scanline is 2, because the first number above 2 dividable by 4 is 4.
4 Ė 2 bytes = 2 bytes padding
The total length of the scanline in bytes is 2 bytes of pixel information and 2 bytes of padding = 4 bytes.

The number of scanlines is the height of the image, the size of the color map in this example would be 4 bytes of the scanline x 15 pixel in height = 60 bytes.

The transparent map is also build out of scanlines. For each pixel there is 1 bit that tells if the pixel is transparent (1) or solid (0). If the pixel is transparent and the color of the pixel is white, the pixel inversed transparent. The width of a scanline is 1\8 * width, rounded to whole bytes, rounded to 4 bytes. You can use the calculation used by the example to calculate this. The size of the transparent map in this example would be 60 bytes.

The total size of the image in this example is the bitmap header (40 bytes) + the palette size (2 colors, 8 bytes) + the size of the color map (60 bytes) + the size of the transparent map (60 bytes) = 168 bytes.

Further information

References, online documentation of icons., Website of Microsoft creator of Windows.


AND-map, transparent map see image data
CUR, extension of the cursor file
Cursor, see format description.
ICO, extension of the icon file
Icon, see format description.
Image, part of an icon file with bitmap header, color map and transparent map.
Palette, array of colors
Windows, the operating system from Microsoft.
XOR-map, color map see image data

Related Discussions
  • USING DLLS (2001-01-04 01:47:50)
    Hi again Goober ... :o) Let's take NETAPI32.DLL as an example. This DLL is created by Microsoft and the explanation of its use is described in...
  • ADD TO RESOURCE ON RUNTIME (2001-01-04 11:00:49)
    I think what you are asking is to change the .EXE file at run-time. Yes, it is possible, but nobody I found will share that information. If you...
    Just draw your icons with the Borland Image Editor (Delivered with Delphi). It allows to save different icons in one ico file as well.
  • PRINTING A PDF FORM (2001-01-07 05:57:11)
    Hello Tom, If you find a delphi solution to bypass the acrobat Printer i am very interrested. Actually i am printing a lot of invoice to the...
  • SHARE API (2001-01-06 15:53:18)
    Thanks for your reply, but I'm not totally stupid :-) I've already looked for this function in Delphi files !! No more problem : I've found a very...
  • SAVING CURSORS? (2001-01-07 05:09:39)
    Well whenever I want to login I have to enable cookies - that's a bit annoying. And people were able to enter their email addresses before as...
  • BTRIEVE ERROR CODE 3014, ęNO ENGINE FOUNDĽ ,PLEASE HELP... (2001-01-10 09:01:39)
    Contact me via e-mail at I have a very good friend that works in support at Pervasive and he will telephone you to work...
  • ICONS (2001-01-10 09:09:37)
    This component is not working correctly. Colors look different when saved with this component.
    This link describes some API routines dealing Wave files. At the end of the article is the E-Mail address of the author. Perhaps he will be...
Latest News
Submit News Form Past News
Latest Forum Entries