TinyEXR.NET is a pure C# port library of tinyexr
The target frameworks are net8.0, netstandard2.1
TinyEXR.NET can be found on NuGet (← click it !)
The net8.0 target has no additional runtime dependencies.
The netstandard2.1 target depends on SharpZipLib.
- full NativeAOT support!
- Single-part EXR read/write for scanline images.
- Single-part EXR read/write for tiled images, including one-level tiles and multi-resolution mipmap/ripmap layouts.
- Multipart image EXR parse/load/save for image parts.
- Deep single-part scanline EXR load through
LoadDeepEXR. - Regular image compression support for
NONE,RLE,ZIP,ZIPS,PIZ,PXR24,B44, andB44A. - Deep scanline compression support for
NONE,RLE,ZIPS, andZIP. - Layer- and multiview-aware helpers such as
EXRLayersandLoadEXRWithLayer, including RGBA expansion for subsampled channels in the convenience load path. - Managed header/image models that preserve EXR metadata needed by tools and inspectors, including data/display windows, tile descriptions, custom attributes, channel sampling, line order, and long names.
- Full image decode for mixed multipart files that include deep or non-image parts. Current behavior is metadata-only for those parts.
TinyEXR.NET keeps its public API almost identical to tinyexr v1, so most functions and data structures can be mapped directly from the original library. The main differences are a small number of C#-oriented interfaces designed to avoid raw pointer-based usage and provide a more natural managed API surface.
Example:
ResultCode load = Exr.LoadEXR(inputPath, out float[] rgba, out int width, out int height);
if (load != ResultCode.Success)
{
throw new InvalidOperationException($"LoadEXR failed: {load}");
}The repository currently includes TinyEXR.Viewer, an Avalonia sample built on top of TinyEXR.NET.
The viewer is intended for manual EXR inspection: it can open EXR files from the file picker, drag and drop, or a command-line path, preview single-part images and pure-image multipart files, switch between parts/layers/levels when decoded image data is available, and display metadata such as version flags, windows, tile information, channels, custom attributes, and deep-image statistics.
See Samples/TinyEXR.Viewer/README.md for run instructions and the current feature boundaries.
The current test suite covers the main supported surface of the library across both target outputs: the default target path and the netstandard2.1 fallback path run the same shared test cases.
See Test/README.md for the current test layout and execution details.
The repository includes memory-only benchmarks for the main read/write paths. Sample files are loaded during setup, so the timed results reflect decode/encode work on in-memory buffers rather than filesystem IO.
Updated on 2026-05-03. C# results use BenchmarkDotNet Mean; C++ baseline results use the Google Benchmark CPU column.
- CPU:
13th Gen Intel Core i7-13700K 3.40GHz - OS:
Windows 11 25H2 10.0.26200.8246 - .NET SDK/runtime:
10.0.203/10.0.7 - C# benchmark:
BenchmarkDotNet 0.15.8, default job, workstation GC - C++ compiler:
MSVC 19.50.35730,Visual Studio 2026 18.5.2
| Method | Sample | C# mean | C# allocated | C++ baseline | Managed / baseline |
|---|---|---|---|---|---|
LoadEXRFromMemory |
desk_scanline |
40.05 ms |
15.73 MB |
38.65 ms |
1.04x |
SaveEXRToMemory |
desk_scanline |
108.77 ms |
46.56 MB |
164.06 ms |
0.66x |
LoadEXRImageFromMemory |
desk_scanline |
23.43 ms |
7.15 MB |
28.65 ms |
0.82x |
SaveEXRImageToMemory |
desk_scanline |
43.48 ms |
80.90 MB |
41.36 ms |
1.05x |
LoadEXRImageFromMemory |
kapaa_multires |
42.94 ms |
21.27 MB |
55.40 ms |
0.78x |
SaveEXRImageToMemory |
kapaa_multires |
169.49 ms |
53.54 MB |
213.54 ms |
0.79x |
LoadEXRMultipartImageFromMemory |
beachball_multipart_0001 |
82.74 ms |
30.65 MB |
127.60 ms |
0.65x |
SaveEXRMultipartImageToMemory |
beachball_multipart_0001 |
213.06 ms |
78.32 MB |
223.96 ms |
0.95x |
LoadDeepImageFromMemory |
balls_deep_scanline |
14.19 ms |
5.47 MB |
N/A |
N/A |
See Benchmark/README.md for more details.
Starting with v1.0, TinyEXR.NET is a pure C# implementation of the tinyexr-compatible API surface.
The legacy v0.3.x line is kept as a maintenance branch. It may continue to receive compatibility fixes and follow tinyexr updates when needed, but no new features will be added to v0.3.x.
The main branch moves forward with v1.0+.
For new development, prefer the mainline v1.0+ branch. Use the v0.3.x maintenance branch only if you need the legacy native-wrapper line for compatibility reasons.
- High-level RGBA helpers such as
LoadEXR,LoadEXRFromMemory,SaveEXR,SaveEXRToMemory,LoadEXRWithLayer, andEXRLayersare still the recommended entry points, so code that only uses these helpers usually needs little or no change. IsExrandIsExrFromMemoryare nowIsEXRandIsEXRFromMemory.TinyEXR.Native.*andTinyEXR.Native.EXRNativeare gone. The library is now a pure managed C# implementation, so the old native-runtime, P/Invoke, and static-link workflow fromv0.3.xno longer applies.- Native-style structs are replaced by managed types such as
ExrVersion,ExrHeader,ExrImage,ExrMultipartHeader,ExrMultipartImage,ExrDeepImage, andExrBox2i. - Low-level read/write calls are now managed
out-based APIs instead ofref-based native mutation. For example,ParseEXRHeaderFromFile(path, ref version, ref header)becomesParseEXRHeaderFromFile(path, out ExrVersion version, out ExrHeader header), andLoadEXRImageFromFile(ref image, ref header, path)becomesLoadEXRImageFromFile(path, header, out ExrImage image). SaveEXRImageToMemoryalso changed shape:v0.3.xreturnedbyte[]?, while the current API returnsResultCodeand writes the payload toout byte[] encoded.
Mixed multipart files that include deep or non-image parts are currently metadata-only for those parts; full image decode is supported for image parts.
TinyEXR.NET is under MIT license