Из ошибки памяти при загрузке Битового массива

Я работаю с большими изображениями размера (для напр. 16000x9440 пкс) и сокращение некоторые регионы для других вещей. Я вытаскиваю исключение "Из памяти", когда создают новый Растровый экземпляр:

using (FileStream fileStream = new FileStream(mapFileResized, FileMode.Open))
{
    byte[] data = new byte[fileStream.Length];
    fileStream.Read(data, 0, data.Length);
    using (MemoryStream memoryStream = new MemoryStream(data))
    {
        using (Bitmap src = new Bitmap(memoryStream)) // <-- exception
        {
            tile = new Bitmap(tileWidth, tileHeight, PixelFormat.Format24bppRgb);
            tile.SetResolution(src.HorizontalResolution, src.VerticalResolution);
            tile.MakeTransparent();
            using (Graphics grRect = Graphics.FromImage(tile))
            {
                grRect.CompositingQuality = CompositingQuality.HighQuality;
                grRect.SmoothingMode = SmoothingMode.HighQuality;
                grRect.DrawImage(
                        src,
                        new RectangleF(0, 0, tileWidth, tileHeight),
                        rTile,
                        GraphicsUnit.Pixel
                );
            }
        }
    }
}

Когда я использую небольшие размеры изображения (для напр. 8000x4720 пкс), затем все хорошо работают.

Как я могу работать с большими изображениями размера?

Битовый массив мозаики PS расположен в наконец блоке.

С наилучшими пожеланиями, Alex.

5
задан Blorgbeard 25 June 2010 в 10:58
поделиться

3 ответа

Вы используете около гигабайта оперативной памяти, поэтому неудивительно, что у вас закончилась память.

Предполагая, что вы используете формат файла 32bpp с 16000x9440 пикселей, вы получите размер файла примерно:

16000 * 9440 * (32/8) = ~ 576MB

byte[] data = new byte[fileStream.Length];
fileStream.Read(data, 0, data.Length);
using (MemoryStream memoryStream = new MemoryStream(data))
{
  [... snip ...]
}

Вы загружаете весь файл в поток памяти, для этого требуется 576MB .

[... snip ...]
    using (Bitmap src = new Bitmap(memoryStream)) // <-- exception
    {
        [... snip ...]
    }
[... snip ...]

Вы загружаете все содержимое потока в растровое изображение, для этого требуется еще как минимум 576 МБ (в зависимости от того, сколько памяти требует растровое изображение на пиксель, должно быть не менее 4, а возможно и больше). В этот момент у вас в памяти дважды остается изображение, что серьезно сказывается на таких больших изображениях.

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

Другим решением было бы загрузить только часть растрового изображения и загрузить другие части по запросу (во многом как карты Google), но я не могу помочь вам с этим решением, может потребоваться чтение растрового изображения вручную.

6
ответ дан 13 December 2019 в 19:21
поделиться

Не полный ответ на ваш вопрос, но вам, вероятно, лучше использовать такую ​​библиотеку, как ImageMagick.NET

3
ответ дан 13 December 2019 в 19:21
поделиться

MemoryStream реализован с использованием массива байтов, в котором хранятся данные. Если вы читаете больше данных, чем может вместить массив, выделяется новый массив двойного размера и байты копируются из одного массива в другой.

Поскольку вы, очевидно, знаете, сколько данных вам понадобится, вы можете выделить правильный размер заранее и таким образом избежать изменения размера.

Однако, как только вы достигнете определенного размера, у вас закончится память. .NET налагает ограничение в 2 ГБ на один объект ( даже на 64-битном ), поэтому внутренний массив в MemoryStream никогда не сможет вырасти сверх этого. Если ваше изображение больше, вы получите исключение нехватки памяти.

2
ответ дан 13 December 2019 в 19:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: