OutOfMemoryException загрузка большого изображения в объект Bitmap с помощью Compact Framework
У меня проблема с утечкой памяти.
У меня есть этот код в button_click
:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim ms As New IO.MemoryStream
Dim bm As New Bitmap("\Application Data\imgs\IMG22.jpg")
bm.Save(ms, Drawing.Imaging.ImageFormat.Jpeg)
End Sub
Этот код прекрасно работает, когда я запускаю.exe на своем ноутбуке (я имею в виду под windows7/32bits с полной.net framework), но когда я запускаю приложение на устройстве с WindowsMobile 6.1, приложение выдает это исключение:
SmartDeviceProject22.exe
OutOfMemoryException
в
Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
at
System.Drawing.Image.Save(Stream stream, ImageFormat format)
at
SmartDeviceProject22.Form1.Button3_Click(Object sender, EventArgs e)
at
....
Размер изображения составляет около 200 КБ, а ширина и высота около 1500 пикселей. Детали изображения:
- Размер: 1536x2048
- Горизонтальное разрешение: 72dpi
- Горизонтальное разрешение: 72dpi
- Битовая глубина: 24
- Блок разрешения: 2
- Цветовое представление: sRGB -
Любая помощь будет по достоинству оценена.
Я пытаюсь код @asawyer даже удалить ВСЕ код, ссылку и т. Д., И проблема сохраняется, я думаю, это что-то о ширине / высоте изображения или с компактной структурой.
Любой другой совет?
Решение и объяснение проблемы. Ну а после некоторых испытаний реальная проблема заключалась не в утечке памяти, как @pdriegen сказал, что это проблема доступной памяти.
Я изменяю свой код на это (и проверено на мобильном устройстве):
Dim fs As IO.FileStream = IO.File.OpenRead("\Application Data\ryder\IMG23.jpg")
Dim arrb(fs.Length) As Byte
fs.Read(arrb, 0, arrb.Length)
fs.Close()
fs.Dispose()
И с кодом выше (по-видимому) я получаю byte() (массив) изображения для хранения в базе данных, используя dataSet.
В заключение: загрузить растровый объект в memoryStream, плохая идея. Большое спасибо всем, кто нашел время, чтобы прочитать мою проблему, и особенно тем, кто публикует свой ответ.
Решение (если вам нужно показать изображение в графическом окне):
Через несколько недель это, вероятно, лучшее (бесплатное) решение: внедрите ImageHelper, как описано здесь: ImageHelper
В этом классе / образце используется пространство имен чертежей из OpenNetCF ( http://www.opennetcf.com/)
Он отлично работает и решает проблемы с памятью, загружая большие растровые изображения в память, на самом деле мы загружаем миниатюру, поэтому размер в памяти значительно уменьшается и избегает проблемы исключений OutOfMemory.
О Крисе Таке Я просто понимаю, что автор поста об ImageHelper и соучредителе OpenNetCF находится здесь в stackru, вот его профиль: ctacke
2 ответа
Я не верю, что проблема в утечке памяти. Вместо этого проблема заключается в нехватке доступной памяти.
Несмотря на то, что размер сжатого изображения составляет 200 КБ, при загрузке его в виде растрового изображения оно будет распаковано и сохранено в памяти в собственном растровом формате. Учитывая высоту и ширину 1500px каждый и допуская формат растрового изображения 32bpp (по умолчанию, если не указан), вы смотрите на 9 МБ выделенной памяти
1500 * 1500 * 4 = 9 МБ.
Учитывая ограничения памяти, присутствующие в ОС мобильного устройства (32 МБ / процесс - пространство, выделенное системными библиотеками), вы вполне можете оказаться в сценарии перерыва в памяти. Конечно, мне неизвестно, какая другая память выделяется приложением, в котором вы запускаете этот код.
Попробуйте тот же код на том же устройстве с меньшим изображением. Вы должны увидеть, что он работает нормально.
Ваши утечки Gdi обрабатывают, оборачивают поток и растровое изображение в предложениях Using.
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
using ms As New IO.MemoryStream
using bm As New Bitmap("\Application Data\imgs\IMG22.jpg")
bm.Save(ms, Drawing.Imaging.ImageFormat.Jpeg)
end using
end using
End Sub