Daggerfall:Image formats

The UESPWiki – Your source for The Elder Scrolls since 1995

Jump to: navigation, search


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.

Sponsored Links
Personal tools