factograf
EN
Sign in

Windows icon file format

ICO (file format)

All data from the card 7
Filename extension
.ico
Internet media type
image/x-icon (but see below)
Uniform Type Identifier (UTI)
com.microsoft.ico
Developed by
Microsoft
Type of format
Graphics file format for computer icons
Container for
BMP and PNG
Extended to
CUR

The ICO file format is an image file format for computer icons in Microsoft Windows. An ICO file holds one or more images at multiple sizes and color depths, from which Windows selects and scales the most appropriate one for a given use. A Windows application's own icon — shown on the desktop, in the Start menu, or in File Explorer — is stored in the same format inside its executable as an icon resource, rather than as a separate file.

The CUR file format is an almost identical format for non-animated cursors in Microsoft Windows. The two differ only in the bytes that identify the file and in a hotspot recorded in the CUR header — the pixel offset, in x,y coordinates, from the top-left corner of the cursor image to the point at which the user is actually pointing.

The ANI file format is used for animated Windows cursors. ANI is a RIFF container; each frame within it is a complete CUR-format image and may itself contain images at multiple sizes.

First introduced as monochrome images in Windows 1.0, the format acquired its directory-based multi-image structure in Windows 3.0 and support for larger sizes and higher color depths in Windows 95; Windows Vista added 256×256 images and PNG compression. Each image is stored either as a DIB or as a complete PNG file, and a file typically bundles several so the best match for the requested size and color depth can be chosen.

History

Icons introduced in Windows 1.0 were monochrome; in Windows 1.x and 2.x, ICO and CUR files were raw binary images with no directory wrapper — each file contained a single such image, at 64×64 pixels for icons and 32×32 for cursors. The 64×64 icon size was designed for a 1024×1024 target display and was shown downscaled on the lower-resolution monitors of the era. These single-image icons and cursors were created with the SDK's Icon Editor (ICONEDIT), which worked in separate Icon, Cursor and Bitmap modes. In icon and cursor modes it offered four pen "colors" — White, Black, Screen and -Screen — where a Screen pixel took on the color of the screen pixel already beneath it and a -Screen pixel took the opposite (inverted) color, the same transparent-and-invert behavior later carried by the 1-bit AND/XOR mask of the ICONDIR format (see below). The two masks were stored in the opposite order used by that later format, however: the AND mask came first, followed by the XOR mask, and each mask's rows were padded to a 2-byte (word) boundary rather than the 4-byte boundary the ICONDIR format uses. Cursors additionally stored a hotspot, which the Icon Editor placed at the image's center by default if the author did not set one explicitly. Applications loaded icons and cursors only from the resources compiled into an executable module, via the LoadIcon and LoadCursor functions, each taking a module handle and a resource name.

The multi-image ICONDIR format and the DIB-based frame layout were introduced in Windows 3.0, replacing the raw binary format: each file now begins with a directory of fixed-size entries followed by the image data as DIBs, using the 40-byte BITMAPINFOHEADER as the norm. The legacy 12-byte BITMAPCOREHEADER is also accepted; it is the bitmap header of OS/2 Presentation Manager 1.x, whose own icon and pointer resources were likewise built around an AND/XOR-mask-plus-image scheme comparable to the one Windows uses, though held in a different, multi-image-capable container. Shipping 3.x icons used only 1 bpp (monochrome) and 4 bpp (16-color VGA), often pairing both depths in a single file, with 8 bpp not yet in common use.

With Windows 95, the icon directory gained the headroom to describe images of any size from 1×1 up to 256×256 pixels (including non-square sizes) — by letting a bWidth or bHeight value of 0 stand for 256 pixels — and added a new 32 bpp color depth (16.7 million colors, without an alpha channel) on top of the 1, 4 and 8 bpp depths the format already supported; though these were format capabilities rather than depths the shell of the era actually rendered, and the shell could not display very large icons. Shipped system icons of the era remained 16-color (4 bpp) in practice. It was possible to enable 16-bit (65535 color) icons by setting the Shell Icon BPP value in the registry; the high-color icons feature of Microsoft Plus! for Windows 95 applied this setting. The Shell Icon Size registry value set the size of the large (desktop) shell icons and could be adjusted from 16 to 72 pixels through the Appearance tab of the Display Properties dialog, defaulting to 32 pixels; the small shell icon size was fixed and could not be changed. The notification area of the Windows taskbar was limited to 4 bpp icons until Windows Me when it was updated to support 16-bit icons.

Windows NT 4.0 was the first release to ship system icons at 8 bits per pixel (256 colors) and to add a 48×48-pixel size alongside the existing 16×16 and 32×32. The 256-color depth and the 48×48 size became common across the 98, Me and 2000 generation.

Windows XP extended the 32-bit format with an 8-bit alpha channel (24-bit color plus per-pixel transparency) and was the first release to ship system icons that used it, allowing semitransparent areas like shadows, anti-aliasing, and glass-like effects to be drawn in an icon. Its shell used 48×48-pixel icons in Windows Explorer, the largest size Microsoft recommended for the release; larger images were downscaled when no closer size was available.

The format could describe a 256×256 image well before Vista, but an uncompressed 32-bit image at that size needs about a quarter of a megabyte per frame (256 × 256 × 4 bytes), which made shipping such icons impractical. Windows Vista made 256×256 icons practical by adding support for storing frames in the compressed PNG format, and was the first release to render and ship system icons at that size. Although compression is not required, Microsoft recommends that all 32-bit color 256×256 icons in ICO files should be stored in PNG format to reduce the overall size of the file. The Windows Vista Explorer supports smoothly scaling icons to non-standard sizes which are rendered on the fly even if an image is not present for that size in the icon file. The Windows Vista shell adds a slider for "zooming" the icon sizes in and out. With users using higher resolutions and high DPI modes, larger icon formats (such as 256×256) are recommended. Windows Vista and later versions also dropped the ability to display icons stored in 16-bit (New Executable) modules.

The color depth of cursors trailed that of icons. On the 16-bit Windows 3.x line, cursors stayed monochrome (1 bpp) even after icons had moved to 16 colors (4 bpp) in Windows 3.0. Color cursors first appeared on the NT 3.x line, which shipped 4 bpp cursors, and reached the consumer line with Windows 95. 32-bit cursors did not appear until Windows Vista. Cursors that invert the screen pixels beneath them still include a monochrome (1 bpp) frame, since that is the only way to produce the effect (described below).

The pixel size of cursors stayed fixed at 32×32 on standard-DPI systems throughout the 9x and NT eras, up to Windows Vista. Through Windows XP, the desktop was not scaled continuously with DPI. On systems Windows XP treated as high-DPI — those whose primary display was 150 DPI or greater — XP doubled the nominal cursor size (SM_CXCURSOR/SM_CYCURSOR) to 64×64 so the pointer would not become too small to use, and Microsoft recommended authoring cursor sets with both 32×32 and 64×64 images for such systems — though the cursors XP itself shipped contained only 32×32. Windows Vista was the first release to scale icon sizes continuously with the display DPI. From Windows 7, the cursors shipped with Windows began carrying several sizes in a single file for the same reason — adding a 48×48 tier alongside the existing 32×32. Windows 8.1 added a 64×64 tier and introduced per-monitor DPI awareness, letting windows on different displays use different scale factors. From Windows 10 cursors also shipped in a larger five-size set. The system selects among these sizes by display scaling (see Default sizes and DPI scaling for the exact set).

Icon size and color-depth timeline

The standard color depths and pixel sizes shipped in system icons changed over successive releases, as summarized below.

Standard shipped icon color depths and sizes by release
Release Color depths (bpp) Standard sizes (px) Notes
Windows 1.x–2.x 1 64 (icons), 32 (cursors) Raw single image, no directory
Windows 3.x / NT 3.x 1, 4 32 ICONDIR + DIB introduced; 1 bpp + 4 bpp paired
Windows 95 4 16, 32 Higher depths supported by the shell but rarely shipped; 16 px is the small (taskbar/notification-area) icon size
Windows NT 4.0 / 98 / Me / 2000 4, 8 16, 32, 48 8 bpp and 48 px introduced in NT 4.0; became common by 98/Me
Windows XP 4, 8, 32 16, 32, 48 32 bpp with alpha channel introduced
Windows Vista / 7 4, 8, 32 16, 32, 48, 256 256 px added, stored as PNG
Windows 8 / 8.1 4, 8, 32 16, 20, 24, 32, 40, 48, 64, 256 Eight-size ladder completed
Windows 10 / 11 32 16, 20, 24, 32, 40, 48, 64, 256 Shipped icons are 32 bpp only

MIME type

While the IANA-registered MIME type for ICO files is image/vnd.microsoft.icon, it was submitted to IANA in 2003 by a third party and is not recognized by Microsoft software, which uses image/x-icon or image/ico instead. Erroneous types image/ico, image/icon, text/ico and application/ico have also been seen in use.

Both ICO and CUR remain partially supported in current web browsers for legacy reasons, although the CUR format's screen pixel inversion feature was never implemented there.

Structure

An ICO or CUR file is made up of an ICONDIR ("Icon directory") structure, containing an ICONDIRENTRY structure for each image in the file, followed by a contiguous block of all image data. Each image is stored either as a raw DIB (see DIB format) or as a complete PNG file (see PNG format). It is customary practice to store the image data in the same order as the entries in the image directory.

All values in ICO/CUR files are represented in little-endian byte order.

ICONDIR structure

Offset
(bytes)
Field Size
(bytes)
Description
0 idReserved 2 Reserved. Must be 0.
2 idType 2 Image type: 1 for ICO image, 2 for CUR image. Other values are invalid.
4 idCount 2 Number of images in the file.
6 idEntries idCount * 16 ICONDIRENTRY array. Each entry represents an image.

ICONDIRENTRY structure

Offset
(bytes)
Field Size
(bytes)
Description
0 bWidth 1 Image width in pixels. Can be any number between 0 and 255. 0 means width is 256.
1 bHeight 1 Image height in pixels. Can be any number between 0 and 255. 0 means height is 256.
2 bColorCount 1 Number of colors in the color table. For paletted depths: 2 for 1 bpp, 16 for 4 bpp; 0 for 8 bpp and above. An incorrect value affects image selection scoring for icons.
3 bReserved 1 Reserved. Must be 0.
4 wPlanes 2
  • In icon format: Specifies color planes. Should be 0 or 1.
  • In cursor format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
6 wBitCount 2
  • In icon format: Specifies bits per pixel.
  • In cursor format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
8 dwBytesInRes 4 Image data size in bytes.
12 dwImageOffset 4 Specifies the offset of the DIB or PNG data from the beginning of the ICO/CUR file.

DIB format

DIB frames are stored as raw DIB (.bmp) data: a BITMAPINFOHEADER followed by the pixel data and a 1-bit AND mask, without the BITMAPFILEHEADER that precedes DIB data in a standalone.bmp file. Frames should use the standard 40-byte BITMAPINFOHEADER (biSize = 40); the extended BITMAPV4HEADER (108 bytes) and BITMAPV5HEADER (124 bytes) are not accepted.

The height declared in the BITMAPINFOHEADER is twice the height declared in the image directory, because the DIB holds two stacked parts of equal dimensions: the color image (the XOR mask) above the 1-bit AND mask. Rows in both parts are padded to a multiple of four bytes.

The AND mask is one bit per pixel regardless of the image's color depth: a 0 bit draws the corresponding image pixel, while a 1 bit leaves the screen unchanged, making the pixel transparent.

The color image is conventionally stored at 1, 4, 8 or 32 bits per pixel, the depths authoring tools produce; 16- and 24-bit frames are also loaded by Windows, described below.

A 1-bit (monochrome) frame carries a two-entry color table: index 0 is black (#00000000) and index 1 is white (#00FFFFFF). This format dates to the monochrome displays for which icons and cursors were originally designed, where the result was computed as Output = (Existing AND Mask) XOR Image. The AND and XOR bits combine to give four pixel types:

AND bit XOR bit Pixel type
0 1 White
0 0 Black
1 0 Transparent (screen pixel unchanged)
1 1 Inverted (screen pixel color inverted)

On color frames the XOR step draws from the color bitmap instead of a 1-bit image, so transparency is carried by the AND mask alone.

4- and 8-bit frames are paletted: a color table follows the header, and each pixel is an index into it.

16- and 24-bit frames store their pixels directly, with no color table and no alpha channel, so transparency comes only from the AND mask. Neither is commonly produced by icon authoring tools. Windows loads both and promotes them to 32 bpp; Microsoft additionally lists 24-bit outside the supported color formats, recommending conversion to 0RGB 32-bit beforehand.

32-bit frames store pixels in blue, green, red, alpha order (A8R8G8B8) and use straight (non-premultiplied) alpha — R, G and B are full-intensity values not multiplied by the alpha. When every alpha byte is zero the frame is treated as fully opaque 32-bit color with an unused zero byte (X8R8G8B8; supported since Windows 9x); when any alpha byte is non-zero the frame uses 8-bit per-pixel alpha compositing (supported since Windows XP). The AND mask should still be correct, with its bit set to 1 wherever the alpha is zero. A mask left entirely zero renders correctly under alpha blending but produces wrong results wherever the 1-bit mask is used directly, such as monochrome rendering or compositing drag images and drop-shadow silhouettes.

PNG format

A PNG frame is a complete PNG file embedded verbatim, with no BITMAPINFOHEADER, no doubled height, and no AND mask. Windows recognizes it by the PNG file signature at the start of the image data; any other leading bytes are interpreted as a BITMAPINFOHEADER-prefixed DIB frame. The PNG is stored raw rather than wrapped in a DIB with biCompression = BI_PNG, because icon editors of the era crashed on the unrecognized compression value, whereas a raw signature made those parsers fail early and safely.

The image data is conventionally 32-bit RGBA, the format authoring tools produce. Dimensions and color depth are taken directly from the PNG data, and Windows derives the AND mask automatically from the alpha channel, so none need be supplied.

A PNG frame can be stored at any size, but compression is conventionally applied only to the 256×256 frame; because PNG frames are unreadable on pre-Vista Windows, keeping the smaller frames as uncompressed DIB preserves down-level compatibility.

In executable files

Icons and cursors in Portable Executable (EXE or DLL) files are organized in resources of type RT_GROUP_ICON (14), RT_GROUP_CURSOR (12), RT_ICON (3) and RT_CURSOR (1).

A RT_GROUP_ICON or RT_GROUP_CURSOR resource has the same shape as the ICONDIR directory of an ICO or CUR file — a header giving the image type and count, followed by one fixed-size entry per image — with the entries differing from the file's ICONDIRENTRY in two ways. Each entry's trailing four-byte dwImageOffset is replaced by a two-byte ordinal that indexes the corresponding RT_ICON or RT_CURSOR resource rather than a file offset, so an entry is 14 bytes rather than 16. In the cursor form, the entry stores its width and height as two WORD values and holds no hotspot data; as described below, the hotspot is instead part of the RT_CURSOR resource itself, in contrast to CUR files, where it is held in the directory entry.

These two structures have no single agreed name. Microsoft's current documentation calls the header NEWHEADER and each entry RESDIR; other sources call them GRPICONDIR and GRPICONDIRENTRY; and the original Windows SDK documentation gave the in-executable entry no distinct name at all, reusing the file-format names ICONDIRENTRY and CURSORDIRENTRY.

RT_ICON and RT_CURSOR resources have the same image data format as in ICO files and can store PNG images as well. The first four bytes of an RT_CURSOR resource contain the cursor hotspot as two WORD values (x, y); the resource entry's dwBytesInRes includes these four bytes, unlike in CUR files, where the hotspot lives in the directory entry and is not counted in dwBytesInRes.

The icon a module presents to Windows File Explorer is the alphabetically first named icon group, or, if none are named, the group with the numerically lowest resource identifier.

Icon library

An icon library is a way to package Windows icons; it is typically a 32-bit Portable Executable binary file having an.ICL extension, with icon resources being the packaged icons. Unlike an ordinary EXE or DLL, an ICL file conventionally contains only icon resources, with no cursors or other resource types. As in an ordinary DLL, each icon in the library is identified by a numeric (0–32767) or named resource identifier together with a language code, and this identifier/language-code pair must be unique within the file. An ICL file may also carry an optional, non-standardized block of user-friendly icon names. A legacy 16-bit New Executable variant of the format dates to Windows 3.11 and is no longer generally supported; Windows Vista and later dropped the ability to display icons from such 16-bit libraries (see History).

Image selection

When Windows loads an ICO or CUR file with multiple images, it scores each candidate entry and picks the one with the lowest score. The target size comes from the system metrics (see below) and the target color depth is that of the primary monitor, since no API supplies an explicit depth. The score combines a size component and a color depth component:

{\displaystyle {\text{WidthScore}}=\left|{\text{EntryWidth}}-{\text{TargetWidth}}\right|\times {\begin{cases}2&{\text{EntryWidth}}<{\text{TargetWidth}}\\1&{\text{EntryWidth}}\geq {\text{TargetWidth}}\end{cases}}} {\displaystyle {\text{HeightScore}}=\left|{\text{EntryHeight}}-{\text{TargetHeight}}\right|\times {\begin{cases}2&{\text{EntryHeight}}<{\text{TargetHeight}}\\1&{\text{EntryHeight}}\geq {\text{TargetHeight}}\end{cases}}} {\displaystyle {\text{BppScore}}=\left|{\text{EntryBpp}}-{\text{TargetBpp}}\right|\times 2} {\displaystyle {\text{TotalScore}}={\text{WidthScore}}+{\text{HeightScore}}+{\text{BppScore}}}

Widths, heights and target values are in pixels; bpp is bits per pixel.

Images smaller than the requested size are penalized with a ×2 multiplier. An entry that scores 0 is an exact match on size and color depth. When two entries have the same score, the one with higher color depth wins. A bWidth or bHeight value of 0 in ICONDIRENTRY is interpreted as 256 for scoring purposes. Because these fields are one byte each, they cannot represent sizes above 256, and the size used for scoring is taken from these directory fields rather than from the embedded image.

For icons, a non-zero bColorCount gives the size of the color table, and for image-selection purposes Windows derives the color depth as the number of bits needed to represent that many colors — so 2 colors map to 1 bpp, 16 to 4 bpp, and 256 to 8 bpp — the color counts of real indexed images; if bColorCount is 0, wBitCount is used directly instead. Cursors have no equivalent field to read: in the cursor form of ICONDIRENTRY, bColorCount is unused and wBitCount instead holds the hotspot's vertical coordinate (see above). Through Windows Vista, this meant cursor candidates differing only by color depth could not be distinguished during scoring. From Windows 7 onward, the color depth for cursor scoring is instead read from the cursor's own image data.

Earlier versions of Windows further penalized color compression by doubling the color-depth delta a second time; Windows XP dropped this extra penalty so that a 32-bpp icon can be chosen over an 8-bpp one on a 24-bpp display, which the alpha-blended XP user interface relies on.

Although the scoring algorithm is independent of the order in which images are stored, Windows-shipped files follow a consistent convention: modern single-depth icons and cursors store the largest image first, while legacy files containing multiple color depths tend to group their entries in ascending order of color depth (4-bit, then 8-bit, then 32-bit). Third-party icon editors apply the same ascending-depth ordering. The order matters only when two images tie on both score and color depth: the one stored first is then kept — most likely when no specific size is requested.

Default sizes and DPI scaling

Windows exposes the nominal icon and cursor sizes through the Win32 GetSystemMetrics function. SM_CXICON/SM_CYICON report the default icon size; SM_CXSMICON/SM_CYSMICON report the small icon size. SM_CXCURSOR/SM_CYCURSOR report the nominal cursor size. These values are used as the default target dimensions when loading an image without an explicit size.

On current versions of Windows (Windows 10 and later), higher DPI settings make Windows request larger images. Both icons and cursors are always square. Icon sizes scale linearly with DPI; cursor sizes are rounded to a fixed set of five discrete slots. When no image at the exact target size is available, Windows applies the scoring algorithm above to select the nearest candidate and scales it to the target size.

DPI scaling from Windows 10 onward
DPI range 96–143 144–191 192–287 288–383 ≥ 384
Scale range 100%–149% 150%–199% 200%–299% 300%–399% ≥ 400%
SM_CXICON 32–128 px
SM_CXSMICON 16–64 px
SM_CXCURSOR 32 px 48 px 64 px 96 px 128 px

The SM_CXCURSOR values above assume the default cursor size setting (pointer size = 1 in Windows Settings). The cursor size slider scales all five slots proportionally: at pointer size 2 all values double, at size 3 they triple, and so on. SM_CXICON and SM_CXSMICON are not affected by the cursor size setting.

In 18 languages

Text from Wikipedia, CC BY-SA 4.0 · Source article