Game textures: DDS, TGA, EXR and HDR
Open a .dds from a game, mod or engine and see its DXGI format, every mip level and every face of a cube map, one channel at a time. A .tga, an OpenEXR .exr or a Radiance .hdr opens too, with exposure for the floating-point ones. Save what you are looking at as a PNG.
Everything is decoded by this tab on your device. The file is never uploaded.
What it shows
- DDS (DirectDraw Surface): the DXGI format by its exact name (for example
DXGI_FORMAT_BC7_UNORM_SRGB), whether it came from the DX10 header, an old FourCC such asDXT5orATI2, or bit masks; the size, the mip chain, cube-map faces, array size, volume depth and the DX10 alpha mode. A mip picker, a face picker for cube maps and a slice picker for arrays and volume textures. Decoded here: BC1 (DXT1), BC2 (DXT3), BC3 (DXT5), BC4, BC5, BC6H, BC7, 8-bit RGBA and BGRA, R8, R8G8, A8, 5:6:5, 5:5:5:1, 4:4:4:4, 10:10:10:2, 16-bit UNORM, half and full floats, R11G11B10 and RGB9E5. Any other format is named, with its header facts. - TGA (Truevision Targa): uncompressed and RLE, true-colour (15, 16, 24 and 32 bits), greyscale and colour-mapped, with the origin and alpha bits from the header and, in a TGA 2.0 file, the author, software, date and alpha type from its extension area.
- OpenEXR (.exr): half and float channels with NONE, RLE, ZIPS, ZIP, PIZ, PXR24, B44 and DWA compression, decoded by three.js r186’s EXR loader (vendored on this site), plus every header attribute: channels, windows, line order, and any owner, comments or capture date.
- Radiance HDR (.hdr): flat and run-length-encoded RGBE, with the header’s program, exposure, gamma and primaries.
- For every format: R, G, B and A switched on and off (one channel alone shows as grey), alpha over a checkerboard, zoom from fit to 3200 % with square pixels, a probe that reads the stored value under the pointer (floats for HDR, and the 4 × 4 block it sits in for BC formats), and Save as PNG of exactly the mip, face, channels and exposure on screen. HDR pictures get an exposure slider in stops, a choice of curve (clamp or ACES-like) and the minimum, maximum and mean luminance.
Reading a DDS header
A DDS file is the four bytes DDS followed by a 124-byte header: height, width, mip count, a pixel-format block and the capability flags that mark a cube map and which of its six faces are present. The pixel-format block either holds bit masks (an uncompressed layout such as A8R8G8B8) or a FourCC: DXT1 is BC1, DXT3 BC2, DXT5 BC3, ATI1 BC4 and ATI2 BC5. Formats newer than Direct3D 9, BC6H and BC7 among them, need the FourCC DX10 and a further 20-byte header that names a DXGI format and adds an array size and an alpha mode.
The pixels follow in a fixed order: for each array element (or cube face, in the order +X, −X, +Y, −Y, +Z, −Z), mip 0 first and then each smaller mip down to 1 × 1. Worked example: a 1024 × 1024 BC1 texture is 256 × 256 blocks of 8 bytes, 524,288 bytes; its ten smaller mips add 174,776 more (a third, as always), so with the 128-byte header the file is 699,192 bytes. The same texture in BC3 or BC7, at 16 bytes a block, is twice that. If a file is shorter than its header promises, the page lists which surfaces are missing and draws the ones that are there.
Block compression in one list
- BC1, 4 bits per pixel: two 5:6:5 colours and two in between; when the first colour is the smaller, one index means transparent black (1-bit alpha, “DXT1a”).
- BC2, 8 bits: a BC1 colour block plus a plain 4-bit alpha for each pixel. BC3, 8 bits: BC1 colour plus smooth alpha from two 8-bit endpoints and six or eight steps.
- BC4, 4 bits: one channel (height, roughness, masks), shown here as grey. BC5, 8 bits: two such channels, almost always the X and Y of a tangent-space normal map.
- BC6H, 8 bits: RGB half floats for HDR skies and lightmaps, 14 modes, unsigned (UF16) or signed (SF16). BC7, 8 bits: high-quality RGB or RGBA, 8 modes with up to three colour lines per block.
Why a BC5 normal map looks red and green: only X and Y are stored, and the shader rebuilds Z as √(1 − x² − y²). The page does the same and puts Z in blue, so the picture looks like the familiar lilac normal map; the probe still shows the two stored values.
TGA: no signature and two origins
A TGA starts with an 18-byte header and no magic number, so a TGA under the wrong name looks like random bytes. TGA 2.0 files end with a 26-byte footer that does carry one, TRUEVISION-XFILE., and that is how this page recognises them; a TGA 1.0 file is recognised by a plausible header when it is named .tga. Rows are stored bottom to top unless bit 5 of the image descriptor says otherwise, which is why a badly written reader shows TGAs upside down. RLE files are a series of packets: a byte whose top bit marks a run (one pixel repeated up to 128 times) or a raw stretch.
The low 4 bits of the descriptor give the number of alpha bits. When a 32-bit file declares 0, the fourth byte is ignored, as the format says. When it declares alpha but every alpha value is 0 (a common bug in exporters), the picture is shown opaque and the facts say so, rather than showing you an empty canvas.
EXR and HDR: exposure, curves and luminance
HDR pixels are linear light values that can go far above 1.0 (a sky can hold 50,000). To show them on an 8-bit screen the page multiplies by 2 to the power of the exposure, then either clamps at 1.0 or applies an ACES-like filmic curve (Krzysztof Narkowicz’s 2016 fit) that rolls highlights off instead of cutting them, then encodes for an sRGB display. Auto exposure puts the mean luminance at 18 % grey. Luminance is Y = 0.2126 R + 0.7152 G + 0.0722 B (Rec. 709 primaries); NaN and infinite pixels are counted and left out of the minimum, maximum and mean.
A Radiance .hdr stores each pixel as three 8-bit mantissas sharing one exponent (RGBE), a quarter of the size of 32-bit floats but only about 2 significant digits per pixel. Its EXPOSURE= line records a factor the values were already multiplied by; it is reported, not undone. An OpenEXR keeps 16- or 32-bit floats per channel: PIZ (wavelet) and ZIP are lossless, PXR24, B44 and DWA are lossy.
What it cannot do
- KTX, KTX2 and Basis Universal files are named, not shown. The page recognises KTX and KTX2 and says what they are; it does not transcode Basis (ETC1S or UASTC) supercompressed textures.
- ASTC, ETC, PVRTC and ATC (mobile GPU formats) are named, not decoded, inside a DDS or as their own files, and so are video (YUV) surfaces, bump maps and integer (UINT and SINT) formats.
- No editing and no re-encoding. It does not compress to BCn, write a DDS or build mips; Save as PNG writes an 8-bit PNG of the current view only, so HDR detail outside the exposure is lost in the saved file.
- No exact colour management. sRGB and linear textures are shown as their bytes say; ICC profiles, EXR chromaticities and white points are reported, not applied. Premultiplied alpha is shown as stored.
- EXR limits. Deep EXR files and ripmap-tiled files are not decoded (their headers are), a multi-part file shows its first part, only the data window is drawn, and channel layers beyond R, G, B, A and Y are not shown.
- Very large textures depend on memory. A 16384 × 16384 float picture needs about 4 GB in the tab; a phone will refuse it long before that.
- HDR with unusual scanline order. Only the usual “-Y height +X width” Radiance layout is decoded; the XYZE variant is not.