OS/2 Bitmap Also Known As: BMP, Presentation Manager Bitmap, PM Bitmap, PM BMP, PM DIB Type Bitmap Colors Mono, 4-bit, 8-bit, 24-bit Compression RLE, Huffman 1D, uncompressed Maximum Image Size 64Kx64K and 4Gx4G pixels Multiple Images Per File Yes Numerical Format Little-endian Originator Microsoft Corporation, IBM Platform Intel machines running OS/2, Microsoft Windows, Windows NT, Windows 95, and MS-DOS Supporting Applications Too numerous to list See Also Microsoft Windows Bitmap Usage Used as the standard bitmap, pointer, and icon storage format in the IBM OS/2 Presentation Manager environment. Comments A well-defined format for programmers having access to the IBM Developer's Toolkit for OS/2 Warp and Presentation Manager Software Development Kit. Its simple RLE compression scheme is rather inefficient for complex, deep-pixel images. Its many variations and differences from the Windows BMP format can be confusing. It is also less widely used than the Windows BMP file format. Vendor specifications are available for this format. Code fragments are available for this format. Sample images are available for this format. The IBM OS/2 Bitmap (BMP) file format is one of several graphics file formats supported by the OS/2 operating system. BMP is the native bitmap format of OS/2 and is used to store several types of bitmap data, including icons and pointers. Most graphics and imaging applications operating under OS/2 support the creation and display of BMP format files. BMP is also found in MS-DOS and Microsoft Windows and originated in that environment. Contents: File Organization File Details For Further Information BMP was originally developed for the Microsoft Windows environment. Microsoft shared responsibility with IBM for the development of early versions of IBM's OS/2 operating system. When Presentation Manager, the OS/2 Graphical User Interface, required a bitmap format, the Windows BMP format was used. Thus, the Windows 2.x and OS/2 1.x BMP formats are identical. The structure of BMP format files is closely tied to the API of both OS/2 and Windows. In this regard, BMP was never meant to be a portable format, or used for bitmap data interchange between different operating systems. As each of these operating system APIs has changed, the BMP format has changed along with them. OS/2 BMP files are much less common than Windows BMP files. This is mostly due to the wider distribution and acceptance of the Microsoft Windows environment over the IBM OS/2 operating system, as well as to the greater number of graphics-using Windows applications. Because OS/2 BMP files are encountered less frequently, many graphics file display programs do not support the reading, writing, and displaying of OS/2 BMP files but do support Microsoft BMP. However, because both of these formats use the same file extension, a non-OS/2-aware file reader will not be able to discern whether it is reading a Windows or an OS/2 BMP file. Reading an OS/2 BMP file as if it were a Windows BMP file will produce unpredictable results from the software application. There are currently two versions of BMP under OS/2 (1.x and 2.x) and six variations; two with the file extension .ICO, two with .PTR, and two using .BMP. This article describes the two versions and their variations used under IBM OS/2. For a discussion of the Microsoft Windows BMP format versions, see the article about the Microsoft Bitmap format. All of the BMP versions originated on Intel-based machines and thus share a common little-endian heritage. The current BMP format is otherwise hardware-independent and can accommodate images with up to 24-bit color. Its basic design makes it a good general purpose format that can be used for color or black-and-white image storage if file size is not a factor. Its main virtues are its simplicity and widespread support in the PC marketplace. The compression method used is a type of run-length encoding (RLE), although most BMP files to date have been stored uncompressed. Although the BMP RLE scheme is lossless and quickly decompressed, it is not considered a superior compression method. The OS/2 BMP format is documented in the appendix of the OS/2 Presentation Manager Programmer's Reference manual and in the online Presentation Manager reference from the OS/2 Warp v3 toolkit. File Organization OS/2 BMP files occur in two major revisions (v1.x and v2.x) and in six different variants: Bitmap, Bitmap Array, Icon, Color Icon, Pointer, and Color Pointer. The typical BMP file contains four sections of data: the file header, the bitmap header, the color palette, and the bitmap data. File Header Bitmap Header Color Palette Bitmap Data As previously mentioned, OS/2 1.x BMP files are identical to Microsoft Windows 2.x BMP files. This fact reflects the common ancestry of the OS/2 operating system and the Microsoft Windows operating environment. The major difference between v1.x and v2.x files is the size of the bitmap header. This header is 14 bytes in length in v1.x BMP files and is 64 bytes in length in v2.x files. File Details All OS/2 BMP files begin with a file header 14 bytes in length with the following format: typedef struct _Os2BmpFileHeader { WORD FileType; /* File type identifier */ DWORD FileSize; /* Size of the file in bytes */ WORD XHotSpot; /* X coordinate of hotspot */ WORD YHotSpot; /* Y coordinate of hotspot */ DWORD BitmapOffset; /* Starting position of image data in bytes */ } OS2BMPFILEHEADER; FileType holds a 2-byte magic value used to identify the file type. This value is 4D42h (or "BM" in ASCII) for a single bitmap, 4142h ("BA") for a bitmap array, 4349h ("IC") for an icon, 4943h ("CI") for a color icon, 5450h ("PT") for a pointer, and 5043h ("CP") for a color pointer. If your application only uses "BM" type BMP files, make sure to always check this field before attempting to use any of the data read from the file. Size is the combined size of the file header plus the bitmap header in bytes. This value is typically zero in many BMP files. XHotSpot and YHotSpot store the coordinates of the central point of the hotspot on the bitmap for icons and pointers. These coordinates are relative to the lower-left corner of the bitmap. If there is no hotspot, then these values will be zero. These values are not used in bitmap and bitmap array BMP files. BitmapOffset is the offset, in bytes, from the beginning of the file to the pixel data that corresponds to this header. BMP Version 1.x (IBM OS/2 1.x) Following the file header in v1.x BMP files is a second header called the bitmap header. This header contains information specific to the bitmap data. This header is 12 bytes in length and has the following format: typedef struct _Os21xBitmapHeader { DWORD Size; /* Size of this header in bytes */ WORD Width; /* Image width in pixels */ WORD Height; /* Image height in pixels */ WORD NumPlanes; /* Number of color planes */ WORD BitsPerPixel; /* Number of bits per pixel */ } OS21XBITMAPHEADER; Size is the size of the header in bytes. For OS/2 1.x BMP files, this value is always 12. Width and Height are the width and height of the image in pixels, respectively. Width does not include any scan-line boundary padding. NumPlanes is the number of color planes used to represent the bitmap data. OS/2 BMP files contain only one color plane, so this value is always 1. The apparent size of a plane in bits is calculated by: Width * Height * BitsPerPixel The actual size of a plane includes scan-line padding. BitsPerPixel is the number of bits per pixel in each plane. This value is in the range 1 to 24; the values 1, 4, 8, and 24 are the only values considered legal by the OS/2 1.x API. Following the header is the color palette data. A color palette is always present in a BMP file if the bitmap data contains 1-, 4-, or 8-bit data. Twenty-four-bit bitmap data never uses a color palette (nor does it ever need to). Each element of the palette is three bytes in length and has the following structure: typedef struct _Os21xPaletteElement { BYTE Blue; /* Blue component */ BYTE Green; /* Green component */ BYTE Red; /* Red component */ } OS21XPALETTEELEMENT; Blue, Green, and Red hold the color component values for a pixel, each in the range 0 to 255. The size of the color palette is calculated from the BitsPerPixel value. The color palette has 2, 16, 256, or 0 entries for a BitsPerPixel of 1, 4, 8, and 24, respectively. The number of color palette entries is calculated as follows: NumberOfEntries = 1 << BitsPerPixel; To detect the presence of a color palette in a BMP file (rather than just assuming that a color palette does exist), you can calculate the number of bytes between the bitmap header and the bitmap data and divide this number by the size of a single palette element. Assuming that your code is compiled using 1-byte structure element alignment, the calculation would be: NumberOfEntries = (BitmapOffset - sizeof(OS2BMPFILEHEADER) - sizeof(OS21XBITMAPHEADER)) / sizeof(OS21XPALETTEELEMENT); If NumberOfEntries is zero, then there is no palette data, otherwise you have the number of elements in the color palette. BMP Version 2.x (IBM OS/2 2.x) Version 2.x BMP files begin with the same 14-byte header as v1.x BMP files. The file header is also followed by a bitmap header, which is an expanded version of the v1.x bitmap header. It is typically 64 bytes in size and contains up to 14 additional fields: typedef struct _Os22xBitmapHeader { DWORD Size; /* Size of this structure in bytes */ DWORD Width; /* Bitmap width in pixels */ DWORD Height; /* Bitmap height in pixel */ WORD NumPlanes; /* Number of bit planes (color depth) */ WORD BitsPerPixel; /* Number of bits per pixel per plane */ /* Fields added for OS/2 2.x follow this line */ DWORD Compression; /* Bitmap compression scheme */ DWORD ImageDataSize; /* Size of bitmap data in bytes */ DWORD XResolution; /* X resolution of display device */ DWORD YResolution; /* Y resolution of display device */ DWORD ColorsUsed; /* Number of color table indices used */ DWORD ColorsImportant; /* Number of important color indices */ WORD Units; /* Type of units used to measure resolution */ WORD Reserved; /* Pad structure to 4-byte boundary */ WORD Recording; /* Recording algorithm */ WORD Rendering; /* Halftoning algorithm used */ DWORD Size1; /* Reserved for halftoning algorithm use */ DWORD Size2; /* Reserved for halftoning algorithm use */ DWORD ColorEncoding; /* Color model used in bitmap */ DWORD Identifier; /* Reserved for application use */ } OS22XBITMAPHEADER; Size is the size of the header in bytes. This header can vary in size, so the reader must be careful only to read the number of bytes indicated by this value. Fields not included in the Size value are not stored in the BMP file, and their values are assumed to be zero. For example, if Size is 16, then only the first five fields (16 bytes) of the header are present. The color palette will begin starting on the 17th byte. If Size is 40, then only the first eleven fields are present. If this value is 64, then the entire header is present in the file. A value larger than 64 indicates a later version of the OS/2 BMP format. Width and Height are the width and height of the image in pixels, respectively. Width does not include any scan-line boundary padding. NumPlanes is the number of color planes used to represent the bitmap data. OS/2 BMP files contain only one color plane, so this value is always 1. The apparent size of a plane in bits is calculated by: Width * Height * BitsPerPixel The actual size of a plane includes scan-line padding. BitsPerPixel is the number of bits per pixel in each plane. This value is in the range 1 to 24; the values 1, 4, 8, and 24 are the only values considered legal by the OS/2 2.x API. Compression indicates the type of encoding method used to compress the bitmap data. 0 indicates that the data is uncompressed; 1 indicates that the 8-bit RLE algorithm was used; 2 indicates that the 4-bit RLE algorithm was used; 3 indicates that the Huffman 1D algorithm was used; and 4 indicates that the 24-bit RLE algorithm was used. (See the section called "Image Data and Compression" below for more information on BMP RLE encoding.) ImageDataSize is the length of the pixel data in bytes, as stored in the file. This value may be zero for uncompressed bitmaps, in which case the bitmap size is calculated from: Width * Height * BitsPerPixel This value may never be zero for uncompressed bitmaps. XResolution and YResolution are the horizontal and vertical resolutions of the bitmap. These values are used to help a BMP reader choose a proper resolution when printing or displaying a BMP file. The units used for the values in these fields are defined in the Units field. ColorsUsed is the number of colors present in the palette. If this value is zero and the value of BitsPerPixel is less than 16, then the number of entries is equal to the maximum size possible for the color map. (BMP files with a BitsPerPixel value of 16 or greater will not have a color palette.) This value is calculated by using the value of the BitsPerPixel field: ColorsUsed = 1 << BitsPerPixel; ColorsImportant is the number of significant colors in the palette, determined by their frequency of appearance in the bitmap data; the more frequent the occurrence of a color, the more important it is. This field is used to provide as accurate a display as possible when using graphics hardware that supports fewer colors than defined in the image. For example, an 8-bit image with 142 colors might only have a dozen or so colors making up the bulk of the image. If these colors could be identified, a display adapter with only 16-color capability would be able to display the image more accurately using the 16 most frequently occurring colors in the image. The most important colors are always stored first in the palette; ColorsImportant is 0 if all of the colors in the palette are to be considered important. Units indicates the type of units used to interpret the values of the XResolution and YResolution fields. The only valid value is 0, indicating pixels per meter. Reserved is unused and is always set to a value of zero. Recording specifies how the bitmap scan lines are stored. The only valid value for this field is 0, indicating that the bitmap is stored from left to right and from the bottom up, with the origin being in the lower-left corner of the display. Rendering specifies the halftoning algorithm used on the bitmap data. A value of 0 indicates that no halftoning algorithm was used; 1 indicates error diffusion halftoning; 2 indicates Processing Algorithm for Noncoded Document Acquisition (PANDA); and 3 indicates super-circle halftoning. Size1 and Size2 are reserved fields used only by the halftoning algorithm. If error diffusion halftoning is used, Size1 is the error damping as a percentage in the range 0 through 100. A value of 100 percent indicates no damping, and a value of 0 percent indicates that any errors are not diffused. Size2 is not used by error diffusion halftoning. If PANDA or super-circle halftoning is specified, Size1 is the X dimension and Size2 is the Y dimension of the pattern used in pixels. ColorEncoding specifies the color model used to describe the bitmap data. The only valid value is 0, indicating the RGB encoding scheme. Identifier is a field reserved for application use and may contain an application-specific value. The color palette that may follow the bitmap header is basically the same as the v1.x palette, but adds an extra byte of padding to increase its size to four bytes. This allows palette entries to be read as 4-byte values, making these values more efficient to read in memory and easier to see in a hex dump or debugger. typedef struct _Os22xPaletteElement { BYTE Blue; /* Blue component */ BYTE Green; /* Green component */ BYTE Red; /* Red component */ BYTE Reserved; /* Padding (always 0) */ } OS22XPALETTEELEMENT; Blue, Green, and Red hold the color component values for a pixel, each in the range 0 to 255. Reserved pads the structure to end on an even-byte boundary and is always zero. When identifying BMP files you must make sure that the first two bytes of the file are 4Dh 42h and only read the number of bytes from the bitmap header as indicated by the Size field. This value will be 12 for OS/2 1.x BMP files and less than or equal to 64 for OS/2 2.x BMP files. The file header is identical for both versions; the only difference in the bitmap header is that the Width and Height fields are WORDs in v1.x files and DWORDs in v2.x files. Color Palette As we have seen, a BMP color palette is an array of structures that specify the red, green, and blue intensity values of each color in a display device's color palette. Each pixel in the bitmap data stores a single value used as an index into the color palette. The color information stored in the element at that index specifies the color of that pixel. One-, 4-, and 8-bit BMP files are expected to always contain a color palette. Twenty-four-bit BMP files never contain color palettes. You must be sure to check the Size field of the bitmap header to know if you are reading 3-byte or 4-byte color palette elements. A Size value of 12 indicates an OS/2 1.x (or possibly a Windows 2.x) BMP file with 3-byte elements. Larger numbers, such as 64, indicate later versions of BMP, which all use 4-byte color palette elements. OS/2 BMP File Types Each new version of BMP has added new information to the bitmap header. In some cases, the newer versions have changed the size of the color palette and added features to the format itself. Unfortunately, a field wasn't included in the header to easily indicate the version of the file's format or the type of operating system that created the BMP file. If we add Windows' four versions of BMP to OS/2's two versions--each with four possible variations--we find that as many as twelve different related file formats all have the file extension ".BMP". It is clear that you cannot know the internal format of a BMP file based on the file extension alone. But fortunately, you can use a short algorithm to determine the internal format of BMP files. The FileType field of the file header is where we start. If these two byte values are 424Dh ("BM"), then you have a single-image BMP file that may have been created under Windows or OS/2. If FileType is the value 4142h ("BA"), 4349h ("IC"), 4943h ("CI"), 5450h ("PT"), or 5043h ("CP"), you have an OS/2 variation of the BMP format, the internals of which we discuss below. If your file type is "BM", then you must now read the Size field of the bitmap header to determine the version of the file. Size is 12 for Windows 2.x BMP and OS/2 1.x BMP, 40 for Windows 3.x and Windows NT BMP, 12 to 64 for OS/2 2.x BMP, and 108 for Windows 4.x BMP. A Windows NT BMP file will always have a Compression value of 3; otherwise, it is read as a Windows 3.x BMP file. Note that the only difference between Windows 2.x BMP and OS/2 1.x BMP is the data type of the Width and Height fields. For Windows 2.x they are signed shorts and for OS/2 1.x they are unsigned shorts. Windows 3.x, Windows NT, and OS/2 2.x BMP files only vary in the number of fields in the bitmap header and in the interpretation of the Compression field. In addition to standard bitmaps, an OS/2 file supports the storage of icon, color icon, pointer (also called a cursor), color pointer, and bitmap array data. As we have noted, each of these BMP file types have a different image FileType value as follows: Bitmap Array 4142h `BA' Bitmap 4D42h `BM' Color Icon 4943h `CI' Color Pointer 5043h `CP' Icon 4349h `IC' Pointer 5450h `PT' The icon, pointer, color icon, and color pointer BMP files have the same file and bitmap headers as bitmap BMP files, but differ in how the headers and bitmap data are arranged. Icon and pointer BMP files store only 1-bit monochrome data and do not use color palette data, although a color palette may be present in the file. The bitmap data is normally uncompressed and stores two bitmap masks used to display the icon or pointer image. The top half of the bitmap is the AND mask and the bottom half is the XOR mask (remember that the bitmap is stored from the bottom-up). The icon or pointer is displayed by first ANDing the top half of the bitmap with the pixels on the display and then XORing the bottom half of the bitmap with the same pixels. The four possible values produced from this masking will result in the background, foreground, transparent, and inverse values defined for the monochrome display. Also note that because the two masks each occupy one-half of the total size of the bitmap, the icon or pointer displayed will be one-half the height specified in the Height field of the file header. Display AND OR Resulting Pixel Mask Bit Mask Bit Value X 0 0 0 (background) X 0 1 1 (foreground) X 1 0 X (transparent) X 1 1 ~X (inverse) Color icon and color pointer BMP files are basically the same as icon and pointer files but have an additional color bitmap added. The headers and color table for the monochrome bitmap are immediately followed by the headers and color palette for the color bitmap. The monochrome bitmap data and color bitmap data then follow, as shown in Figure OS/2 Bitmap-1. Also note that this is the most common arrangement of these sections. The bitmap data can actually appear in any order as long the BitmapOffset field in the file headers point to the proper bitmap data. And the FileType field in other OS2BMPFILEHEADER sections will have the same value (either `CI' or `CP'). The NumPlanes and BitsPerPixel fields of the OS22XBITMAPHEADER header will indicate which is the monochrome and the color bitmap. For compatibility with existing software, the monochrome image data should always be written to the BMP file first. Figure OS/2 Bitmap-1: Monochrome/color data format [Graphic: Figure OS/2 Bitmap-1] Color icons and color pointers are displayed using the same process as their monochrome counterparts, with the color pixel values used to set the color of the icon or pointer pixels on the display. Color icon and color pointers are typically based on the v2.x OS/2 BMP format, as the OS/2 32-bit icon editor only generates these file types, even when monochrome images are stored in them. Display AND OR Color Resulting Pixel Mask Bit Mask Bit Pixel Value X 0 0 C C (color) X 0 1 C C (color) X 1 0 C X (transparent) X 1 1 C ~X (inverse) The bitmap array flavor of BMP allows the storage of one or more bitmaps within a single BMP file. Bitmap array files are typically used to hold multiple resolution bitmaps of the same image. This BMP variation is similar in concept and use to the Multiple Resolution Bitmap (.MRB) files found in the Microsoft Windows environment. When multiple images are stored in a single OS/2 BMP file, it is assumed that each image has different metrics (dimensions, color depth, resolution) and that all the images are different renderings of the same object. Bitmap array files start with a series of headers and color palettes. There is one set of headers for each bitmap stored in the file. The first header is a variation of the BMP file header, called a bitmap array header. This header is 14 bytes in size and has the following format: typedef struct _Os2BmpArrayHeader { WORD Type; /* Header type, always 4142h ("BA") */ DWORD Size; /* Size of this header */ DWORD OffsetToNext; /* Offset to next OS2BMPARRAYFILEHEADER */ WORD ScreenWidth; /* Width of the image display in pixels */ WORD ScreenHeight; /* Height of the image display in pixels */ } OS2BMPARRAYHEADER; Type holds the 2-byte value 4142h, or `BA' in ASCII. This value identifies the start of all bitmap array headers. File readers should not attempt to read `BA' files as if they are single-bitmap (`BM') BMP files. Size is the size of this bitmap array header and the headers that follow it. This value really has no practical use and is often set to zero. It is included in this header mainly for compatibility with other BMP headers starting with both Type and Size fields. OffsetToNext contains the byte offset of the next OS2BMPARRAY-FILEHEADER structure in the file. This offset is calculated from the starting byte of the file. A value of zero indicates that this header is for the last image in the array list. ScreenWidth and ScreenHeight indicate the resolution of the image in pixels. These values are used in conjunction with the Width, Height, NumPlanes, and BitsPerPixel values of the bitmap header to determine which bitmap in the file to display. The headers that follow the bitmap array file header and the color palette data are the same used by the standard OS/2 BMP file format. Each image stored in the array bitmap file will have a complete set of these headers, as shown in Figure OS/2 Bitmap-2, and be linked together by the OffsetToNext value in the bitmap array header. Figure OS/2 Bitmap-2: Multi-image data format [Graphic: Figure OS/2 Bitmap-2] A display program should look through the list of OS2BMPARRAYHEADER structures in a bitmap array file and choose the image that most closely fits the resolution and metrics of the display device. If a proper image is not available, the first image in the list is displayed by default. Device-independent images should therefore always be placed first in any bitmap array list. The value of the Size field of the bitmap header will indicate if this is an OS/2 1.x or 2.x bitmap array file. OS/2 attempts to find an exact match of the requested size (image dimensions). For icons and pointers, if a bitmap of the requested size cannot be found, a device-independent icon or pointer bitmap is used. If the requested size cannot be found for standard bitmaps, a bitmap whose display size matches the output device's size is used, and a device-independent bitmap is used if neither is available. If multiple bitmaps match the requested size (or if there are multiple matches for the screen size or if there are multiple device-independent images, etc.), then the image whose color depth most closely matches the output device's color depth is used. The icon/pointer size that is requested depends on the display driver. The following versions are most commonly used: 40x40 4bpp 16 color 32x32 4bpp 16 color 32x32 1bpp monochrome 20x20 1bpp monochrome 16x16 1bpp monochrome The size 40x40 is used for 8514/a, XGA, and other displays with a resolution of 1024x768 or higher. The size 32x32 is used for VGA, EGA, and most other devices of resolution less than 1024x768. The sizes 20x20 and 16x16 are half-size variants of the 40x40 and 32x32 images. They are intended for small-icon views and use in window title bars. If you ever encounter a user with a CGA (640x200) display, the icon size is 32x16 1bpp (monochrome). Image Data and Compression Uncompressed data is a series of values representing either color palette indices or actual RGB color values. Pixels are packed into bytes and arranged as scan lines. Each scan line must end on a 4-byte boundary, so one, two, or three bytes of padding may follow each scan line. Scan lines are always stored from the bottom up in OS/2 BMP files with the origin in the lower-left corner of the display. Monochrome bitmaps contain one bit per pixel, eight pixels per byte (with the most significant bit being the leftmost pixel), and have a 2-element color palette. If a BMP reader chooses to ignore the color palette, all "one" bits are set to the display's foreground color and all "zero" bits are set to the background color. Four-bit pixels are packed two per byte with the most significant nibble being the leftmost pixel. Eight-bit pixels are stored one per byte. Both 4- and 8-bit pixel values are indices into color palettes 16 and 256 elements in size respectively. The OS/2 BMP format supports a simple run-length encoded (RLE) compression scheme for compressing 4-, 8-, and 24-bit bitmap data. One-bit monochrome data may be compressed using the Huffman 1D algorithm common to facsimile transmission applications. (For a discussion of the Huffman 1D algorithm, see Chapter 9, Data Compression.) BMP uses a two-value RLE scheme. The first value contains a count of the number of pixels in the run, and the second value contains the value of the pixel. Runs of up to 255 identical pixel values may be encoded as only two bytes of data. Actually, it's a bit more complex than this. In addition to encoded runs, there are unencoded runs, delta markers, end-of-scan-line markers, and an end-of-RLE data marker. The 8-bit RLE algorithm (RLE8) stores repeating pixel values as encoded runs. The first byte of an encoded run will be in the range of 1 to 255. The second byte is the value of the 8-bit pixels in the run. For example, an encoded run of 05 18 would decode into five pixels, each with the value 18, or 18 18 18 18 18. When a scan line does not contain enough pixel runs to achieve a significant amount of compression, contiguous pixel values may be stored as literal or unencoded runs. An unencoded run may contain from 3 to 255 pixel values. The first byte of an unencoded run is always zero. This makes it possible to tell the difference between the start of an encoded and the start of an unencoded run. The second byte value is the number of unencoded pixel values that follow. If the number of pixels is odd, then a 00 padding value also follows. This padding value is not part of the original pixel data and should not be written to the decoded data stream. Here are some examples of encoded and unencoded data streams: Encoded Bytes Decoded Bytes 05 10 10 10 10 10 10 00 05 23 65 34 56 45 00 23 65 34 56 45 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 00 04 46 57 68 79 46 57 68 79 Three marker values may also be found in the RLE data. Each of these markers also begins with a zero-byte value. The second byte value indicates the type of marker. These markers specify positional information relating to the decoded bitmap data and do not generate any data themselves. The first marker is the end-of-scan-line marker and is identified by two byte values 00 and 00. This marker is an indication that the end of data for the current scan line has been reached. Encoded data occurring after this marker is decoded starting at the beginning of the next scan line. If an end-of-scan-line marker is not present in the encoded data, then the pixels will automatically wrap from the end of one scan line to the start of the next. This marker is only used when you want to force the decoding of a scan line to end at a particular place. If the end-of-line marker occurs in the middle of a scan line, all remaining pixels in the decoded bitmap for the line are ignored. This "short scan line" technique is used to omit unneeded portions of scan lines. Most often, it is found in icon and pointer BMP files. The next marker is the end of RLE data marker. It is identified by the two byte values 00 and 01. This marker occurs only as the last two bytes of the RLE data. This marker is an indication that the reader should stop decoding data. The last marker is the run offset marker, also called a delta or vector code. This marker is four bytes in size, with the first two bytes being the values 00 and 02, and the last two values specifying a pixel address using unsigned X and Y values as an offset from the current bitmap cursor position. The X value is the number of pixels across the scan line, and the Y value is the number of rows forward in the bitmap. This run offset marker indicates the location in the bitmap where the next decoded run of pixels should be written. For example, a run offset marker value of 00 02 05 03 would indicate that the offset of the bitmap cursor should move five pixels down the scan line, three rows forward, and write out the next run. The cursor then continues writing decoded data from its new position moving forwards. Run offset markers are used when a bitmap may contain a large amount of "don't care" pixels. For example, if the BMP file holds a bitmap used as a mask (such as used with icons and pointers), many of the pixels in the rectangular bitmap may not be used. Rather than store these unused pixels in the BMP file, only the significant pixels are stored, and the delta markers are used as "jumps" to skip over the parts of the bitmap not actually used in the mask. Here is another example. In color icon and color pointer BMP files, it is unnecessary to store color values for pixels whose AND mask value is 1, since the screen color will be determined by the XOR mask for those pixels and not by the color value. In this case, delta markers and end-of-scan-line markers would be used to skip over and ignore pixels not used in the image and therefore not stored in the bitmap. The following are the BMP RLE markers: 00 00 End of scan line 00 01 End of bitmap data 00 02 XX YY Run offset marker Here is an example of decoding an 8-bit data stream. Each of the values is an 8-bit index value into the color palette, not an actual color value. Encoded Bytes Decoding Description Decoded Bytes 04 16 Four bytes of value 16 16 16 16 16 08 45 Eight bytes of value 45 45 45 45 45 45 45 45 45 00 00 End of scan line None 00 02 04 02 Move to offset four pixels forward and two rows up None 03 E4 Three bytes of value E4 E4 E4 E4 00 03 12 A4 46 00 Three bytes of unencoded data 12 A4 46 00 00 End of scan line None 00 01 End of RLE data None The 4-bit RLE algorithm (RLE4) stores repeating pixel values in a very similar manner to RLE8. All of the markers are the same. The only real difference is that two pixel values are packed per byte, and these pixel values alternate when decoded. For example, an RLE4-encoded data stream of 07 48 would decode to seven pixels, alternating in value as 04 08 04 08 04 08 04. If this looks bizarre, it's because you rarely see alternating runs of pixel values in bitmaps eight bits or greater in depth. Four-bit (16-color) bitmaps, however, usually contain a lot of dithering. Most dithering algorithms will yield relatively large runs of alternating pixels. Runs of repeating sequences of three and four pixels are also fairly common output from many dithering algorithms. But the ability for efficiently encoding these types of pixel runs is not currently supported in the BMP RLE scheme. Runs of identical pixel values may be encoded by RLE4 as well. For example, a run of twelve pixels, all of the value 9, would be RLE4-encoded as 0C 99 and would decode to the run 09 09 09 09 09 09 09 09 09 09 09 09. Padding is added to unencoded pixel runs that are an odd number of bytes, rather than pixels, in length. And an unused final nibble in odd-length runs is set to zero. For example, the six pixel values 1 3 5 7 9 0 would be stored as the unencoded run 00 06 13 57 90 00, while the five pixel values 1 3 5 7 9 would be stored as the unencoded run 00 05 13 57 90 00. Following is an example of decoding a 4-bit data stream. Each of the values is a 4-bit index value into the color palette, not an actual color value. Encoded Bytes Decoding Description Decoded Bytes 04 16 Four values alternating 1 and 6 1 6 1 6 08 44 Eight values alternating 4 and 4 4 4 4 4 4 4 4 4 00 00 End of scan line None 00 02 04 02 Move to offset four pixels forward and two rows up None 03 E4 Three values alternating E and 4 E 4 E 00 06 12 A4 46 00 Six values of unencoded data 1 2 A 4 4 6 00 00 End of scan line None 00 01 End of RLE data None And, as you probably guessed, the 24-bit RLE algorithm (RLE24) encodes pixel values using nearly the same algorithm as RLE4 and RLE8. The only difference is that run values encoded are three bytes in size (one byte per RGB color component), rather than four or eight bits in size. Here is an example of decoding a 24-bit data stream. Each of the values is an actual color value found in the bitmap data. Run length values must be a multiple of three, and odd-length encoded runs are padded with a final zero byte, which is not part of the decoded data. Encoded Bytes Decoding Description Decoded Bytes 04 16 D4 6F Four pixels of value 16, D4, 6F 16 D4 6F 16 D4 6F 16 D4 6F 16 D4 6F 02 00 00 00 Two pixels of value 0,0,0 00 00 00 00 00 00 00 00 End of scan line None 00 02 09 0C Move to offset nine pixels forward and twelve rows up None 03 E4 E4 E4 Three pixels of value E4,E4,E4 E4 E4 E4 E4 E4 E4 E4 E4 E4 00 01 12 A4 46 00 One pixel of unencoded data 12 A4 46 00 00 End of scan line None 00 01 End of RLE data None Here is a summary of OS/2 BMP data characteristics: Pixel Depth Pixel Size Compression Color Palette 1 bit 1 bit 0,3 Yes 4 bits 4 bits 0,2 Yes 8 bits 1 byte 0,1 Yes 24 bits 3 bytes 0,4 No For Further Information The OS/2 BMP file format is maintained by IBM. Version 1.x of the OS/2 BMP format is documented in the Presentation Manager Software Development Kit (SDK). Later versions of OS/2 BMP are found in the IBM Developer's Toolkit for OS/2 Warp, version 3: OS/2 V3 Technical Library: Presentation Manager Programming Reference (IBM part number G25H-7105). and in the online Presentation Manager reference. For further information, contact: IBM Corporation Attn: Independent Vendor League Mail Stop 147 150 Kettletown Road Southbury CT 06488 Voice: 203-266-2000 WWW: http://www.ibm.com/ IBM documentation can be ordered from: USA: 1-800-426-7282 Canada: 1-800-465-1234 Hours: 8am to 8pm EST, Monday through Friday Information about the OS/2 BMP format can also be found in the following references: Charlap, David, "The BMP File Format: Part I," Dr. Dobb's Journal, vol. 20, no. 228, March 1995. Charlap, David, "The BMP File Format: Part II," Dr. Dobb's Journal, vol. 20, no. 229, April 1995. IBM Corporation, OS/2 2.0 Programmer's Toolkit: Presentation Manager Reference (online manual). Luse, Marv, "The BMP File Format," Dr. Dobb's Journal, vol. 9, no. 219, September 1994, pp. 18-22. Petzold, Charles, "Preserving a Device-Independent Bitmap: The Packed-DIB Format," PC Magazine, July 1991, pp. 433-439. Petzold, Charles, "What's New in Bitmap Formats: A Look at Windows and OS/2," PC Magazine, 11 September 1990, pp. 403-410. The code for the above issues of Dr. Dobb's Journal are available at: ftp://ftp.mv.com/pub/ddj/1994/1194.09/bmp.zip ftp://ftp.mv.com/pub/ddj/1995/1195.03/bmp.zip The two Dr. Dobb's Journal articles by David Charlap contain a complete collection of source code for working with Windows 2.x, 3.x, NT, and OS/2 BMP file formats. It is available at the above FTP site and on CD-ROM. You might also be able to find some helpful information at the OS/2 shareware BBS: Voice: 703-385-0201 BBS: 703-385-4325 WWW: http://www.os2bbs.com/ Telnet: bbs.os2bbs.com Or at IBM's OS/2 homepage: WWW: http://www.austin.ibm.com/pspinfo/os2.html Also, look at these other online resources: http://axion.physics.ubc.ca/os2/os2.html OS/2 Resource listing ftp://ftp-os2.cdrom.com/ OS/2 Archive at Walnut Creek CD-ROM Copyright ¸ 1996, 1994 O'Reilly & Associates, Inc. All Rights Reserved.