What Is a DDS File? A Texture Your Graphics Card Reads Without Unpacking It
A DDS file holds a texture, not really a picture. Jump to your question below, or read it through in order.
A DDS file holds a texture, not really a picture. Jump to your question below, or read it through in order.
A DDS file holds a texture, packed the way graphics hardware wants to read it. Microsoft built the format for DirectX and it has fed 3D games since 1999.
Calling it an image format is where most explanations go wrong. A PNG has to be unpacked into memory before anything can draw with it. A DDS does not, and that difference is the entire point.
DDS stands for DirectDraw Surface. Microsoft built it for real-time rendering applications. DirectDraw was the part of DirectX that handled 2D surfaces in 1999, and the name stuck long after that job moved elsewhere. What survived is a container built to hold raster pixel data in the exact layout a GPU wants.
Open one in an ordinary image viewer and you may well see a picture. That is courtesy, not purpose. Directories file it as a raster image, and file it under video game textures in the same breath.
The DDS container holds various types of data. What is inside can be plain uncompressed pixels or one of seven block-compressed formats, and every guide that gives DDS a single bit depth has missed that.
.ddsDDS , four bytes, note the space.dds as well: Fusion Dialog Development System dialogs and PC6001VX emulator snapshots.JPEG and PNG have to be unpacked into memory before graphics hardware can draw with them. DDS does not. It stays compressed in video memory and the GPU decodes one 4x4 block at a time, on demand, only where it is needed.
Picture a game loading one wall, once from PNG and once from DDS. With PNG, software reads the file, decompresses it into full-size pixels then hands those to the graphics card, and video memory now holds every pixel at full width. Four megabytes for one 1024 by 1024 texture.
With DDS, none of that middle happens. The file already holds the format hardware understands, so data is copied across as it stands. Same texture, half the megabyte, nothing to unpack. That is where the load times go.
Block compression cuts textures into 4 by 4 squares and stores every square in a fixed number of bytes. Fixed is the magic word. Because block twelve always sits eight bytes past block eleven, hardware can jump straight to whichever block it needs.
JPEG cannot do that. Its compression is adaptive, so finding one part means decoding everything before it. Fine for photos you look at once, hopeless for real-time work where a texture is sampled thousands of times per frame.
Unpacked before use. Decoded on the processor, then the full-size pixels are handed over. Memory holds every pixel at full width.
Used as it arrives. Copied into video memory compressed, decoded in hardware block by block, only where something is being drawn.
This is why the format looks strange from outside. No progressive loading, no clever entropy coding, no interlacing. Every one of those would make the file smaller and make random access impossible, and random access is the only thing a graphics card asks for.
Seven block formats, BC1 to BC7. Every one packs a 4 by 4 square into 8 or 16 bytes, which works out at 4 or 8 bits per pixel. All of them lose detail.
DXT1 and BC1 are one format with two names. DXT came from DirectX 8 and BC arrived with Direct3D 10. Both names are still in use, which is why one page calls a file DXT5 and the next calls it BC3.
| Format | Old name | Per 4 by 4 block | What it stores |
|---|---|---|---|
| BC1 | DXT1 | 8 bytes, 4 bits per pixel | Color with 1 bit of alpha |
| BC2 | DXT3 | 16 bytes, 8 bits per pixel | Color with 4 bits of alpha |
| BC3 | DXT5 | 16 bytes, 8 bits per pixel | Color with 8 bits of alpha |
| BC4 | ATI1 | 8 bytes, 4 bits per pixel | One channel, for height or gloss |
| BC5 | ATI2 | 16 bytes, 8 bits per pixel | Two channels, for normal maps |
| BC6H | None | 16 bytes, 8 bits per pixel | HDR color, 16-bit half float |
| BC7 | None | 16 bytes, 8 bits per pixel | Color and alpha, best quality |
Microsoft puts BC1 at 6:1 against 24-bit color and BC2 and BC3 at 4:1 against 32-bit color with alpha. Those ratios never move, because every block costs the same whatever it holds. Older tools call the entire family DXTn, after the DXT names. The algorithm underneath is S3TC.
Block compression is lossy, every format, no exceptions. S3TC, the family behind DXT1 to DXT5, is described by its own documentation as lossy compression that degrades image quality.
Which matters most when you edit. Open one, change a single pixel, hit save. The entire texture goes through compression again.
Four bytes reading DDS , a 124-byte header, then pixel data. Files using a Direct3D 10 format slot an extra 20-byte header in between, so the data starts at byte 148 rather than 128.
A DDS is simpler than most formats on this site. No directory, no index, no chunks. One header says what the pixel data is, then that pixel data follows, surface after surface until the file ends.
| Part | Size | What it does |
|---|---|---|
| Magic number | 4 bytes | The characters DDS , with a trailing space |
| DDS_HEADER | 124 bytes | Width, height, mipmap count, pixel format, surface flags |
| DDS_HEADER_DXT10 | 20 bytes, sometimes | Present only for Direct3D 10 formats, and it names a DXGI format instead |
| Surface data | Everything left | The main image, then every mipmap, then every cube face |
That gives two possible starting points for pixel data, 128 bytes in or 148. Software reading a DDS checks the FourCC in the DDS_PIXELFORMAT block, and when it reads DX10 it knows another header is waiting, carrying texture arrays and the newer formats.
One DDS can hold far more than one image. Mipmaps are smaller copies stacked together, every one half the width of the last, down to a single pixel. Graphics hardware uses whichever size suits how far away a surface is, which stops distant detail flickering.
A cubemap holds six faces, one per direction, which is how reflections and skies get drawn. Volume textures stack slices into a solid block, used for fog, fire and anything with depth. The header says which arrangement applies, through DDSCAPS2_CUBEMAP and DDSCAPS2_VOLUME.
Nearly half the header is officially empty. Microsoft marks dwReserved1, eleven entire DWORDs, as unused, along with dwCaps3, dwCaps4 and dwReserved2. That is 56 bytes of a 124-byte header doing nothing, left over from structures DirectDraw 7 needed and nothing since has.
Block compression is fixed rate. BC1 spends 4 bits on every pixel whatever the picture looks like, and mipmaps add about a third on top. Plain artwork in DDS can easily beat detailed artwork in PNG for size.
The older version of this page promised that DDS files are typically much smaller than PNGs. Sometimes true, often not. The reason is worth knowing before you convert a folder full of them.
PNG looks for repetition and DDS never does. Flat red squares compress to almost nothing, because there is almost nothing to say. Block compression never looks. Every 4 by 4 square costs 8 bytes in BC1, whether it holds faces or flat walls.
| Stored as | Flat two-color art | A detailed photo |
|---|---|---|
| PNG | A few KB | Around 2MB |
| BC1, no mipmaps | 512KB | 512KB |
| BC1 with mipmaps | 699KB | 699KB |
| Uncompressed, 32-bit | 4MB | 4MB |
Same two numbers in both columns, which is the point. A texture costs what its dimensions cost.
Every mipmap is half the width and half the height of the one above, so it costs a quarter as much. Add that quarter, then a sixteenth, then a sixty-fourth. The series settles just under one third more than the original.
Worth paying, because without mipmaps a distant surface flickers as the camera moves. Worth knowing, because it explains why a texture pack arrives so much larger than the artwork that went into it.
Short of disk space in a game folder? The mipmaps are not the place to save it. Dropping them costs more in stutter and shimmer than the space is worth.
Video memory is where the saving lands. BC1 textures take half a megabyte on disk and half a megabyte in video memory. PNG takes a few kilobytes on disk and four megabytes once unpacked. DDS trades file size for the number that matters while a game runs.
Paint.NET and GIMP both open DDS files and cost nothing. XnViewMP, IrfanView and ImageMagick handle them too. Windows Photos does not, which is why double-clicking usually does nothing.
Programs that open DDS files split into two kinds. Viewers show you what is there. Editors let you change it and, more importantly, control which block format comes out the other side.
| Software | Cost | Why choose it |
|---|---|---|
| Paint.NET | Free | The easy answer on Windows. Opens and saves DDS with a format chooser, and reads BC7 |
| GIMP | Free, open source | Windows, macOS and Linux, with DDS support built in since 2.10 |
| XnViewMP | Free | Fast viewing and batch conversion across hundreds of formats |
| ImageMagick | Free, open source | One command over a folder, when there are thousands of files |
| Windows Texture Viewer | Free | Small and quick, when you only want to look |
| File Viewer Plus, Substance Painter | Paid | A general viewer, and the texture tool most studios author in |
| texconv, from DirectXTex | Free, from Microsoft | The reference tool. Every block format, mipmap control, and what game studios use |
| Adobe Photoshop | Subscription, plus a plug-in | Fits an existing workflow. The plug-in is the part that matters |
On macOS, Preview reads many DDS files with nothing installed, though not the newest block formats. Worth trying first, because double-clicking costs nothing.
Two names on old lists have gone. Microsoft DirectX Texture Editor shipped with the DirectX SDK, now retired, deprecated and no longer available; DirectXTex and its texconv tool replaced it. The NVIDIA plug-in people remember was replaced by NVIDIA Texture Tools Exporter.
The older version of this page also listed DirectX itself as a program that opens files, which it is not.
DDS files hold pixel data and nothing executable. The risk in searching for free DDS viewers is the download sites at the top of those results, not the file. Use getpaint.net, gimp.org, xnview.com or Microsoft's own GitHub.
Two causes cover nearly all of it. Your software is older than the block format inside, or you are asking Windows Photos to do a job it has never done.
Software does not read DDS in general. It reads whichever block formats somebody built in, and BC7 and BC6H arrived with DirectX 11 in 2009. Plenty of viewers stop at DXT5 and say nothing useful about why.
| What you see | What it usually means | Start with |
|---|---|---|
| Double-click does nothing | Windows Photos does not read DDS | Paint.NET, which is free |
| Not supported, or unknown format | A newer format, BC7 or BC6H, in older software | GIMP or texconv, both current |
| No thumbnail in File Explorer | Windows ships no DDS thumbnail handler | A viewer, or a shell extension |
| Opens flat gray or bright green | A normal map, shown as raw color | Nothing. That is what one looks like |
| Only part of the image appears | A cube map, drawn as one face | A viewer that understands cube maps |
| Colors look washed out | An HDR texture squeezed into 8 bits | Software that reads BC6H |
| Nothing opens it at all | Not a texture. See section 1 | Check where the file came from |
Pulled it out of a game archive? Some studios ship DDS files with a custom header or an extra wrapper. If every viewer refuses one file from a folder that otherwise works, that is usually why.
Gray and green are not faults. Normal maps store surface direction in the color channels rather than a picture, so they look pale lavender or vivid green by design. Gloss and height maps store one channel and show up gray.
Out of DDS is easy and safe. Into DDS means choosing a block format, and every save re-compresses the entire texture, so keep your lossless original.
| Convert to | What you get | Good for |
|---|---|---|
| PNG | Lossless, alpha kept, mipmaps dropped | Editing, sharing, keeping a master |
| TGA | Lossless and uncompressed. See the TGA format | Older 3D tools that expect it |
| JPEG | Lossy on top of lossy, no alpha | Almost nothing. Avoid |
| Another DDS | Re-compressed, so a little worse | Changing block format, only once |
Four steps, and the order matters more than the tools.
Generation loss is the reason for that order. Block compression makes the same decisions every time it runs, but it makes them on whatever it is given. The second pass compresses an image that has already lost detail.
JPEG is the wrong destination for textures. It drops the alpha channel, where transparency and often an entire extra map live. It also adds its own losses to losses already there.
PNG or the TGA image format keeps everything. Both are lossless and both hold alpha.
Games are where DDS files live, usually packed inside an archive rather than loose on disk. Modding is how most people meet one, and the filename suffix usually says what kind of map it holds.
Install a game and you will rarely see .dds files at all. Studios pack thousands of textures into one archive, because opening one large file beats opening ten thousand small ones. Unpack that archive and out they come, which is how Skyrim modding starts.
| Ending | What the texture holds | Usual format |
|---|---|---|
_d or _diffuse | The color people actually see | BC1 or BC7 |
_n or _normal | Surface bumps, stored as directions | BC5 |
_s or _spec | How shiny every part is | BC4 |
_m or _mask | Several one-channel maps packed together | BC7 |
_e or _glow | Parts that light themselves | BC1 |
Conventions rather than rules, and every studio bends them. They hold often enough to be worth checking first. Normal maps edited as though they were color come out wrong in ways that are hard to see and easy to ship.
Match what you replace. Same dimensions, same block format, same mipmaps. Otherwise the game may refuse the file or draw it at the wrong size. Powers of two matter as well, because a texture 1000 pixels wide behaves differently from one at 1024.
Building textures from scratch? Keep your working files as Photoshop PSD documents and export DDS at the end. Layers do not survive the trip and there is no way back.
Bigger is not better here. Doubling a texture to 4096 pixels wide costs four times the video memory, and cards that run out start swapping textures in and out mid-frame. That reads as stutter rather than warning.
Microsoft published the file layout, and the compression inside it was patented until 2018. That gap is why open-source graphics drivers shipped for years without support for the most common DDS format there is.
S3 Graphics published S3 Texture Compression in 1998 and patented it. Microsoft adopted it for DirectX as DXT1 through DXT5, and within a few years it was in every graphics card being made.
Which left free software in an awkward position. Anyone could read Microsoft's file layout documentation, so writing a DDS parser was fine. Decoding the pixels inside was the patented part.
| Patent | Expired | Note |
|---|---|---|
| US 5,956,431 | 2 October 2017 | The original S3TC patent |
| US 6,775,417 | 16 March 2018 | A continuation, with a 165-day extension |
Wikipedia puts it plainly: the patent situation presented a major obstacle to open source implementations. Linux distributions shipped drivers with texture compression switched off, and users installed a separate library to turn it back on.
Since March 2018 that is over. Support ships turned on, GIMP reads and writes the formats with no plug-in. Twenty-year-old textures open on a fresh machine with nothing added.
The newer block formats never had this problem. BC6H and BC7 arrived with DirectX 11 in 2009 without the same encumbrance. Open-source tools took them up quickly while DXT1 support stayed awkward for another decade.
Documented by Microsoft, open to read and never registered with IANA. The header is 124 bytes and dwSize must say so, which is the field most hand-written writers get wrong.
Nothing here helps you open a texture. Directories list digital photos and Windows desktop backgrounds among its uses, which is true and beside the point. It is on record for two reasons. DDS is properly documented, which is rare among the formats on this site. And the older version of this page filled its specification table with software names instead.
| Property | Value |
|---|---|
| Full name | DirectDraw Surface (DDS) |
| Kind | A binary container for texture data, never text |
| Published specification | Yes. Microsoft documents it publicly |
| Introduced with | DirectX 7.0, released 22 September 1999 |
| Byte order | Little-endian |
| Signature | 44 44 53 20, which is 0x20534444 read as a little-endian DWORD |
| Header | 124 bytes, and dwSize must be set to 124 |
| Extended header | DDS_HEADER_DXT10, 20 bytes, when the code reads DX10 |
| Smallest valid file | 128 bytes of header, or 148 with the extension |
| Block size | 8 bytes for BC1 and BC4, 16 bytes for every other block format |
| Compression | BC1 to BC7, all lossy, or no compression at all |
| Field | What it holds |
|---|---|
dwSize | Must be 124. Not 128, which is where the pixel data starts |
dwFlags | Which of the fields below are worth reading |
dwHeight, dwWidth | Size in pixels |
dwPitchOrLinearSize | Bytes per row uncompressed, total bytes compressed |
dwDepth | Slices, for a volume texture |
dwMipMapCount | How many mipmap levels follow |
dwReserved1[11] | Unused. Forty-four bytes of nothing |
ddspf | The pixel format block, which names the compression |
dwCaps, dwCaps2 | Texture, cube map or volume, and which faces are present |
dwCaps3, dwCaps4, dwReserved2 | Unused. Twelve more bytes of nothing |
Fifty-six of those 124 bytes are marked unused in Microsoft's own documentation. They are the shape of structures DirectDraw 7 once needed, kept so old readers do not fall over.
Microsoft gives the rule for block-compressed data as max( 1, ((width+3)/4) ) * block-size. Block size is 8 bytes for BC1 and BC4, and 16 for everything else. Round the width up to the next multiple of four, count the blocks, multiply.
Which is why 1000-pixel textures waste a little and 1024-pixel ones do not, and why powers of two are still the habit twenty-five years on.
Required flags are easy to miss. Microsoft asks for DDSD_CAPS, DDSD_HEIGHT, DDSD_WIDTH and DDSD_PIXELFORMAT, plus DDSCAPS_TEXTURE. Mipmapped files need DDSD_MIPMAPCOUNT as well. Files missing them often still load, which is worse than failing, because they fail somewhere else later.
Two questions sort out most of what is left. Answer them in order.
Do that first. Free, current on block formats and the end of most DDS problems. See section 6.
Check what map it is. Gray and green textures are normal maps and gloss maps, working exactly as intended. Section 9 reads the filenames.
Working with other graphics files? TGA image files are what most 3D tools expect as a lossless source, and PCX picture files turn up in archives from the same era of PC graphics.
Editing the artwork instead? PSD files from Photoshop hold your layers, and Adobe Illustrator AI files or EPS vector files are where logos and flat art usually start.
Building something in 3D? STL model files carry the shape a texture gets wrapped around, and PDF documents are where the finished renders end up.
Stuck on your computer rather than your file? Our Windows fixes and macOS guides cover the system side.
New to all of this? What a file format is covers the ground underneath, and our file format guides list the rest.
Found something here that does not match your own file? Send us the exact wording on screen and we will check it against Microsoft's reference.