Daggerfall:Image formats
The UESPWiki – Your source for The Elder Scrolls since 1995
Contents |
[edit] IMG file format
by Dave Humphrey
The format of the IMG files found in Daggerfall's ARENA2 directory are quite simple to determine. The basic format, as follows, is 12 bytes of header information followed by the image data. The format completely describes the 259 IMG files found in the game.
[Bytes 0-1] short XOffset
[Bytes 2-3] short YOffset;
Unknown what exactly these two values are, but probably
the image offsets for displaying purposes.
[Bytes 4-5] short Width;
[Bytes 6-7] short Height;
[Bytes 8-9] short Unknown;
Might indicate compressed data or not.
0x0000 = Uncompressed image data???
0x0002 = Compressed image data???
[Bytes 10-11] short ImageSize;
Total number of bytes taken up by the image data. Note that
this is the size of the image data in the file, which may be
compressed (or, sometimes ImageSize is not Width*Height).
[Bytes 12...] unsigned char ImageData[ImageSize];
A linear bitmap form (one pixel right after another).
You will still need the correct palette to properly display
the image (there are several in the ARENA2 directory).
[edit] Special IMG files
- FMAP0I00.IMG, FMAP0I01.IMG, FMAP0I16.IMG
- These 12 byte files contain nothing but a NULL header (0x00's).
- 720 Byte Files
- 9x80 image with no header.
- 990 Byte Files
- 45x22 image with no header.
- 1720 Byte Files
- 43x40 image with no header.
- 2140 Byte Files
- 107x20 image with no header.
- 2916 Byte Files
- 36x81 image with no header.
- 3200 Byte Files
- 40x80 image with no header.
- 3938 Byte Files
- 179x22 image with no header.
- 4280 Byte Files
- 107x40 image with no header.
- 4508 Byte Files
- 322x14 image with no header.
- 20480 Byte Files
- 320x64 image with no header.
- 26496 Byte Files
- 184x144 image with no header.
- 64000 Byte Files
- 320x200 image with no header.
- 64768 Byte Files
- 320x200 image with no header and 768 bytes of palette data at the end of the file (256 RGB entries, 0-63 values).
- 68800 Byte Files
- 320x215 image with no header.
- 112128 Byte Files
- 512x219 image with no header.
[edit] CIF file format
CIF files initially look just like the IMG files, except a closer examination reveals that they are much larger than they needed to be. This lead to the finding that most CIF files simply contain several IMG files, one after the other, illustrated as follows:
Image #1 Header
Image #1 Data
Image #2 Header
Image #2 Data
...etc...
The only apparent method determining how many images a CIF file contains is to read all the images (or at least all the image headers, skipping the image data). Once no (or few) bytes are left after an image, the file is complete. The number of images in a CIF file may be fixed as is evident with playing around with the FACE*.CIF files (adding another face after the default 10 has no effect in the game). Using the format detailed below, all CIF files in the ARENA2 directory can be successfully exported to PCX files.
[edit] Special CIF files
[edit] FACES.CIF
The file FACES.CIF contains the NPC portraits seen in the conversation window. There is no header information in the file, just 61 64x64 images placed one after another.
[edit] WEAPON CIF files
Unfortunately, once again, there are exceptions to the general CIF format, the WEAP*.CIF files. These images images for the weapons seen when you equip and attack from the main display. The first image in a weapon CIF is usually the normal weapon seen when you aren't attacking but have the weapon armed. This first image is the usual IMG format. Note that the file WEAPON09.CIF has the bow and hand-to-hand weapons which do not have this first image as they aren't visible unless you are attacking. The basic overall format is as follows:
Image #1 Header (except for WEAPON09.CIF) Regular IMG Header
Image #1 Data (except for WEAPON09.CIF) Regular IMG Data
Group #1 Header
RLE Image #1 Data
RLE Image #2 Data
...
Group #2 Header
...
etc...
[edit] Weapon CIF Group Header
The header is similar to the IMG image header but is longer, 76 bytes and has a few fields switched around.
[Bytes 0-1] short Width;
[Bytes 2-3] short Height;
Note that the offset and size fields are switched around from
the IMG format.
[Bytes 4-5] short XOffset;
[Bytes 6-7] short YOffset;
Assuming from the IMG format
[Bytes 8-9] short Unknown;
The value 0x0015 which appears only in WEAPON09.CIF
(unconfirmed). Otherwise unknown (possibly 0).
[Bytes 10-11] short ImageSize;
[Bytes 12-75] short ImageOffsetList[32];
These values are the offset from the start of the header to the
beginning of the RLE compressed image data for each of the
images in the group. Note that the last offset in the list
gives the offset to the start of the next group header.
[edit] Weapon CIF RLE Image Data
The weapon CIF image data for the group images (not the first image) is compressed in a form of RLE bytes (RLE means Run-Length-Encoded). The basic algorithim for decoding this data is as follows:
while BytesRead < Width*Height
Data = read 1 byte from file
if (Data > 127) then
PixelData = read 1 byte from file
Copy PixelData to image (Data-127) times
BytesRead += (Data-127)
else
Read in (Data+1) bytes from file
Copy (Data+1) bytes to image
BytesRead += (Data+1)
end if
end while
As an example, take the raw hexadecimal byte string
C7 00 01 77 71 81 70 00 75 D9 00
1. C7, decode as (C7-7F) = 48 x 00
2. 01, read in (01+01) bytes = 77 71
3. 81, decode as (81-7F) = 2 x 70
4. 00, read in (00+01) bytes = 75
5. D9, decode as (D9-7F) = 5A x 00
Summary: Total of A7 pixels decoded (167)
[edit] Texture file formats
Texture files are all files in the ARENA2 game directory that match TEXTURE.??? where ??? is a number ranging from 000 to 511 (there are some numbers missing as there are 472 files total). The description which follows has been tested extensively and appears to describe the overall format accurately enough to be able to export all the images to PCX files successfully, all 10,956 of them. Note that there are 4 special texture files which are not described by the format and contain no images (see Appendix A).
[edit] General File Layout
Texture Header (26 Bytes)
Image Header Offset List
...Image Headers...
...Image Data...
...
The overall texture format is slightly more complicated than the usual DF image format. The texture header and offset list are always the same, although the latter is variable length. The Image Headers and Data occur throughout the file with relatively little apparent order. What it appears to be is that the image data is always stored in images 256 bytes wide. Thus, if you had 4 images 64 pixels wide and 100 high, these would be stored in one big image 256x100 in size. Thus, reading the image data is not a simple matter as you have to read 1 column, skip 256 bytes, read the next column, etc... Fortunately, the offset to the first byte of image data is given in the image header. Image headers are grouped together so image data does not usually follow the header.
To simplify, the basic input routine for the image data would be as follows:
Read Header and Offset List
For Each Image
Jump to Image Header Offset in File
Read Image Header
Jump to Start of Image Data
For Each Row in Image
Read Image Row
Jump Forward 256-ImageWidth Bytes
Next
Next
Note that not all textures follow this convention, but most do.
[edit] Texture Header
The header always starts off the texture file and is always 26 bytes in length.
[Bytes 0-1] short NumImages;
The number of images contained in the texture file. This value
ranges from 1 to 128 in texture files.
[Bytes 2-25] char TextureName[24];
Contain a string describing the texture file. Assumably it
includes the terminating NULL character.
[edit] Image Header Offset List
The offset list follows the texture header in the file and contains one 20 byte record for each image in the texture.
[Bytes 0-1] short Type1;
[Bytes 2-5] long HeaderOffset;
Contains the offset to the of the image header from the origin
of the texture file.
[Bytes 6-7] short Type2;
[Bytes 8-11] long Unknown1;
Ranges from 0 to 4 but is usually zero (90% of all images).
[Bytes 12-15] long NullValue1;
[Bytes 16-19] long NullValue2;
Always zero (confirmed).
[edit] Image Header
Each image header is pointed to by the HeaderOffset in the offset list at the beginning of the file. It contains 28 bytes of information.
[Bytes 0-1] short XOffset;
[Bytes 2-3] short YOffset;
Unconfirmed what these values really are, but could be some
sort of offset used to position the texture when drawn.
[Bytes 4-5] short Width;
[Bytes 6-7] short Height;
Size, in pixels, of the image.
[Bytes 8-9] short Unknown1;
0x0108 = Image has subimages which are RLE compressed data.
0x1108 = Image has RLE type compressed data with a row offset
section before the single image data.
[Bytes 10-13] long ImageSize;
Total size of the image including this 28 byte header.
[Bytes 14-17] long ImageOffset;
Offset to the first byte of the image data from the start of
this header.
[Bytes 18-19] short Unknown2;
0x0000 = Image has subimages in special compressed format.
0x00C0 = Usual value, regular single image.
NonZero = Regular single image. Unknown what the differences
in the values indicate.
[Bytes 20-21] short NumSubImages;
This value indicates the number of subimages in the image
data. Usually this value is 1 indicating the usual image
format, but some image records contain several subimages and
have a special format (see below).
[Bytes 22-25] long Unknown3;
[Bytes 26-27] short Unknown4;
Side note from DigitalMonk 00:04, 1 August 2008 (EDT): While trying to determine if any of the Unknown fields might control texture scaling, I discovered that Unknown3 and Unknown4 should probably instead be treated as:
[Bytes 22-23] short Unknown3;
[Bytes 24-25] short Unknown4;
[Bytes 26-27] short Unknown5;
I still don't know what they do, and changing them in a texture file doesn't seem to do anything. Oddly, Unknown4==Unknown5 in all the images I've looked at. I've also tried breaking them down further into bytes, but no new patterns seem to appear.
[edit] SubImage Format
If the number of subimages is greater than 1, it indicates that the image is composed of a number of seperate images and has a slightly different format. The offset pointed to by the ImageOffset in the image header is to a list of long offsets to the seperate image data. Unlike the usual images data which is combined into one big 256 pixel wide image, subimage data is linear, although it is still seperated into rows. The subimage data format is as follows:
Subimage Offset List - long Offsets[NumSubImages];
The offset is relative to the start of the offset list.
Subimage #1 Data
short ImageWidth;
short ImageHeight;
SubImage Row #1 Data
Row data is slightly compressed in a format which is
described further below.
SubImage Row #2 Data
...etc...
Subimage #2 Data
...
...etc...
[edit] SubImage Row Data Format
The row data of each subimage is slightly compressed in a form of RLE encoding where only the 00 pixels are compressed (that is the pixels that are not displayed in the texture to provide transparency). For each row the basic algorithim to read and decode the bytes is as follows:
While Not Finished Row
NumZeroBytes = get character from file
Add NumZeroBytes to Image Row
NumImageBytes = get character from file
Read NumImageBytes from file to Image Row
End While
As an example, take the encoded byte string
30 00 18 01 EF 17 00 17 02 EF EF 17 00
for an image that is 0x30 pixels wide. The rows decode as follows:
Row 1: Made entirely of zeros (0x30 bytes of zero, 00 pixel bytes)
Row 2: Starts with 0x18 bytes of zero
0x01 bytes of pixel data (0xEF)
Ends with 0x17 bytes of zero (0x18 + 0x01 + 0x17 = 0x30)
Row 3: Starts with 0x17 bytes of zero
0x02 bytes of pixel data (0xEF 0xEF)
Ends with 0x17 bytes of zero (0x17 + 0x02 + 0x17 = 0x30)
[edit] RLE Image Format
Some single images have compressed data which seems to be indicated by the value 0x1108 in the Unknown1 parameter of the image header (unconfirmed but pretty sure at the moment). The format of the image data pointed to by the DataOffset in the image header is as follows:
RowOffsets[ImageHeight] (8 bytes each)
Contains 8 byte records for each of the rows in the image. The
record data is:
short RowOffset;
Offset from the start of the image header to
the start of the compressed row data.
short Encoded;
0x0000 Indicates an uncompressed row
0x8000 Indicates a RLE type compressed row.
These are the only values it ever takes.
RowData[ImageHeight] (variable length)
Contains compressed row data in a form of RLE bytes. The
format is as follows:
short RowSize;
Length of the row in pixels (not bytes of
compressed data).
RLE Compressed Data
See the RLE Compressed Data section below.
[edit] RLE Compressed Data Format
The RLE compressed image data is basically composed of 3 byte triplets, that is you can read 3 bytes of data at a time to determine what to do. The basic format is:
signed short ByteCount;
If this value is positive, it indicates the number of raw
uncompressed pixel bytes which follow. Thus, the byte string
'03 00 7F 7D 7E' merely uncompresses as 3 pixels with values
'7F 7D 7E'.
If this value is negative it indicates that the next pixel
byte is to be repeated (-ByteCount) times. Thus, the byte
string 'F9 FF 7D' uncompresses as '7D 7D 7D 7D 7D 7D 7D'
unsigned char RLEData;
Start of the pixel data. If ByteCount is negative, the next
byte after this will be the next 3 bytes of RLE data (or the
next row if this is the last pixel in the current row). If
ByteCount is positive there may be more pixel data which
follows this byte.
[edit] RLE SubImage Format
So we have special formats for subimages, for single RLE encoded images, so obviously we must confuse things further with a RLE subimage format. This format occurs in images that have multiple subimages and also have the RLE encoding flag set with the Unknown1 variable in the image header. Although unconfirmed, a value of Unknown1 = 0x0108 indicates a RLE subimage format. As the name implies, it combines the subimage and RLE single image formats. There is no subimage offset table but the RLE row offset table contains offsets to all the rows of the subimages, one after the other, as shown below.
Subimage #1, Row #1 Offset
Subimage #1, Row #2 Offset
...
Subimage #1, Row #Height Offset
Subimage #2, Row #1 Offset
...
Subimage #2, Row #Height Offset
...etc...
Thus, the subimages can be extracted by combining consecutive (from the RLE offset table) ImageHeight rows of image data. Note that consecutive rows in the RLE offset table may not nessecarily be consecutive rows of data in the file.
[edit] Special Texture Files
There are a few texture files which do not exactly fit the above format:
TEXTURE.000
TEXTURE.001
These two texture files each contain 128 (0x80) images but with no
image header or data, just the texture header and offset list. The
high byte of the offset list Type1 parameter holds the palette color
index of the color to use for the texture (assumably). The texture
is used for any objects colored with a solid color and not a bitmap.
The file can be identifed by an image offset of 0.
TEXTURE.215
TEXTURE.217
Each of these textures contain one image but with only the texture
header and offset list, no image header or data. Most likely these
files are not used.
[edit] PAL format
The PAL palette files were trivial to intepret since the size of the files were all 768 bytes (768 = 256 * 3). A PAL file simply contains the Red, Green, and Blue components of each colour in that order for each of the 256 colours in the palette. Like regular VGA palettes, colour components values range from 0-63 (0x00 to 0x3F).
Note: The file PAL.PAL is actually in COL format.
[edit] COL format
This is an Autodesk Animator Pro format:
Bytes 1 - 4 INT32 File size (always 776)
Bytes 5 - 6 INT16 Format ID (always 0xB123)
Bytes 7 - 8 INT16 Format version (always 0)
Bytes 9 - 776 CHARS 256-color, 24-bit RGB palette
Note: The palette is a full 24-bit palette, with values in the range 0..255 for every color channel.

![[Content is available under Attribution-ShareAlike]](http://www.uesp.net/w/images/Somerights.png)