PCX headers come in blocks of 128 (though only slightly over half is used). ZSoft .PCX FILE HEADER FORMAT Byte Item Size Description/Comments 0 Manufacturer 1 Constant Flag 10 = ZSoft .PCX 1 Version 1 Version information: 0 = Version 2.5 2 = Version 2.8 w/palette information 3 = Version 2.8 w/o palette information 5 = Version 3.0 2 Encoding 1 1 = .PCX run length encoding 3 Bits per pixel 1 Number of bits/pixel per plane 4 Window 8 Picture Dimensions (Xmin, Ymin) - (Xmax - Ymax) in pixels, inclusive 12 HRes 2 Horizontal Resolution of creating device 14 VRes 2 Vertical Resolution of creating device 16 Colormap 48 Color palette setting 64 Reserved 1 65 NPlanes 1 Number of color planes 66 Bytes per Line 2 Number of bytes per scan line per color plane (always even for .PCX files) 68 Palette Info 2 How to interpret palette - 1 = color/BW, 2 = grayscale 70 Filler 58 blank to fill out 128 byte header ~ Let's look at a header: 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 AA AA 00 AA 00 AA 00 AA AA FF 55 55 55 3 FF 55 AA AA AA 00 00 AA 55 55 FF 55 55 55 00 AA 4 00 AA 00 00 55 FF FF FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 In line 1 the first byte (0A) is the ZSoft "signature". The next byte, 05, represents the version of the file. You're only likely to encounter 2 values for this, 02 for monochrome images and 05 for 16 and 256 color images. The next byte, 01, is a constant, useful mostly for verification that the file is indeed a PCX file. The fourth byte is 01, which indicates 1 color bit per pixel. If this were a 256 color file this value would be 08. The next 8 bytes 00 00 00 00 7F 02 5D 01 tell us the picture dimensions. 7F 02 values to 639 (127 + {256 * 2}) and 5D 01 values to 349 (93 + {256 * 1}) so we have a standard 640 x 350 EGA image expected to be 16 colors. The remainder of the line is pretty much useless. It simply tells us the resolution of the hardware the image was created on. The next 3 lines 2 00 00 00 AA AA 00 AA 00 AA 00 AA AA FF 55 55 55 3 FF 55 AA AA AA 00 00 AA 55 55 FF 55 55 55 00 AA 4 00 AA 00 00 55 FF FF FF 55 FF FF FF 55 FF FF FF contain the color palette setting, detailed below: Palette Information Description EGA/VGA 16 Color Palette Information The palette information is stored in one of two different formats. In standard RGB format (IBM EGA, IBM VGA) the data is stored as 16 triples. Each triple is a 3 byte quantity of Red, Green, Blue values. The values can range from 0-255 so some interpretation into the base card format is necessary. On an IBM EGA, for example, there are 4 possible levels of RGB for each color. Since 256/4 = 64, the following is a list of the settings and levels: Setting Level 0-63 0 64-127 1 128-192 2 193-254 3 VGA 256 Color Palette Information ZSoft has recently added the capability to store palettes containing more than 16 colors in the .PCX image file. The 256 color palette is formatted and treated the same as the 16 color palette, except that it is substantially longer. The palette (number of colors x 3 bytes in length) is appended to the end of the .PCX file, and is preceded by a 12 decimal. To determine the VGA BIOS palette you need only divide the values read in the palette by 4. To access a 256 color palette: First, check the version number in the header, if it contains a 5 there is a palette. Second, read to the end of the file and count back 769 bytes. The value you find should be a 12 decimal, showing the presence of a 256 color palette. CGA Color Palette Information For a standard IBM CGA board, the palette settings are a bit more complex. Only the first byte of the triple is used. The first triple has a valid first byte which represents the background color. To find the background, take the (unsigned) byte value and divide by 16. This will give a result between 0-15, hence the background color. The second triple has a valid first byte, which represents the foreground palette. PC Paintbrush supports 8 possible CGA palettes, so when the foreground setting is encoded between 0 and 255, there are 8 ranges of numbers and the divisor is 32. CGA color map Header Byte #16 Background color is determined in the upper four bits. Header Byte #19 Only upper 3 bits are used, lower 5 bits are ignored. The first three bits that are used are ordered C, P, I. These bits are interpreted as follows: c: color burst enable - 0 = color; 1 = monochrome p: palette - 0 = yellow; 1 = white i: intensity - 0 = dim; 1 = bright The next line 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 decodes this way. The first byte 00 is not used, declared "reserved". The next byte 04 is the number of color planes. This means the data will be encoded in a set of 4. For a 256 color file, this would be 01. The next 2 bytes 50 00 tend to be redundant, having to do with the width of the screen and the encoding scheme between 1 bit per pixel and 8 bits per pixel. This values to 80, which tells us the 640 wide screen will be encoded in 8 pixel segments (8 x 80 = 640). If it were a value of 40 01, that would confirm an image width of 320 (64 + 256) and confirm that it is an 8 bit per pixel image where the pixels would be encoded in a single byte rather than grouped in 8's. A value of 80 02 would be a 640 (128 + 512) wide screen of 8 bit pixels (256 color). The final two bytes are frequently set to 00 00 and ignored. They can be used to determine if a file is to be grey-scale. Decoding .PCX Files First, find the pixel dimensions of the image by calculating [XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1]. Then calculate how many bytes are required to hold one complete uncompressed scan line: TotalBytes = NPlanes * BytesPerLine Note that since there are always an integral number of bytes, there will probably be unused data at the end of each scan line. TotalBytes shows how much storage must be available to decode each scan line, including any blank area on the right side of the image. You can now begin decoding the first scan line - read the first byte of data from the file. If the top two bits are set, the remaining six bits in the byte show how many times to duplicate the next byte in the file. If the top two bits are not set, the first byte is the data itself, with a count of one. Continue decoding the rest of the line. Keep a running subtotal of how many bytes are moved and duplicated into the output buffer. When the subtotal equals TotalBytes, the scan line is complete. There will always be a decoding break at the end of each scan line. But there will not be a decoding break at the end of each plane within each scan line. When the scan line is completed, there may be extra blank data at the end of each plane within the scan line. Use the XSIZE and YSIZE values to find where the valid image data is. If the data is multi-plane BytesPerLine shows where each plane ends within the scan line. Continue decoding the remainder of the scan lines. There may be extra scan lines at the bottom of the image, to round to 8 or 16 scan lines. First let's point out that the lines are encoded horizontally, one line at a time. Now let's look at 2 points. First the "color encoding" scheme of 1 to 4 patterns and second the nature of the 8 pixel codings and repeat calculations. Now let's take some "real world" examples, of increasing complexity, and how to "read" them. 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 D9 FF 80 F6 00 D9 FF 80 F6 00 D9 FF 80 F6 00 D9 10 FF 80 F6 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 11 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 12 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 13 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 14 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 15 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 16 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 Look at line 9 above. The first byte, D9, is interpreted this way. D9 is 217 in decimal. Subtract 192 and we get a value of 25. This means we're going to deal with 25 blocks of 8 pixels (there are a total of 80 blocks for a 640 width screen, that is 80 blocks of 8 pixels). The pixel pattern is encoded in the second byte, FF. This means all 8 pixels on (a solid line). If the value was 03 that would mean only the right two pixels were on for a 6 off, 2 on pattern. This means we turn on the leftmost 200 pixels. This leaves us 55 blocks to decode. The next block is a single block, because the value is less than 192 (&H80). Since only the left bit is on (128 or &H80) only 1 pixel is on. This gives us a total of 201 pixels on (and 7 off) so we've decoded 208 total with 432 (or 54 blocks) to go. F6 is 246. Subtract 192 and you get 54. This completes the 54 blocks. The next byte, 00 means all pixels off. This gives us a total pattern of 201 pixels on and 439 off (7 + {54 times 8}). Now we note that the 4 patterns (D9 FF 80 F6 00) which encode color are equal. This values to 1 + 2 + 4 + 8, or COLOR 15 for the pixels on. Now consider the image below: 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 FF 00 D1 00 D9 FF 80 F6 00 D9 FF 80 F6 00 D9 FF 10 80 F6 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 11 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 12 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 13 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 14 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 15 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 16 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF Look at this pattern: 9 FF 00 D1 00 D9 FF 80 F6 00 D9 FF 80 F6 00 D9 FF 10 80 F6 00 The first pattern (FF 00 D1 00) is a "blank" (63 blocks of no pixels on + 17 blocks of no pixels on) but 2, 3 and 4 have the pattern. This means the color value is 2 + 4 + 8 or COLOR 14. The two following images are COLOR 2 and COLOR 1 respectively. 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 FF 00 D1 00 D9 FF 80 F6 00 FF 00 D1 00 FF 00 D1 10 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 11 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 12 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 13 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 14 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 15 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 16 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 D9 FF 80 F6 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 10 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 11 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 12 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 13 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 14 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 15 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 16 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 It's somewhat wierd to note that files which have the same pixels set, but which have different colors have different sizes. In general a file of the same pixels set, but with lower COLOR values, will be smaller. Now let's move on to a more sophisticated image. 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 C1 F8 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 C1 F8 10 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 FF 00 D1 00 11 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 12 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 13 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 14 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 15 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 16 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 Let's look at lines 9 C1 F8 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 C1 F8 10 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 The first pattern interprets like this: C1 is one block of pixels with pattern F8 (the left 5 pixels on). FF is 63 blocks of pixels with pattern 00 (no pixels on). D0 is 16 blocks of pixels with pattern 00 (no pixels on). This completes 80 blocks for color value 1. Let's strip off this and continue: 9 C1 F8 D7 00 C1 FF F7 00 C1 F8 10 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 C1 is one block of pixels with pattern F8 (the left 5 pixels on). D7 is 23 blocks of pixels with pattern 00 (no pixels on). C1 is one block of pixels with pattern FF (all 8 pixels on). F7 is 55 blocks of pixels with pattern 00 (no pixels on). This completes 80 blocks for color value 2. Let's strip off this and continue: 9 C1 F8 10 FF 00 D0 00 C1 F8 D7 00 C1 FF F7 00 C1 is one block of pixels with pattern F8 (the left 5 pixels on). FF is 63 blocks of pixels with pattern 00 (no pixels on). D0 is 16 blocks of pixels with pattern 00 (no pixels on). This completes 80 blocks for color value 4. Let's strip off this and continue: 10 C1 F8 D7 00 C1 FF F7 00 C1 is one block of pixels with pattern F8 (the left 5 pixels on). D7 is 23 blocks of pixels with pattern 00 (no pixels on). C1 is one block of pixels with pattern FF (all 8 pixels on). F7 is 55 blocks of pixels with pattern 00 (no pixels on). This completes 80 blocks for color value 8. Now let's see what this did: The left 5 pixels (X locations 0 to 4) were on for all 4 color values. This means they are COLOR 15 {1 + 2 + 4 + 8} (bright white). The 8 pixels (X locations 192 to 199) were on for color values 2 and 8. This means their color is 10 {2 + 8} (bright green). Now let's decode line where the first 16 pixels vary from COLOR 0 to 15 in sequence: 1 0A 05 01 01 00 00 00 00 7F 02 5D 01 80 02 5E 01 2 00 00 00 00 00 AA 00 AA 00 00 AA AA AA 00 00 AA 3 00 AA AA 55 00 AA AA AA 55 55 55 55 55 FF 55 FF 4 55 55 FF FF FF 55 55 FF 55 FF FF FF 55 FF FF FF 5 00 04 50 00 00 00 00 00 00 00 00 00 00 00 00 00 6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 C2 55 FF 00 CF 00 C2 33 FF 00 CF 00 C2 0F FF 00 10 CF 00 00 C1 FF FF 00 CF 00 FF 00 D1 00 FF 00 D1 11 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 12 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 13 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 14 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 15 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 16 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 00 FF 00 D1 The data is in line 9 and part of 10 9 C2 55 FF 00 CF 00 C2 33 FF 00 CF 00 C2 0F FF 00 10 CF 00 00 C1 FF FF 00 CF 00 C2 55 FF 00 CF 00 decodes as 2 blocks of COLOR bit 1 with pattern 55 (0101010101010101) followed by 63 and 15 blocks of nulls. C2 33 FF 00 CF 00 decodes as 2 blocks of COLOR bit 2 with pattern 33 (0011001100110011) followed by 63 and 15 blocks of nulls. C2 0F FF 00 CF 00 decodes as 2 blocks of COLOR bit 3 with pattern 0F (0000111100001111) followed by 63 and 15 blocks of nulls. 00 C1 FF FF 00 CF 00 decodes as 1 nul block and 1 block of COLOR bit 4 with pattern FF (0000000011111111) followed by 63 and 15 blocks of nulls. These sum up to: (0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1) x 1 (0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1) x 2 (0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1) x 4 (0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1) x 8 ------------------------------------------------ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15