HDRLib 1.0.1
dotnet add package HDRLib --version 1.0.1
NuGet\Install-Package HDRLib -Version 1.0.1
<PackageReference Include="HDRLib" Version="1.0.1" />
<PackageVersion Include="HDRLib" Version="1.0.1" />
<PackageReference Include="HDRLib" />
paket add HDRLib --version 1.0.1
#r "nuget: HDRLib, 1.0.1"
#:package HDRLib@1.0.1
#addin nuget:?package=HDRLib&version=1.0.1
#tool nuget:?package=HDRLib&version=1.0.1
HDRLib

HDRLib is a .NET 8 library for merging exposure brackets into display-ready high-dynamic-range images and for applying the same tone-mapping pipeline to a single image. It combines automatic AVX2 SIMD acceleration on supported CPUs with an explicit ILGPU path for compatible accelerators.
- Debevec-style camera response recovery and radiance-map construction
- Pyramid image alignment before exposure merging
- Motion masking to reduce ghosts in moving regions
- Natural, ACES Filmic, brightness-balancing, and contrast-balancing tone mappers
- Automatic AVX2 selection with a scalar/parallel CPU fallback
- Explicit GPU execution through ILGPU
- JPEG/PNG image I/O and EXIF exposure metadata through ImageSharp
Source, issues, and releases: github.com/staszx/HDRLib
Install
dotnet add package HDRLib --version 1.0.1
The package targets net8.0 and contains both HDRLib.dll and the
HDRLib.PixelProvider.ImageSharp.dll image provider used below.
How the HDR algorithm works
HDR processing starts with two or more photographs of the same scene at different exposure times:
- Load exposure data. The ImageSharp provider reads RGB pixels and EXIF exposure metadata. Accurate exposure times are important for radiance recovery.
- Align the bracket. A coarse-to-fine image pyramid estimates the movement between frames and brings them into a common coordinate system.
- Detect movement. A motion mask identifies regions that do not agree across the bracket so moving subjects contribute less to the merge.
- Recover the camera response. Stratified samples across the luminance range are used to solve a smooth Debevec response curve for each RGB channel.
- Build the radiance map. Well-exposed samples receive more weight than clipped shadows or highlights. The weighted values are combined into a floating-point scene-radiance image.
- Normalize and tone-map. The HDR values are normalized and passed through the selected tone mapper, producing an ordinary image that retains useful highlight and shadow detail.
SampleCount controls the number of points used to estimate the response curve.
SmoothFactor regularizes that curve. MotionFilterStrength controls motion-mask
sensitivity from 0 (disabled) to 100; it is not a generic sharpening control.
Tone mappers
HDRLib includes four tone mappers:
NaturalToneMapperSettingsprovides adaptive photographic compression with configurable target gray, white point, and tonal-range compression.AcesFilmicTonemapperSettingsapplies an ACES-style fitted filmic curve.ContrastBalancerToneMapperSettingsbalances scene contrast with independent compression, lighting, luminance, and clipping controls.BrightnessBalancerToneMapperSettingsbalances overall scene brightness with lighting and brightness-boost controls.
All four support the scalar CPU, AVX2 SIMD, and explicit ILGPU processing paths.
For a merged HDR bracket, the tone mapper receives floating-point scene radiance,
which can be far above the display range of 0..1. HDRLib normalizes that
radiance using the bracket's measured scene brightness before display mapping.
Automatic white balance preserves the HDR range and is applied consistently
before tone mapping on every backend.
SINGLE processing keeps its existing behavior: input is an ordinary display-range image, so tone mapping adjusts its appearance but does not reconstruct scene dynamic range that is absent from the source.
What changed in 1.0.1
- Fixed flat gray ContrastBalancer output on HDR brackets with automatic white balance enabled.
- Fixed fully overexposed BrightnessBalancer output on high-scale HDR radiance.
- Prevented white balance from clipping HDR channel values to
1.0before tone mapping. - Made white-balance ordering and calculations consistent across CPU, AVX2 SIMD, and ILGPU implementations; invalid non-finite samples are excluded from automatic white-balance statistics.
- Added CPU/SIMD/GPU regression coverage for Natural, ACES Filmic, ContrastBalancer, and BrightnessBalancer on large-range HDR input.
Hardware acceleration
The default CPU path uses Parallel.For. With
SystemHelper.UseAvxState = UseAvxState.Auto (the default), HDRLib selects its
AVX2 implementation when Avx2.IsSupported; otherwise it uses the scalar CPU
implementation. Keep Auto unless you are deliberately testing a particular
path—forcing SIMD on unsupported hardware is invalid.
GPU execution is explicit: create one GpuContext and pass it to the aligner,
HDR processor, or single-image processor. Reuse the context across images so
ILGPU kernels and accelerator resources are not recreated for every file. ILGPU
enumerates the accelerators available through its installed backends; actual GPU
support depends on the machine, driver, and backend.
Strong naming and GPU acceleration are independent: the NuGet assemblies have
public key token eaeefe50e84677d9; strong naming provides assembly identity,
not publisher authentication or NuGet repository signing.
HDR example: automatic CPU/SIMD selection
using HDRLib;
using HDRLib.Align;
using HDRLib.Hdr.Debevec;
using HDRLib.Interfaces;
using HDRLib.PixelProvider.ImageSharp;
using HDRLib.ToneMapping.Settings;
SystemHelper.UseAvxState = UseAvxState.Auto;
var exposures = new List<IImageProxy>();
try
{
foreach (var path in new[] { "scene-2ev.jpg", "scene-0ev.jpg", "scene+2ev.jpg" })
{
var image = new ImageSharpProxy();
image.Load(path);
exposures.Add(image);
}
ImageAligner.Create().Process(exposures);
var processor = new HDRProcessor<ImageSharpProxy>();
using var output = processor.Process(exposures, new HdrImageOptions
{
SampleCount = 1_000,
SmoothFactor = 300,
MotionFilterStrength = 80,
ToneMapperSettings = new NaturalToneMapperSettings
{
AutoAdjustEnabled = true,
Gamma = 1f
}
});
output.SaveAsJpeg("scene-hdr.jpg");
}
finally
{
foreach (var image in exposures)
image.Dispose();
}
HDR example: GPU alignment and merge
using HDRLib;
using HDRLib.Align;
using HDRLib.Gpu;
using HDRLib.Hdr.Debevec;
using HDRLib.Interfaces;
using HDRLib.PixelProvider.ImageSharp;
using HDRLib.ToneMapping.Settings;
using var gpu = new GpuContext(); // preferred accelerator
var exposures = new List<IImageProxy>();
try
{
foreach (var path in new[] { "room-dark.jpg", "room-mid.jpg", "room-light.jpg" })
{
var image = new ImageSharpProxy();
image.Load(path);
exposures.Add(image);
}
ImageAligner.Create(gpu).Process(exposures);
var processor = new HDRProcessor<ImageSharpProxy>(gpu);
using var output = processor.Process(exposures, new HdrImageOptions
{
SampleCount = 1_500,
SmoothFactor = 400,
MotionFilterStrength = 70,
ToneMapperSettings = new NaturalToneMapperSettings
{
AutoAdjustEnabled = true,
Contrast = 1.1f,
Gamma = 1f
}
});
output.SaveAsJpeg("room-hdr-gpu.jpg");
}
finally
{
foreach (var image in exposures)
image.Dispose();
}
If the default accelerator is not the one you want, inspect
GpuContext.GetAccelerators() and pass its zero-based index to
new GpuContext(index).
SINGLE example: automatic CPU/SIMD tone mapping
SINGLE processing does not create new scene dynamic range. It applies HDRLib's tone-mapping and post-processing operators to one ordinary image.
using HDRLib;
using HDRLib.Hdr.Debevec;
using HDRLib.PixelProvider.ImageSharp;
using HDRLib.ToneMapping.Settings;
SystemHelper.UseAvxState = UseAvxState.Auto;
using var source = new ImageSharpProxy();
source.Load("portrait.jpg");
using var processor = new SingleImageProcessor(source);
processor.Process(new NaturalToneMapperSettings
{
AutoAdjustEnabled = true,
ExposureEV = 0.25f,
Contrast = 1.1f,
Saturation = 5f,
Gamma = 1f
});
using var output = processor.ToImage<ImageSharpProxy>();
output.SaveAsJpeg("portrait-tonemapped.jpg");
SINGLE example: reusable GPU processor
using HDRLib.Gpu;
using HDRLib.Hdr.Debevec;
using HDRLib.PixelProvider.ImageSharp;
using HDRLib.ToneMapping.Settings;
using var gpu = new GpuContext();
using var processor = new SingleImageProcessor(gpu);
var settings = new AcesFilmicTonemapperSettings
{
AutoAdjustEnabled = true,
ExposureEV = 0.2f,
Saturation = 4f
};
foreach (var path in Directory.EnumerateFiles("input", "*.jpg"))
{
using var source = new ImageSharpProxy();
source.Load(path);
processor.LoadSource(source);
processor.Process(settings);
using var output = processor.ToImage<ImageSharpProxy>();
output.SaveAsJpeg(Path.Combine("output", Path.GetFileName(path)));
}
Licensing
HDRLib is available under AGPL-3.0-or-later. A separate commercial license is required when you cannot or do not want to comply with the AGPL obligations. See LICENSE.
HDRLib also depends on projects with their own terms. In particular, ImageSharp 3.1.11 uses the Six Labors Split License rather than Apache-2.0 and may require a Six Labors commercial license in some closed-source commercial scenarios. Review THIRD-PARTY-NOTICES.md before distribution.
Build and pack
dotnet test HDRLib.sln -c Release
.\pack.ps1 -Configuration Release
The package and symbols package are written to artifacts/. Both library
assemblies are strong-name signed from HDRLib.snk.
The four snippets above are also available as a buildable console project in
samples/HDRLib.Examples.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- ILGPU (>= 1.5.3)
- ILGPU.Algorithms (>= 1.5.3)
- MetadataExtractor (>= 2.8.1)
- SixLabors.ImageSharp (>= 3.1.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Fix HDR radiance-scale handling in ContrastBalancer and BrightnessBalancer; preserve HDR values during automatic white balance; align white-balance behavior across CPU, AVX2 SIMD, and ILGPU backends; add cross-backend HDR regression coverage for all tone mappers.