WedX - журнал о программировании и компьютерных науках

«System.OutOfMemoryException» в system.drawing.image

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

IList<PropertyInfo> properties = typeof(ApplicationUser).GetProperties()
                               .Where(x => x.PropertyType == typeof(Byte[])).ToList();

var imaBytes = property.GetValue(user, null) as Byte[];
if (imaBytes == null || imaBytes.Length == 0) continue;

Image userImage = ImageHelper.byteArrayToImage(imaBytes);   
userImage.Save(pathname + $@"\{DirName}\" + property.Name + ".jpg", ImageFormat.Jpeg);  

а это мой ImageHelper.byteArrayToImage :

public static Image byteArrayToImage(byte[] byteArrayIn)
{
    try
    {
        using (MemoryStream ms = new MemoryStream(byteArrayIn))
        using (var image = Image.FromStream(ms,false,true))
        {
            byteArrayIn = new byte[0];
            return new Bitmap(image); 
        }
    }
    catch (Exception e)
    {
       Logger.log(e);
    }
}

редактировать:
я оборачиваю код MemoryStream и изображения с помощью statment и меняю свой код и добавляю метод ImageToDisk:

public static void ImageToDisk(byte[] byteArrayIn, string pathToSave)
    {
        try
        {
            using (MemoryStream ms = new MemoryStream(byteArrayIn))
            {
                using (var image = Image.FromStream(ms, false, true))
                {
                    image.Save(pathToSave, ImageFormat.Jpeg);
                    image.Dispose();

                }

            }
        }
        catch (Exception e)
        {
            Logger.log(e);
            throw;
        }

    }  

и основной код таков:

 foreach (var property in properties)
                    {
                        try
                        {
                            var imaBytes = property.GetValue(user, null) as Byte[];
                            if (imaBytes == null || imaBytes.Length == 0)
                            {
                                continue;
                            }

                            ImageHelper.ImageToDisk(imaBytes, pathname + $@"\{DirName}\" + property.Name + ".jpg");

                        }
                        catch (Exception ex)
                        {
                            LogException(ex);
                        }
                    }  

но теперь я получаю system.runtime.interopservices.externalexception
РЕДАКТИРОВАТЬ 2:
у меня кружится голова!!! кажется, что некоторые пользователи загружают изображения из IE, а IE меняет тип MIME на изображение/PJPEG
введите описание изображения здесь
произошла ошибка - это какой-то файл с этим типом MIME, а также некоторые другие файлы image/PJPEG сохранить правильно без каких-либо исключений
введите здесь описание изображения как я могу решить эту ошибку??

11.09.2018

  • Судя по предыдущему опыту, проверка ошибок в коде загрузки изображения несколько ошибочна, поэтому может быть просто файл изображения поврежден или используются расширения или методы сжатия, которые .NET не поддерживает. Например, если у вас есть образ, который говорит, что он ОГРОМНЫЙ, тогда .NET фактически попытается загрузить образ и выделить память вместо того, чтобы отбрасывать исключение. 11.09.2018
  • Одна вещь о вашем коде, однако, почему вы выделяете два изображения, почему бы просто не return Image.FromStream(...); вместо того, чтобы делать это в блоке использования и создавать растровое изображение вокруг него? 11.09.2018
  • В каком формате находится изображение в байтовом массиве? 11.09.2018
  • спасибо за комментарий, изображения в формате JPEG, но некоторые изображения сохраняются правильно! 11.09.2018
  • @MoshheghFaghdan OOM почти всегда вызывается тем, что Dispose() не вызывался для объектов, которые необходимо удалить, множества временных объектов (например, созданных строковыми операциями) или частого изменения размера больших массивов. Все это создает временные объекты, которые в какой-то момент будут удалены сборщиком мусора. В то же время они создают много фрагментации памяти. Среда выполнения может быть не в состоянии найти достаточно большой блок для размещения нового массива byte или этого нового списка. 11.09.2018
  • Пожалуйста, никогда не пишите catch (Exception e) { Console.WriteLine(e); throw; }. Это просто пустая трата времени и усилий. Позвольте окружающей среде разобраться с этими ошибками за вас. 11.09.2018
  • @MoshheghFaghdan убедитесь, что вы удалили все объекты GDI. Передайте параметр capacity любому конструктору List, чтобы избежать перераспределения. Повторно использовать byte[] буферов вместо выделения новых. Вы можете использовать BufferManager или ArrayPool для повторного использования byte[] буферов из пула готовых буферов вместо создания новых. 11.09.2018
  • @Enigmativity спасибо за совет, это всего лишь тестовый код, а не окончательный! 11.09.2018
  • @MoshheghFaghdan - Вы также не должны помещать это в тестовый код. Почему вы считаете, что это полезно в тестовом коде? 11.09.2018
  • @Enigmativity Я имею в виду, что это не окончательный производственный код, я просто получил этот код из другого Q / A в SO :))))))))) 11.09.2018
  • Вы избавляетесь от userImage 11.09.2018
  • @Гауравса нет! я не знаю, как его утилизировать, как я могу это сделать, вызвав метод dispose ?? 11.09.2018

Ответы:


1

некоторые из этих файлов вызывают исключение

Я почти уверен, что проблема в размещении ваших изображений. Убедитесь, что все ресурсы освобождены:

using (Image userImage = ImageHelper.byteArrayToImage(imaBytes))
{
  //do whatever you need
  userImage.Save(pathname + $@"\{DirName}\" + property.Name + ".jpg", ImageFormat.Jpeg);
}

Растровые изображения потребляют много памяти. Под капотом Image используется метод GdipLoadImageFromStream. Чтобы высвободить ресурсы, он должен быть в паре с GdipDisposeImage. Вот что происходит внутри метода Image.Dispose().

11.09.2018
  • На самом деле код GDI не различает и выдает исключения OOM даже для таких вещей, как недостаточное количество дескрипторов, поэтому отсутствие удаления действительно может быть здесь виновником. 11.09.2018
  • я еще не тестировал код, но, похоже, он работает правильно, но какое реальное изображение было в формате png ?? является причиной ошибки для неправильного формата изображения?? 11.09.2018
  • Нет, формат изображения не важен. Просто убедитесь, что userImage расположен правильно. 11.09.2018
  • @PawełDyl, я пытаюсь, но в настоящее время выдается исключение «system.runtime.interopservices.externalexception» в system.drawing.dll 11.09.2018
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

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

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]