The basics
What is an EXR file?
An EXR file stores an image as numbers that describe light, not as colours ready for a screen. Industrial Light & Magic developed the format in 1999 because its own file format held 8 bits per channel, too few for visual effects work, where images are brightened, darkened and combined many times over. ILM released OpenEXR as open source in 2003, it became a project of the Academy Software Foundation in 2019, and it's now the standard interchange format for rendered and composited images in film, TV and animation.
Where a PNG or JPG stops at white, an EXR pixel can be 0.001 or 500. That lets a compositor change the exposure, add motion blur or glow, or grade the colours long after rendering, without running out of detail at either end. A single file can also hold many images at once: the beauty render plus separate passes for lighting, reflections, depth or object IDs.
Three things an EXR file is not:
- Not a finished picture. An EXR is a working file. Its values are meant to be converted for a particular display, so it can look wrong when opened as-is (see below).
- Not a web format. No browser displays EXR, and the files are large. Export a JPG or PNG to show the result.
- Not the same as an "HDR photo" from a phone. Those are JPEG or HEIC files made for HDR screens. Radiance HDR files are a different, older high-dynamic-range format.
Anatomy
What's inside an EXR file
An EXR file is a magic number, a version field, a header made of named attributes, an offset table, and then the pixels in chunks. All numbers are little-endian. Below is the whole structure of a 370-byte file we made for this page with the OpenEXR Python library: 2 pixels, red, green and blue as half floats, no compression. The first pixel is (1.0, 0.5, 0.25); the second is brighter, (4.0, 2.0, 0.5). It isn't offered for download; the layout follows the OpenEXR File Layout specification.
tiny.exr: 2 × 1 pixels, half-float R, G, B, no compression
offset bytes part
000000 76 2F 31 01 magic number
000004 02 00 00 00 version 2, no flags
000008 channels\0 chlist\0 37 00 00 00 attribute: name, type, size 55
B\0 01 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00
G\0 01 00 00 00 … type 1 = HALF, sampling 1 × 1
R\0 01 00 00 00 …
00 end of the channel list
000053 compression\0 compression\0 … 00 0 = no compression
000070 dataWindow\0 box2i\0 … (0, 0) to (1, 0): stored pixels
000095 displayWindow\0 box2i\0 … (0, 0) to (1, 0): the frame
0000BD lineOrder\0 lineOrder\0 … 00 increasing y: top to bottom
0000D6 pixelAspectRatio\0 float\0 … 1.0 (00 00 80 3F)
0000F5 screenWindowCenter\0 v2f\0 … 0, 0
000118 screenWindowWidth\0 float\0 … 1.0
000138 type\0 string\0 … scanlineimage optional in a single-part file
000155 00 end of the header
000156 5E 01 00 00 00 00 00 00 offset table: chunk 0 at byte 350
00015E 00 00 00 00 chunk: y = 0
000162 0C 00 00 00 12 bytes of pixel data follow
000166 00 34 00 38 B: 0.25, 0.5
00016A 00 38 00 40 G: 0.5, 2.0
00016E 00 3C 00 44 R: 1.0, 4.0
end of file at 370 bytes- 1
76 2F 31 01The magic number
Every OpenEXR file starts with these four bytes, the integer 20000630 stored little-endian. In ASCII they read
v/1and a control character. - 2
02 00 00 00Version and flags
The first byte is the format version, 2. The other three bytes are flags: bit 9 marks a single-part tiled file, bit 10 long attribute names (up to 255 bytes instead of 31), bit 11 deep data and bit 12 a multi-part file. All zero here: a plain single-part image stored in scan lines.
- 3
channels\0 chlist\0 37 00 00 00A header attribute
The header is a list of attributes, each a null-terminated name, a null-terminated type, a 4-byte size and the value. This one is the channel list, 55 bytes long. Readers skip attributes they don't know, so software can add its own metadata.
- 4
B\0 01 00 00 00 …Channels and pixel types
Each channel has a name, a pixel type (0 = 32-bit unsigned integer, 1 = 16-bit half float, 2 = 32-bit float), a linear-perception hint and its sampling rate. The list is sorted by name, which is why blue comes first.
- 5
compression\0 … 00Compression
One byte. 0 means none; 3 would be ZIP, 4 PIZ, 9 DWAB. The compression method also sets how many scan lines go in each chunk: 1 without compression, 16 for ZIP, 32 for PIZ, 256 for DWAB.
- 6
dataWindow, displayWindowTwo rectangles
The display window is the frame of the picture; the data window is the area that actually has pixels. They're the same here, but the data window can be smaller (a render of just the part that changed) or larger (overscan, extra pixels outside the frame for later reframing or effects).
- 7
lineOrder … screenWindowWidthThe other required attributes
Every EXR must have eight:
channels,compression,dataWindow,displayWindow,lineOrder,pixelAspectRatio,screenWindowCenterandscreenWindowWidth. Multi-part and deep files also neednameandtype. A single null byte ends the header. - 8
5E 01 00 00 00 00 00 00The offset table
One 8-byte offset per chunk, so a reader can jump straight to any scan line block (or tile) without reading the ones before it. Our only chunk starts at byte 350 (
0x15E). - 9
00 00 00 00 0C 00 00 00A chunk
Each chunk starts with the y coordinate of its first scan line and the size of its data. With compression, the chunk holds the compressed data, or the raw data if compressing didn't make it smaller.
- 10
00 34 00 38 …The pixels, one channel at a time
Within a scan line, all of one channel's values come first, then the next channel's, in name order: blue
3400(0.25) and3800(0.5), green3800and4000(2.0), red3C00(1.0) and4400(4.0). The 4.0 is stored as easily as the 1.0: there's no ceiling at white.
Under the hood
Half floats and scene-linear light
Most EXR files store each channel as a half: a 16-bit floating-point number with 1 sign bit, 5 exponent bits and 10 fraction bits. A half can hold values from about 0.00006 up to 65,504, and every doubling of brightness gets 1,024 steps. For comparison, an 8-bit sRGB image has 256 levels in total. Halves take half the space of 32-bit floats and are precise enough for colour, so 32-bit float is kept for data such as depth or positions.
| Type | Bits | Typical use |
|---|---|---|
| HALF (1) | 16-bit float | Colour and alpha: renders, scans, composites |
| FLOAT (2) | 32-bit float | Depth (Z), world positions, motion vectors, anything needing more range or precision |
| UINT (0) | 32-bit unsigned integer | Object or material IDs used to select parts of a render |
The values are usually scene-linear: proportional to the amount of light in the scene. Twice the light gives twice the number. A mid-grey card might be about 0.18 and a lamp 50 or more. A screen can't show that directly; software has to apply a view transform (an sRGB curve, a film-like tone curve, or an ACES output transform) to turn light into display colours.
Channels have names, not fixed positions. R, G, B and A are the main image; render passes are named with a prefix, such as diffuse.R or specular.G, and grouped into layers by applications. That's what people mean by a multilayer EXR.
Variants
Scan lines, tiles, multi-part and deep images
The flags in the version field say which kind of EXR a file is. Readers that only handle the first kind are still common, which explains many "can't open" errors.
| Kind | Since | What it's for |
|---|---|---|
| Scan-line image | The original format | Pixels in blocks of rows. The most widely supported kind. |
| Tiled image | An early update | Pixels in rectangular tiles, optionally with mipmaps or ripmaps (smaller copies of the image). Lets a renderer read only the part of a huge texture it needs. |
| Multi-part file | OpenEXR 2.0 (2013) | Several images, called parts, in one file, each with its own header and possibly its own size and compression. Used for render passes and for stereo left and right views. |
| Deep image | OpenEXR 2.0 (2013) | Each pixel holds a list of samples at different depths instead of one value. Compositors use it to merge separately rendered elements, such as smoke and a character, without edge artefacts. |
Multi-part files differ from a multilayer single-part file: a single-part file can hold dozens of channels, but every channel must be read together. Parts can be read one at a time, which saves time when a compositor needs only the beauty pass.
Compression
EXR compression methods
Every part of an EXR names one compression method. Some are lossless, some lossy, and they differ a lot in speed and file size. The number in brackets is the value stored in the compression attribute.
| Method | Lossless? | Rows per chunk | Notes |
|---|---|---|---|
| None (0) | Yes | 1 | Raw values. Biggest files, fastest to read. |
| RLE (1) | Yes | 1 | Run-length encoding. Only helps on flat areas. |
| ZIPS (2), ZIP (3) | Yes | 1 or 16 | Deflate, as in ZIP files. A common choice for renders. |
| PIZ (4) | Yes | 32 | Wavelet and Huffman coding; good on grainy images such as film scans. |
| PXR24 (5) | Lossless for half and integer data | 16 | From Pixar. Rounds 32-bit floats to 24 bits, then deflates. |
| B44 (6), B44A (7) | No | 32 | Fixed-ratio compression of half channels, designed for real-time playback. B44A packs flat areas further. |
| DWAA (8), DWAB (9) | No | 32 or 256 | JPEG-like compression contributed by DreamWorks Animation. Much smaller files; popular for dailies and review. |
| HTJ2K32 (11), HTJ2K256 (10) | Yes | 32 or 256 | High-Throughput JPEG 2000, added in OpenEXR 3.4 (September 2025). |
OpenEXR 3.5, released in September 2026, added lossless Zstandard compression and a lossy method based on HTJ2K. The OpenEXR project notes that files with lossy HTJ2K written by versions 3.5.0 and 3.5.1 lack a lookup table that 3.5.2 adds, and recommends regenerating them.
Newer compression, older software
Files written with OpenEXR 3.4 stay readable by older software unless they use the new HTJ2K methods. An application built on an older OpenEXR library can't decode a compression method it doesn't know, so for files you send to other studios or tools, stick to ZIP, PIZ or DWAA/DWAB unless you know the receiver's software is up to date.
Colour
Colour spaces and ACES
An EXR stores numbers, and the file doesn't force a meaning on them. Most EXRs hold scene-linear values with the same red, green and blue primaries as sRGB (often called linear Rec.709), but the same structure can hold ACES colour, camera log footage, depth in metres or anything else. An optional chromaticities attribute can record the primaries; many files leave it out, and studios rely on naming conventions and colour management (usually OpenColorIO) instead.
ACES, the Academy Color Encoding System used for film and TV mastering, defines an archive and interchange file based on EXR: the ACES image container (SMPTE ST 2065-4). It's a constrained EXR, registered as image/aces with the extension .exr. According to its IANA registration it is uncompressed and starts with 76 2F 31 01 02 00 00 00 or 76 2F 31 01 02 04 00 00, and an acesImageContainerFlag attribute is set to 1. Its values are linear ACES2065-1, a colour space with very wide primaries.
| Content | Typical values | Shown without conversion, it looks… |
|---|---|---|
| Scene-linear, sRGB/Rec.709 primaries | Mid-grey about 0.18, highlights above 1 | Too dark and contrasty; highlights clip to white |
| ACES2065-1 or ACEScg (linear) | As above, wider gamut | Dark and desaturated |
| Camera log or ACEScct | Mostly between 0 and 1 | Flat, grey and washed out |
| Data passes (depth, positions, IDs) | Any range, often huge | White, black or random colours: it's not a picture |
Troubleshooting
Why an EXR looks dark, washed out or black
- It looks too dark, with harsh contrast. The viewer showed linear values as if they were display values. A mid-grey of 0.18 should appear at about 46% brightness (118 out of 255) after the sRGB curve, but without it, it's shown at 18%. Use a viewer that applies a view transform, set the image's colour space to linear in your application, or convert with a colour-managed tool.
- It looks flat and washed out. The file probably holds log-encoded footage (ACEScct, LogC and similar), or a program applied an sRGB curve to values that already had one. Tell the application the correct input colour space.
- Colours look dull. ACES2065-1 values are being read as sRGB primaries. Set the input to ACES2065-1 (or ACEScg, if that's what the renderer wrote).
- Highlights are a flat white. Values above 1.0 clip on a normal screen. Lower the exposure in the viewer, or apply a tone curve, to see the detail that's there.
- The image is black or transparent. Possible causes: an alpha of 0 with premultiplied colour, a data window that doesn't overlap the display window, or the viewer showing a data pass or the wrong part of a multi-part file. List what's inside with
oiiotool --info -v file.exr(OpenImageIO) orexrheader file.exr(from OpenEXR's tools). - It won't open at all. The application may not support deep data, multi-part files, tiles or a newer compression method such as HTJ2K. Re-save it from a current tool as a single-part scan-line file with ZIP compression.
How to
How to open, edit and convert an EXR file
- Compositing and editing: Nuke, DaVinci Resolve, After Effects and Blender's compositor read EXR with all its layers.
- Painting and retouching: Photoshop opens EXR in 32-bit mode; layered EXRs need a plug-in such as EXR-IO to come in as separate layers. Krita, Affinity Photo and GIMP (since 2.10) also open EXR files.
- Rendering: Blender, Houdini, Maya, 3ds Max and most renderers write EXR, including multilayer files with every render pass.
- Just looking: free HDR viewers such as tev show EXRs with exposure control and let you flip through channels.
To turn an EXR into an ordinary picture, apply a view transform first, so that it looks the way it did in the application. On the command line, OpenImageIO (pip install OpenImageIO) can do it:
# inspect: size, channels, compression, metadata
oiiotool --info -v render.exr
# linear EXR to an 8-bit sRGB PNG (values above 1.0 clip)
oiiotool render.exr --tocolorspace sRGB -d uint8 -o render.png
# a PNG or JPEG into a linear half-float EXR
oiiotool photo.png --colorconvert sRGB linear -d half -o photo.exrConverting a photo to EXR doesn't add dynamic range: the highlights a JPEG clipped stay clipped. Real HDR content comes from renders, RAW photos, bracketed exposures merged together or cinema cameras.
Security
Is an EXR file safe to open?
EXR files contain no scripts or macros. The risks are those of any complex binary format:
- Parser bugs. The OpenEXR library is continuously fuzz-tested, and its releases regularly fix memory-safety bugs found that way; version 3.5.0 alone fixed four. Keep applications and libraries that read EXR up to date, especially on servers that process uploads.
- Huge declared sizes. A small file can declare an enormous data window or many channels. Check the dimensions and channel count before decoding uploaded files.
- Metadata travels along. The header can hold any attribute. Renderers and compositors often add their own, which can include file paths, machine names, project names or the software that made it. Check with
oiiotool --info -vbefore sending files outside your organisation.
Sample files
There are no sample EXR files on this page yet. To make one for testing, run oiiotool input.png --colorconvert sRGB linear -d half -o output.exr with OpenImageIO (pip install OpenImageIO), or render or save one from Blender or Krita.
Put it online
Have an EXR file? Give it a link.
Drop an OpenEXR image on 99helpers and it gets its own web address. Browsers can't display EXR, so anyone who opens the link downloads the file to view it in their own software; add a JPG or PNG preview if people just need to see it.
Questions
OpenEXR files, frequently asked
What is an EXR file?
An OpenEXR image: a high-dynamic-range format from Industrial Light & Magic that stores light values as 16- or 32-bit floating-point numbers. It's the standard file format for renders and visual effects work.
How do I open an EXR file?
Use an application that understands floating-point images: Blender, Nuke, DaVinci Resolve, Photoshop, Krita, GIMP or Affinity Photo, or a free HDR viewer such as tev. Browsers and most basic photo viewers can't open EXR.
Why does my EXR look so dark?
Its values are scene-linear and the viewer is showing them without a view transform. Set the colour space to linear in your application, or convert with a colour-managed tool, and it will look as intended.
How do I convert EXR to JPG or PNG?
Open it in Photoshop, GIMP, Krita or Blender and export, or run oiiotool input.exr --tocolorspace sRGB -d uint8 -o output.png. Adjust the exposure first if bright areas clip to white.
Is EXR lossless?
It can be. None, RLE, ZIP, ZIPS, PIZ and HTJ2K are lossless; PXR24 is lossless for half-float data; B44, B44A and DWAA/DWAB are lossy. The file's compression attribute says which one it uses.
What is a multilayer EXR?
An EXR with more channels than R, G, B and A, named in groups such as diffuse.R or depth.Z. Renderers write each render pass as a layer so a compositor can adjust them separately.
What's the difference between EXR and HDR?
Both store high dynamic range. Radiance HDR packs each pixel into 4 bytes with a shared exponent, has no alpha and only basic compression. EXR has half or full floats per channel, any number of channels, alpha, layers and many compression methods.
Why are EXR files so big?
Each pixel holds several 16- or 32-bit channels, often with many render passes, and the usual compression is lossless. DWAA or DWAB compression makes much smaller files when exact values aren't needed.
Related formats
Other file types explained
Keep going
Related
Sources
- OpenEXR: File Layout specification
- OpenEXR: News and release notes
- OpenEXR: About OpenEXR
- Library of Congress: OpenEXR format description
- Academy Software Foundation: OpenEXR origin story
- IANA: image/aces media type registration
Last reviewed 27 October 2026.