Loading and Saving DDS Files

DirectDraw Surface is Microsoft's file format for storing textures. You can find information on this file format and on its Imaging support in Supported File Formats/DDS section. This section shows how to perform some load/save operations specific for DDS files (cube map and volume texture support). Each example consists of description of a action you want to do and code listing in which the action is carried out by Imaging.

Example 1: Simple Loading and Saving

You have single texture without mipmaps and you want to load it and save it.

uses
  ImagingTypes, Imaging;
var
  Img: TImageData;
begin
  // call this before using any TImageData record
  InitImage(Img);
  // load texture from file
  LoadImageFromFile('X:\images\tex01.dds', Img);
  ...
  // do something with the image
  ...
  // save the image to file
  SaveImageToFile('X:\images\tex02.dds', Img);
  // memory occupied by the image is freed
  FreeImage(Img);
end.
    
Example 2: Loading and Saving Mipmapped Texture

You have single texture with mipmaps and you want to load it and save it.

Warning: Imaging saves mipmaps in the same order as you send them to SaveMultiImageTo* functions in Images parameter. Mipmap dimensions (next level has width and height of the previous level divided by two) and format (must be same as the main image's) are automatically adjusted during saving.
uses
  ImagingTypes, Imaging;
var
  ImgArray: TDynImageDataArray;
  MipMapLevels: LongInt;
begin
  // load texture from file
  LoadMultiImageFromFile('X:\images\tex01mip.dds', ImgArray);
  // get the number of mipmap levels in the loaded DDS file
  // in this case it is equal to Length(ImgArray)
  MipMapLevels := GetOption(ImagingDDSLoadedMipMapCount);
  ...
  // do something with the image
  ...
  // save the texture with mipmaps to file, number of mipmaps saved to
  // file will be Length(ImgArray)
  SaveMultiImageToFile('X:\images\tex02mip.dds', ImgArray);
  // memory occupied by the images is freed
  FreeImagesInArray(ImgArray);
end.
    
Example 3: Loading and Saving Mipmapped Cube Map

You have cubic environment map with mipmaps and you want to load it and save it. The cube faces in DDS files are written in this order: positive x, negative x, positive y, negative y, positive z, negative z. Each face is written with its main image followed by any mipmap levels. All faces must be the same size and have the same number of mipmap levels.

Warning: Imaging saves cube faces and mipmaps in the same order as you send them to SaveMultiImageTo* functions in Images parameter. Make sure that number of images you send to saving functions is equal to NumberOfFaces * MipMapLevels where these two values are defined by options interface (see code below). If the number of images is not right then DDS is saved as simple 2D texture. Mipmap dimensions (next level has width and height of the previous level divided by two) and format (must be same as the main image's) are automatically adjusted during saving.
uses
  ImagingTypes, Imaging;
var
  ImgArray: TDynImageDataArray;
  MipMapLevels, Faces: LongInt;
  IsCubeMap: Boolean;
begin
  // load texture from file
  LoadMultiImageFromFile('X:\images\tex01cubemip.dds', ImgArray);
  // get the number of mipmap levels in the loaded DDS file
  // in this case it is equal to Length(ImgArray) div Faces
  MipMapLevels := GetOption(ImagingDDSLoadedMipMapCount);
  // check whether we have loaded cube map
  IsCubeMap := Boolean(GetOption(ImagingDDSLoadedCubeMap));
  // get the number of cube faces in the loaded DDS file
  // Length(ImgArray) = Faces * MipMapLevels
  Faces := GetOption(ImagingDDSLoadedDepth);
  ...
  // do something with the image
  ...
  // tell Imaging how many mipmap levels next DDS file should have (for each face)
  SetOption(ImagingDDSSaveMipMapCount, MipMapLevels);
  // tell Imaging that the next DDS file should be cubic environment map
  SetOption(ImagingDDSSaveCubeMap, IsCubeMap);
  // tell Imaging how many faces next DDS file should have
  SetOption(ImagingDDSSaveDepth, Faces);
  // save the cube map with mipmaps to file
  SaveMultiImageToFile('X:\images\tex02cubemip.dds', ImgArray);
  // memory occupied by the images is freed
  FreeImagesInArray(ImgArray);
end.
    
Example 4: Loading and Saving Mipmapped Volume Texture

You have volume texture with mipmaps and you want to load it and save it. For volumes without mipmaps, each depth slice is written to the file in order. If mipmaps are included, all depth slices for a given mipmap level are written together, with each level containing half as many slices as the previous level with a minimum of 1. Volume textures do not support DXTn compression as of DirectX 9.0.

Warning: Imaging saves volume slices and mipmaps in the same order as you send them to SaveMultiImageTo* functions in Images parameter. Make sure that number of images you send to saving functions is right (it is not NumberOfFaces * MipMapLevels!). If the number of images is not right then DDS is saved as simple 2D texture. Mipmap dimensions (next level has width and height of the previous level divided by two) and format (must be same as the main image's) are automatically adjusted during saving.
uses
  ImagingTypes, Imaging;
var
  ImgArray: TDynImageDataArray;
  MipMapLevels, Slices: LongInt;
  IsVolume: Boolean;
begin
  // load texture from file
  LoadMultiImageFromFile('X:\images\tex01volmip.dds', ImgArray);
  // get the number of mipmap levels in the loaded DDS file
  // in this case it is NOT equal to Length(ImgArray) div Slices
  MipMapLevels := GetOption(ImagingDDSLoadedMipMapCount);
  // check whether we have loaded volume texture 
  IsVolume := Boolean(GetOption(ImagingDDSLoadedVolume));
  // get the number of volume slices in the loaded DDS file
  // Length(ImgArray) <> Slices * MipMapLevels
  Slices := GetOption(ImagingDDSLoadedDepth);
  ...
  // do something with the image
  ...
  // tell Imaging how many mipmap levels next DDS file should have
  SetOption(ImagingDDSSaveMipMapCount, MipMapLevels);
  // tell Imaging that the next DDS file should be volume texture
  SetOption(ImagingDDSSaveVolume, IsVolume);
  // tell Imaging how many slices next DDS file should have
  SetOption(ImagingDDSSaveDepth, Slices);
  // save the volume texture with mipmaps to file
  SaveMultiImageToFile('X:\images\tex02volmip.dds', ImgArray);
  // memory occupied by the images is freed
  FreeImagesInArray(ImgArray);
end.