Tamanho da imagem do .NET GDI + - limitações do codec de arquivo

Existe um limite no tamanho da imagem que pode ser codificado usando os codecs de arquivo de imagem disponíveis no .NET?

Estou tentando codificar imagens com tamanho> 4 GB, mas ele simplesmente não funciona (ou não funciona corretamente, ou seja, grava um arquivo ilegível) com os codificadores .bmp, .jpg, .png ou .tif.

Quando reduzo o tamanho da imagem para <2GB, ele funciona com o .jpg, mas não com o .bmp, .tif ou .png.

Minha próxima tentativa seria tentar a libtiff porque sei que os arquivos tiff são destinados a imagens grandes.

Qual é um bom formato de arquivo para imagens grandes? ou estou apenas atingindo as limitações de formato de arquivo?

(Tudo isso está sendo feito em um sistema operacional de 64 bits (WinXP 64) com 8 GB de RAM e compilado usando a arquitetura x64.)

Random r = new Random((int)DateTime.Now.Ticks);

int width = 64000;
int height = 64000;
int stride = (width % 4) > 0 ? width + (width % 4) : width;
UIntPtr dataSize = new UIntPtr((ulong)stride * (ulong)height);
IntPtr p = Program.VirtualAlloc(IntPtr.Zero, dataSize, Program.AllocationType.COMMIT | Program.AllocationType.RESERVE, Program.MemoryProtection.READWRITE);

Bitmap bmp = new Bitmap(width, height, stride, PixelFormat.Format8bppIndexed, p);
BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);

ColorPalette cp = bmp.Palette;
for (int i = 0; i < cp.Entries.Length; i++)
{
  cp.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = cp;

unsafe
{
  for (int y = 0; y < bd.Height; y++)
  {
    byte* row = (byte*)bd.Scan0.ToPointer() + (y * bd.Stride);
    for (int x = 0; x < bd.Width; x++)
    {
      *(row + x) = (byte)r.Next(256);
    }
  }
}

bmp.UnlockBits(bd);
bmp.Save(@"c:\test.jpg", ImageFormat.Jpeg);
bmp.Dispose();

Program.VirtualFree(p, UIntPtr.Zero, 0x8000);

Também tentei usar uma região de memória GC fixada, mas isso é limitado a <2GB.

Random r = new Random((int)DateTime.Now.Ticks);

int bytesPerPixel = 4;
int width = 4000;
int height = 4000;         
int padding = 4 - ((width * bytesPerPixel) % 4);
padding = (padding == 4 ? 0 : padding);
int stride = (width * bytesPerPixel) + padding;
UInt32[] pixels = new UInt32[width * height];
GCHandle gchPixels = GCHandle.Alloc(pixels, GCHandleType.Pinned);
using (Bitmap bmp = new Bitmap(width, height, stride, PixelFormat.Format32bppPArgb, gchPixels.AddrOfPinnedObject()))
{
    for (int y = 0; y < height; y++)
    {
        int row = (y * width);
        for (int x = 0; x < width; x++)
        {
            pixels[row + x] = (uint)r.Next();
        }
    }

    bmp.Save(@"c:\test.jpg", ImageFormat.Jpeg);
}
gchPixels.Free();

questionAnswers(3)

yourAnswerToTheQuestion