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

  1. Reduce the image width (crop, downscale, or tile the image) before EXR export.
  2. Choose a compression type with fewer rows per block to shrink bytesPerBlock.
  3. 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

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


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)