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: Saturday, 19 February 2011, at 09:55:52 and has been accessed 2861 times ( dagger/imgfrm.txt ).
/text.shtml