# TIFF Files Larger Than 2 GB in IronOCR
IronOCR loads image input into a single in-memory buffer through its internal `AnyBitmap` type. That buffer is indexed by a 32-bit integer, so it caps at roughly 2 GB regardless of available system memory. A TIFF file larger than 2 GB exceeds this limit and fails to load.
The failure is quiet rather than loud:
```txt
Loaded pages: 0
```
`OcrInput.LoadImage(filePath)` creates an `AnyBitmap` internally and materializes the whole image into one buffer. Because that buffer is indexed by `int`, it is effectively limited to about 2 GB no matter how much memory the machine has, so a TIFF slightly over that limit cannot be held. `LoadImage(filePath)` currently returns zero loaded pages instead of throwing a clear exception; this silent failure is a known issue, and a clearer exception is planned. The single-buffer design is an architectural limit, and native per-page TIFF streaming, which would avoid buffering the whole file, is not yet available.
This affects `2026.5.2`. The limit is a runtime constraint, not OS-specific, so it applies across platforms on .NET.
## Solution
Split the TIFF into sub-2 GB chunks and pass each chunk to IronOCR as a byte array.
### 1. Add Magick.NET
Bring in Magick.NET so you can split the TIFF before handing it to IronOCR. Pick the variant that matches your project (Q8/Q16, AnyCPU/x64).
```bash
dotnet add package Magick.NET-Q16-AnyCPU
```
### 2. Split by Page Count and Load as Bytes
Open the TIFF as a `MagickImageCollection`, break it into page-count chunks that each stay under 2 GB, convert each chunk to a byte array, and load it with `OcrInput.LoadImage(byte[])` rather than the file path.
```csharp
var inputPath = "input.tiff";
var pagesPerChunk = 100;
using var allPages = new MagickImageCollection(inputPath);
int chunkNumber = 1;
for (int i = 0; i < allPages.Count; i += pagesPerChunk)
{
using var chunk = new MagickImageCollection();
for (int j = i; j < Math.Min(i + pagesPerChunk, allPages.Count); j++)
{
chunk.Add(allPages[j].Clone());
}
foreach (var image in chunk)
{
image.SetCompression(CompressionMethod.LZW);
}
var chunkBytes = chunk.ToByteArray();
using (var ocrInput = new OcrInput())
{
ocrInput.LoadImage(chunkBytes);
var pages = ocrInput.GetPages().ToList();
Console.WriteLine($"Loaded pages: {pages.Count}");
var result = new IronTesseract().Read(ocrInput);
Console.WriteLine("OCR Text Length: " + (result.Text?.Length ?? 0));
}
Console.WriteLine($"Chunk {chunkNumber} processed");
chunkNumber++;
}
```
Each chunk is a fresh `MagickImageCollection` cloned from the source pages, re-compressed with `CompressionMethod.LZW`, then serialized with `ToByteArray()` and passed to `OcrInput.LoadImage(byte[])`. Keeping the byte payload under 2 GB is what sidesteps the buffer limit.
### 3. Tune `pagesPerChunk`
Adjust `pagesPerChunk` for your data. Lower it if a chunk approaches 2 GB or if memory is tight; raise it for smaller pages to cut down on overhead.
### 4. Account for Magick.NET in Deployment
Magick.NET ships ImageMagick native binaries. Those add to package size and bring a native dependency footprint, so factor them into your deployment.
IronOCR loads image input into a single in-memory buffer through its internal AnyBitmap type. That buffer is indexed by a 32-bit integer, so it caps at roughly 2 GB regardless of available system memory. A TIFF file larger than 2 GB exceeds this limit and fails to load.
The failure is quiet rather than loud:
Loaded pages: 0
Loaded pages: 0
Text
OcrInput.LoadImage(filePath) creates an AnyBitmap internally and materializes the whole image into one buffer. Because that buffer is indexed by int, it is effectively limited to about 2 GB no matter how much memory the machine has, so a TIFF slightly over that limit cannot be held. LoadImage(filePath) currently returns zero loaded pages instead of throwing a clear exception; this silent failure is a known issue, and a clearer exception is planned. The single-buffer design is an architectural limit, and native per-page TIFF streaming, which would avoid buffering the whole file, is not yet available.
This affects 2026.5.2. The limit is a runtime constraint, not OS-specific, so it applies across platforms on .NET.
Solution
Split the TIFF into sub-2 GB chunks and pass each chunk to IronOCR as a byte array.
1. Add Magick.NET
Bring in Magick.NET so you can split the TIFF before handing it to IronOCR. Pick the variant that matches your project (Q8/Q16, AnyCPU/x64).
dotnet add package Magick.NET-Q16-AnyCPU
dotnet add package Magick.NET-Q16-AnyCPU
SHELL
2. Split by Page Count and Load as Bytes
Open the TIFF as a MagickImageCollection, break it into page-count chunks that each stay under 2 GB, convert each chunk to a byte array, and load it with OcrInput.LoadImage(byte[]) rather than the file path.
var inputPath = "input.tiff";var pagesPerChunk = 100;using var allPages = new MagickImageCollection(inputPath);int chunkNumber = 1;for (int i = 0; i < allPages.Count; i += pagesPerChunk){ using var chunk = new MagickImageCollection(); for (int j = i; j < Math.Min(i + pagesPerChunk, allPages.Count); j++) { chunk.Add(allPages[j].Clone()); } foreach (var image in chunk) { image.SetCompression(CompressionMethod.LZW); } var chunkBytes = chunk.ToByteArray(); using (var ocrInput = new OcrInput()) { ocrInput.LoadImage(chunkBytes); var pages = ocrInput.GetPages().ToList();Console.WriteLine($"Loaded pages: {pages.Count}"); var result = new IronTesseract().Read(ocrInput);Console.WriteLine("OCR Text Length: " + (result.Text?.Length ?? 0)); }Console.WriteLine($"Chunk {chunkNumber} processed"); chunkNumber++;}
var inputPath = "input.tiff";
var pagesPerChunk = 100;
using var allPages = new MagickImageCollection(inputPath);
int chunkNumber = 1;
for (int i = 0; i < allPages.Count; i += pagesPerChunk)
{
using var chunk = new MagickImageCollection();
for (int j = i; j < Math.Min(i + pagesPerChunk, allPages.Count); j++)
{
chunk.Add(allPages[j].Clone());
}
foreach (var image in chunk)
{
image.SetCompression(CompressionMethod.LZW);
}
var chunkBytes = chunk.ToByteArray();
using (var ocrInput = new OcrInput())
{
ocrInput.LoadImage(chunkBytes);
var pages = ocrInput.GetPages().ToList();
Console.WriteLine($"Loaded pages: {pages.Count}");
var result = new IronTesseract().Read(ocrInput);
Console.WriteLine("OCR Text Length: " + (result.Text?.Length ?? 0));
}
Console.WriteLine($"Chunk {chunkNumber} processed");
chunkNumber++;
}
C#
Each chunk is a fresh MagickImageCollection cloned from the source pages, re-compressed with CompressionMethod.LZW, then serialized with ToByteArray() and passed to OcrInput.LoadImage(byte[]). Keeping the byte payload under 2 GB is what sidesteps the buffer limit.
3. Tune pagesPerChunk
Adjust pagesPerChunk for your data. Lower it if a chunk approaches 2 GB or if memory is tight; raise it for smaller pages to cut down on overhead.
4. Account for Magick.NET in Deployment
Magick.NET ships ImageMagick native binaries. Those add to package size and bring a native dependency footprint, so factor them into your deployment.
Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.