Как к изображениям на дисплее, не поднимая огромные суммы RAM

Я работаю над проектом Silverlight, где пользователи добираются для создания их собственных Коллажей.

Проблема

При загрузке набора изображений при помощи класса BitmapImage, пожиратели ресурсов Silverlight огромные неблагоразумные суммы RAM. 150 изображений, где единственные заполняют самое большее 4,5 МБ, поднимают приблизительно 1,6 ГБ RAM - таким образом окончание исключений памяти выдачи.

Я загружаю их через потоки, так как пользователь выбирает их собственные фотографии.

Что я ищу

Класс, метод или некоторый процесс для устранения огромной суммы RAM, высосанной. Скорость является проблемой, таким образом, я не хочу преобразовывать между форматами изображений или чем-либо как этот. Могло бы работать быстрое решение для изменения размеров.

Я попытался использовать WriteableBitmap для рендеринга изображений в, но я нахожу, что этот метод вынуждает меня изобрести велосипед когда дело доходит до, перетаскивают/отбрасывают и другие вещи, которые я хочу, чтобы пользователи смогли сделать с изображениями.

13
задан Michael Sondergaard 7 April 2010 в 08:26
поделиться

6 ответов

Я бы попробовал загрузить каждый поток и изменить его размер до миниатюры (скажем, 640x480) перед загрузкой следующий. Затем позвольте пользователю работать с изображениями меньшего размера. Когда вы будете готовы создать PDF-файл, перезагрузите JPEG-файлы из исходных потоков по одному, удаляя каждое растровое изображение перед загрузкой следующего.

6
ответ дан 2 December 2019 в 00:58
поделиться

Я предполагаю, что вы делаете что-то вроде этого:

Bitmap bitmap = new Bitmap (filename of jpeg);

, а затем делаете:

OnPaint (...)
{
   Graphics g = ....;
   g.DrawImage (bitmap, ...);
}

Это будет изменять размер огромного изображения JPEG до размера, отображаемого на экране каждый раз, когда вы его рисуете. Я предполагаю, что ваш JPEG имеет размер около 2500x2000 пикселей. Когда вы загружаете JPEG в растровое изображение, код загрузки растрового изображения распаковывает данные и сохраняет их либо как данные RGB в формате, который будет легко визуализировать (т. Е. В том же формате пикселей, что и дисплей), либо как вещь, известная как Независимое от устройства растровое изображение (также известное как DIBitmap). Эти растровые изображения требуют больше ОЗУ для хранения, чем сжатый JPEG.

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

В идеале вы хотите загрузить изображение и уменьшить его. .Net имеет систему для этого:

Bitmap bitmap = new Bitmap (filename of JPEG);
Bitmap thumbnail = bitmap.GetThumbnailImage (width, height, ....);
bitmap.Dispose (); // this releases all the unmanged resources and makes the bitmap unusable - you may have been missing this step
bitmap = null; // let the GC know the object is no longer needed

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

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

4
ответ дан 2 December 2019 в 00:58
поделиться

Это не полное решение, но если вы собираетесь выполнять преобразование между растровыми изображениями и форматами JPEG (и наоборот), вам необходимо загляните в библиотеку изображений FJCore . Он достаточно прост в использовании и позволяет вам изменять размер изображений JPEG или перемещать их в другое качество. Если вы используете Silverlight для обработки изображений на стороне клиента, этой библиотеки, вероятно, будет недостаточно, но она, безусловно, необходима.

Вам также следует изучить, как вы представляете изображения пользователю. Если вы делаете коллажи с помощью Silverlight, вероятно, вы не сможете использовать элементы управления виртуализацией, поскольку пользователи будут манипулировать всеми 150 изображениями одновременно. Но, как говорили другие, вам также следует убедиться, что вы не представляете растровые изображения, основанные на полноразмерных файлах JPEG. Сжатый JPEG размером 1 МБ, вероятно, будет расширен до растрового изображения 10 МБ, что, вероятно, является причиной многих ваших проблем. Убедитесь, что вы основываете изображения, которые представляете пользователю, на файлах JPEG гораздо меньшего размера (более низкого качества и с измененным размером).

1
ответ дан 2 December 2019 в 00:58
поделиться

То, что с вами может происходить, является малоизвестным фактом о сборке мусора, который тоже достал мне. Если объект достаточно большой (я не помню, где именно находится линия), сборщик мусора решит, что даже если ничто в настоящее время в области видимости не связано с объектом (и в вашем, и в моем объекты являются изображениями), оно сохраняет изображение. в памяти, потому что было решено, что на случай, если вы когда-нибудь снова захотите это изображение, дешевле сохранить его, чем удалить и перезагрузить позже.

1
ответ дан 2 December 2019 в 00:58
поделиться

Еще один вариант уменьшения оперативной памяти с помощью: Не загружайте изображения, которые в данный момент невидимы, и загружайте их, пока пользователь прокручивает страницу. Этот метод используется веб-разработчиками для повышения скорости загрузки страницы. Для вас это способ не хранить количество дыр в памяти.

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

0
ответ дан 2 December 2019 в 00:58
поделиться

Решение, которое, наконец, сработало для меня, заключалось в использовании WriteableBitmapEX для выполнения следующих действий:

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

У меня была ошибка, заключающаяся в том, что WriteableBitmap не имеет конструктора без параметров, но инициализация его размером 0,0 с последующей загрузкой источника устанавливает их автоматически. Для меня это не было естественным.

Всем спасибо за помощь!

private WriteableBitmap getThumbnailFromBitmapStream(Stream bitmapStream, PhotoFrame photoFrame)
    {
        WriteableBitmap inputBitmap = new WriteableBitmap(0,0);
        inputBitmap.SetSource(bitmapStream);

        Size thumbnailSize = getThumbnailSizeFromWriteableBitmap(inputBitmap, photoFrame.size);

        WriteableBitmap thumbnail = new WriteableBitmap(0,0);
        thumbnail = inputBitmap.Resize((int)thumbnailSize.Width, (int)thumbnailSize.Height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);

        return thumbnail;
    }
0
ответ дан 2 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

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