.NET GDI + размер изображения - ограничения файлового кодека - PullRequest
6 голосов
/ 29 мая 2010

Существует ли ограничение на размер изображения, которое можно кодировать с помощью кодеков файлов изображений, доступных в .NET?

Я пытаюсь кодировать изображения размером> 4 ГБ, но он просто не работает (или не работает должным образом, т.е. записывает нечитаемый файл) с кодировщиками .bmp, .jpg, .png или .tif.

Когда я уменьшаю размер изображения до <2 ГБ, он работает с .jpg, но не с .bmp, .tif или .png. </p>

Моя следующая попытка будет заключаться в том, чтобы попробовать libtiff, потому что я знаю, что файлы tiff предназначены для больших изображений.

Какой формат файла подходит для больших изображений? или я просто бью ограничения по формату файла?

(Все это выполняется в 64-разрядной операционной системе (WinXP 64) с 8 ГБ ОЗУ и компилируется с использованием архитектуры 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);

Я также пытался использовать закрепленную область памяти ГХ, но она ограничена <2 ГБ. </p>

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();

Ответы [ 3 ]

2 голосов
/ 29 мая 2010

Проблема, с которой вы сталкиваетесь, - это, вероятно, следующее ограничение в .NET Framework: максимальный размер объекта, разрешенный в куче GC, составляет 2 ГБ, даже в 64-битных ОС / сборках.

Некоторые ссылки: ссылка , ссылка , ссылка .

В зависимости от ваших потребностей, при относительно простом (несжатом) формате, таком как TIFF, может выполнимо генерировать ваше изображение по частям и объединять детали впоследствии. Просто идея ..

1 голос
/ 07 сентября 2010

Итак, ваша цель - закодировать их в jpeg? Я уверен, что будет способ вытащить только тот раздел, который вы кодируете, затем утилизировать и перейти к следующему разделу. Если вы откроете файл raw и проанализируете его самостоятельно, я уверен, что существуют jpeg-кодеры с открытым исходным кодом, которые помогут в создании разделов. Это должно позволить вам кодировать файлы очень большого размера, но у вас всегда будут проблемы с ОС и файловой системой, которые нужно преодолеть.

1 голос
/ 07 июня 2010

Из спецификации TIFF Раздел 2: Структура TIFF при http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf:

TIFF - это формат файла изображения. В этом документ, файл определяется как последовательность 8-битных байтов, где байты пронумерованы от 0 до N. Максимально возможный файл TIFF составляет 2 ** 32 длина в байтах.

К сожалению, многие авторы и читатели TIFF используют в реализации целые числа со знаком и уменьшают практический размер до 2 ** 31. Это усугубляется частой попыткой водителей сохранить все изображение в памяти, как упомянул Кристоф.

Вероятно, вы обнаружите аналогичные ограничения в других форматах изображений, созданных в 80-х или ранее. Ограничение размера файла в несколько гигабайт не считалось проблемой, когда диски были только в десятках мегабайт.

...