TES Chapter 2: DAGGERFALL - IMAGE FILE FORMATS
IMG, CIF, PAL, COL, and Texture File Formats
by Dave Humphrey - 4 November 2000
dave@uesp.net
This file was initially distributed with DAGPIC, a DOS program which uses the
file format descriptions found below. This file may be distributed at will.
The latest version can always be found at www.uesp.net/dagger/
CONTENTS
=================================================
IMG File Format
Special IMG Files
CIF File Format
Special CIF Files
Weapon CIF Files
Weapon CIF Group Header
Weapon CIF RLE Image Data
TEXTURE File Format
General File Layout
Texture Header
Image Header Offset List
Image Header
SubImage Format
SubImage Row Data Format
RLE Image Format
RLE Compressed Data Format
RLE SubImage Format
Special Texture Files
PAL File Format
COL File Format
Appendix A - Special Texture Files
IMG FILE FORMAT
=================================================
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).
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.
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.
Special CIF Files
--------------------------------------------
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.
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...
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.
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)
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).
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.
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.
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).
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;
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...
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)
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.
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.
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.
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.
PAL FILE 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).
COL FILE FORMATS
=================================================
The COL palette files are similar to PAL files although they are 8 bytes
larger. COL files appear to contain an 8 byte header which can simply be
ignored at the moment.
Appendix A - Special Texture Files
=================================================
There are a four special texture files which should be noted to not
follow the format given in this document.
Texture.000 Color file (no images), colors 0x00 to 0x7f
Texture.001 Color file (no images), colors 0x80 to 0xFF
Texture.215 Empty except for the file header and offset list.
Texture.217 Empty except for the file header and offset list.
If you have any problems, suggestions or comments on this page or website, please
feel free to use the Contact Form to send
a message to the WebMaster.
This document was last modified on: Friday, 17 August 2007, at 19:43:21
and has been accessed
1390
times
( dagger/imgfrm.txt ).
/text.shtml