SixLabors/ImageSharp · error · ImageFormatException
Image is too large to encode in EXR format.
Error message
Image is too large to encode in EXR format.
What it means
The EXR encoder buffers one block of rows and one row of pixel data in memory, so both the bytes-per-row (kept in a uint-backed calculation) and the bytes-per-compression-block (allocated as an int-sized buffer) must fit within 32-bit limits. Images whose width × channels × 4 bytes exceed those bounds throw ImageFormatException because EXR encoding cannot proceed safely on this code path.
Solutions
- Reduce the image width (crop, downscale, or tile the image) before EXR export.
- Choose a compression type with fewer rows per block to shrink bytesPerBlock.
- Reduce channel count (e.g. drop alpha or unused channels) to lower bytes per row.
Example fix
// before
image.SaveAsExr(stream); // throws for ultra-wide images
// after
if ((ulong)(channels * image.Width * 4) <= uint.MaxValue) image.SaveAsExr(stream);
else { using Image tiled = image.Clone(ctx => ctx.Crop(tileWidth, image.Height)); tiled.SaveAsExr(stream); } Defensive patterns
Strategy: validation
Validate before calling
ulong bytesPerRow = (ulong)channels * (uint)image.Width * 4;
if (bytesPerRow > uint.MaxValue || bytesPerRow * rowsPerBlock > int.MaxValue)
throw new InvalidOperationException("Image too large for EXR encoding."); Try / catch
try { image.SaveAsExr(stream); }
catch (ImageFormatException) { /* tile the image or switch compression and retry */ } Prevention
- Check width × channels × 4 against uint.MaxValue before EXR export.
- Tile very wide images instead of encoding whole panoramas.
- Prefer compression types with moderate rows-per-block for wide images.
When it happens
Trigger: Calling SaveAsExr/EncodeAsExr with an image whose bytesPerRow (channels × width × 4) exceeds uint.MaxValue, or whose bytesPerRow × RowsPerBlock(compression) exceeds int.MaxValue — i.e. extremely wide images or huge widths combined with high rows-per-block compression settings.
Common situations: Encoding gigapixel panorama tiles or scientific float images with very large widths; picking a compression type that packs many rows per block (e.g. low-resolution variants) on wide images.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- No encoder was found for extension
- Not supported decoder compression method
- Unsupported EXR version
- Invalid EXR image header
- Not supported encoder compression method
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/d15eddb163969b96.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Exr/ExrEncoderCore.cs:178
/// <param name="compression">The compression to use.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The array of pixel row offsets.</returns>
private ulong[] EncodeFloatingPointPixelData<TPixel>(
Stream stream,
Buffer2D<TPixel> pixels,
int width,
int height,
List<ExrChannelInfo> channels,
ExrCompression compression,
CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
ulong bytesPerRow = ExrUtils.CalculateBytesPerRow(channels, (uint)width);
uint rowsPerBlock = ExrUtils.RowsPerBlock(compression);
ulong bytesPerBlock = bytesPerRow * rowsPerBlock;
if (bytesPerRow > uint.MaxValue || bytesPerBlock > int.MaxValue)
{
throw new ImageFormatException("Image is too large to encode in EXR format.");
}
using IMemoryOwner<float> rgbBuffer = this.memoryAllocator.Allocate<float>(width * 4, AllocationOptions.Clean);
using IMemoryOwner<byte> rowBlockBuffer = this.memoryAllocator.Allocate<byte>((int)bytesPerBlock, AllocationOptions.Clean);
Span<float> redBuffer = rgbBuffer.GetSpan()[..width];
Span<float> greenBuffer = rgbBuffer.GetSpan().Slice(width, width);
Span<float> blueBuffer = rgbBuffer.GetSpan().Slice(width * 2, width);
Span<float> alphaBuffer = rgbBuffer.GetSpan().Slice(width * 3, width);
using ExrBaseCompressor compressor = ExrCompressorFactory.Create(compression, this.memoryAllocator, stream, (uint)bytesPerBlock, (uint)bytesPerRow, rowsPerBlock, width);
ulong[] rowOffsets = new ulong[height];
for (uint y = 0; y < height; y += rowsPerBlock)
{
rowOffsets[y] = (ulong)stream.Position;
// Write row index.
BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, y);View on GitHub (pinned to 59ce6af6fc)