DDS File Documentation


Summary

A DDS (DirectDraw Surface) file is a texture image used by DirectX games and 3D engines such as Unreal, Unity, Source and Bethesda titles. It stores GPU-ready, block-compressed pixels plus a precomputed mipmap chain, so games can load textures with almost no processing; its MIME type is image/vnd-ms.dds. View a .dds with the free XnView MP or IrfanView, edit it in free Paint.NET or GIMP, and convert it to PNG or JPG when you need an ordinary image.

Technical details

FeatureValue
Full nameDirectDraw Surface (DirectX texture image)
File extension.dds
MIME typeimage/vnd-ms.dds
Format typeBinary raster texture container
DeveloperMicrosoft (DirectX)
IntroducedDirectX 7 (1999); DX10 header extension in 2006
SpecificationMicrosoft DDS programming guide (Direct3D)
Open standardPartial — documented by Microsoft
Byte orderLittle-endian
Magic number (hex)44 44 53 20 (DDS , with trailing space)
Header size124-byte DDS_HEADER (after the 4-byte magic)
Pixel-format block32-byte DDS_PIXELFORMAT inside the header
Extended headerOptional 20-byte DDS_HEADER_DXT10 (FourCC DX10)
CompressionBlock: DXT1/3/5 (BC1/2/3), BC4–BC7; or uncompressed
MipmapsOptional precomputed chain (full, 1/2, 1/4 …)
Surface types2D textures, cubemaps, volume (3D) textures, arrays
Related extensions.png, .tga, .ktx2, .psd, .bmp
Specification URLlearn.microsoft.com/windows/win32/direct3ddds/dx-graphics-dds
File signature (magic bytes)
44 44 53 20

Offset 0, 4 bytes. In ASCII this reads DDS — note the trailing space — and as a little-endian 32-bit value it is 0x20534444. It is immediately followed by the 124-byte DDS_HEADER (whose own dwSize field must equal 124), which contains the 32-byte DDS_PIXELFORMAT block. Files that use the modern DX10 extension carry the FourCC DX10 in the pixel format and insert an extra 20-byte DDS_HEADER_DXT10 before the pixel data. The texture data (block-compressed or raw) plus any mipmaps follow the header(s).

What is a DDS file?

DDS stands for DirectDraw Surface. It is Microsoft’s container format for textures, introduced with DirectX 7 in 1999 and part of the DirectX SDK ever since. Its whole reason for existing is to store image data the way a GPU wants to consume it, so a game can read a texture off disk and hand it almost straight to graphics memory with little or no processing. A .dds begins with the four-byte magic DDS , then a header describing the image, then the pixel data — usually already compressed into the exact block format the graphics hardware decodes natively.

That GPU-first design is why DDS is everywhere in game development and modding. Unreal Engine, Unity, the Source engine and Bethesda’s Skyrim and Fallout all ship DDS textures, so anyone who opens a game’s asset folder or downloads a texture mod runs into .dds files constantly. The recurring needs are to view a texture, to edit it while keeping the right compression and mipmaps, and to convert it to an ordinary PNG or JPG. The sections below cover the header layout, the block-compression formats, the mipmap chain, and how those constraints shape editing.

The DDS_HEADER: 124 bytes of dimensions, flags and caps

After the 4-byte magic comes a fixed 124-byte DDS_HEADER. Its first field, dwSize, must equal 124, which acts as a sanity check on top of the magic. The header describes the whole texture: its size, how many mipmaps it has, and which of its fields are actually valid.

DDS_HEADER (124 bytes, little-endian; follows the 4-byte "DDS " magic)
offset size field
  0     4   dwSize                = 124
  4     4   dwFlags               which fields below are valid
  8     4   dwHeight              surface height in pixels
 12     4   dwWidth               surface width in pixels
 16     4   dwPitchOrLinearSize   bytes per scanline (uncompressed) OR
                                  total bytes of top mip (compressed)
 20     4   dwDepth               depth, for volume textures
 24     4   dwMipMapCount         number of mipmap levels
 28    44   dwReserved1[11]
 72    32   ddspf                 DDS_PIXELFORMAT (see below)
104     4   dwCaps                surface complexity (mipmap / cubemap flags)
108     4   dwCaps2               cubemap faces / volume flag
112     4   dwCaps3               (unused)
116     4   dwCaps4               (unused)
120     4   dwReserved2

The dwFlags bitmask states which members carry meaningful data (for example a flag marks whether dwMipMapCount or dwPitchOrLinearSize is set). dwPitchOrLinearSize is interpreted two ways: for an uncompressed texture it is the pitch (bytes per scanline), while for a block-compressed texture it is the total byte size of the top-level surface. The dwCaps and dwCaps2 fields flag whether the file is a simple 2D texture, a texture with mipmaps, a cubemap (and which of its six faces are present), or a volume texture. Everything a loader needs to lay out the data that follows is encoded here.

The DDS_PIXELFORMAT block and FourCC codes

Nested inside the header at offset 72 is the 32-byte DDS_PIXELFORMAT structure (its own dwSize is always 32). This is the field that tells a loader how the pixels are actually encoded: whether the surface is compressed, and if so with which scheme, or if uncompressed, the exact bit masks for the red, green, blue and alpha channels.

DDS_PIXELFORMAT (32 bytes)
offset size field
  0     4   dwSize        = 32
  4     4   dwFlags       DDPF_FOURCC (compressed) / DDPF_RGB (uncompressed) ...
  8     4   dwFourCC      "DXT1","DXT3","DXT5","DX10", or 0 for uncompressed
 12     4   dwRGBBitCount bits per pixel (uncompressed)
 16     4   dwRBitMask
 20     4   dwGBitMask
 24     4   dwBBitMask
 28     4   dwABitMask

When the DDPF_FOURCC flag is set, dwFourCC names the compression: the classic DXT1, DXT3 and DXT5, or the special value DX10. That last value signals that a further 20-byte DDS_HEADER_DXT10 extension header follows before the pixel data; it carries a full DXGI format enum (used for BC4–BC7 and modern formats), a resource dimension, and an array size. When the FourCC is instead zero, the surface is uncompressed and the four bit masks describe the channel layout directly (for example an 8-8-8-8 RGBA surface). A DDS reader therefore branches on this one block to decide how to interpret every byte after the header.

Block compression: DXT1–DXT5 and BC4–BC7

The defining feature of DDS is block compression. Instead of storing per-pixel RGBA values, the image is divided into 4×4 pixel blocks, and each block is encoded into a small fixed-size chunk that the GPU decompresses on the fly. This keeps the texture small in video memory, and because the ratio is fixed the hardware can address any block directly.

FormatAlso calledBlock sizeBest for
DXT1BC18 bytes / 4×4Colour, optional 1-bit alpha
DXT3BC216 bytes / 4×4Colour with sharp/explicit alpha
DXT5BC316 bytes / 4×4Colour with smooth alpha
BC48 bytes / 4×4Single-channel (height/gloss)
BC516 bytes / 4×4Two-channel normal maps
BC6H16 bytes / 4×4HDR colour (DX10)
BC716 bytes / 4×4High-quality colour + alpha (DX10)

DXT1/BC1 packs a 4×4 block into 8 bytes by storing two 16-bit reference colours and a 2-bit index per pixel that interpolates between them; DXT5/BC3 adds a separately compressed alpha block for smooth transparency. The newer BC4–BC7 formats, reachable only through the DX10 extension header, give single-channel and two-channel encodings (BC5 is the standard choice for normal maps because it stores two channels at high precision) and, in BC7, near-lossless colour-plus-alpha. Choosing the wrong one on save is the classic modding mistake: compressing a normal map as DXT1 or as JPG-style colour destroys the surface detail, which is why normal maps use BC5 and colour-with-alpha uses BC3 or BC7.

The mipmap chain and why textures store it

A DDS usually embeds a mipmap chain: the same image pre-scaled to successively half sizes — full resolution, then 1/2, 1/4, 1/8, down to 1×1 — stored one level after another following the top surface. The number of levels is in dwMipMapCount. The GPU picks the level whose texel density best matches how large the surface appears on screen, so a wall seen far away samples a small mip instead of the full texture. This both speeds rendering and removes the shimmering aliasing that sampling a full-resolution texture at distance would produce.

Storing mipmaps in the file rather than generating them at load time is a deliberate trade: the file is larger, but the GPU does no work to build them. It also means an editor must regenerate the chain whenever the top image changes. Tools like Paint.NET, GIMP and Microsoft’s texconv expose a “generate mipmaps” option on export for exactly this reason, and forgetting it leaves a texture that renders correctly up close but breaks up at distance in-game. Ordinary image formats like PNG have no mipmap concept, which is why converting DDS to PNG silently drops the chain.

Viewing, editing and converting DDS textures

For a quick look, the free XnView MP and IrfanView open DDS directly and batch-convert folders of them to PNG or JPG. For actual editing, Paint.NET and GIMP both have native DDS support: they open the texture, let you paint, and on export let you pick the compression (DXT1/DXT5/BC7) and regenerate mipmaps. Photoshop handles DDS through the free NVIDIA Texture Tools Exporter or Intel Texture Works plugins, which expose full BC1–BC7 control. On the command line, Microsoft’s texconv (part of DirectXTex) converts DDS to and from PNG or TGA with precise format control, and can retarget textures to the modern KTX2 container used by glTF and web engines.

The reason a plain image viewer often fails to open a .dds is simply that it does not understand block compression or the DDS header; a DDS-aware tool does. When converting out, remember what the target format cannot carry: PNG keeps the alpha channel but drops mipmaps, JPG drops alpha and corrupts normal/specular maps with its lossy compression, and TGA gives an uncompressed interchange copy with alpha but no mip chain. Convert to PNG for a faithful lossless copy, and only to JPG for plain colour textures where a smaller lossy file is acceptable.

Frequently asked questions

Why won’t my normal image viewer open a .dds?

Most basic viewers do not implement DirectX block compression or the DDS header, so they cannot decode the pixels. Use a DDS-aware tool — XnView MP, IrfanView, Paint.NET or GIMP — which reads the 124-byte header, sees the FourCC in the pixel-format block, and decompresses the DXT/BC data correctly.

What do DXT1, DXT5 and BC7 mean when saving a DDS?

They are the block-compression formats. DXT1/BC1 stores colour with at most 1-bit alpha in 8 bytes per 4×4 block; DXT5/BC3 adds smooth alpha in 16 bytes; BC5 is the two-channel format for normal maps; and BC7 (a DX10-header format) gives high-quality colour plus alpha. Match the original texture’s format, or the game may render it wrong.

Do I need to keep mipmaps when I edit a DDS?

Usually yes. Games rely on the mipmap chain to sample lower-resolution copies at distance, avoiding aliasing. When you re-export in Paint.NET, GIMP or texconv, enable “generate mipmaps” unless the asset specifically uses none, or the texture will shimmer or break up when viewed far away in-game.

References