从独立存储加载大量图像时出现内存不足异常
本文关键字:内存不足 异常 图像 独立 存储 加载 | 更新日期: 2023-09-27 18:30:52
>编辑:我一直得到 OutOfMemoryException 未处理,我认为这就是我将图像保存到独立存储的方式,我认为这是我可以解决我的问题的地方,如何在保存之前减小图像的大小? (在保存图像的地方添加了代码)
我从独立存储中打开图像,有时超过 100 张图像,我想遍历它们的图像,但当有大约 100 到 150 张图像加载到故事板时,我会得到OutOfMemory Exception
。 我如何处理此异常,我已经降低了图像的分辨率。 如何处理此异常并阻止我的应用程序崩溃?
我在这里得到这一行的例外
image.SetSource(isStoreTwo.OpenFile(projectFolder + "''MyImage" + i + ".jpg", FileMode.Open, FileAccess.Read));//images from isolated storage
这是我的代码
private void OnLoaded(object sender, RoutedEventArgs e)
{
IsolatedStorageFile isStoreTwo = IsolatedStorageFile.GetUserStoreForApplication();
try
{
storyboard = new Storyboard
{
//RepeatBehavior = RepeatBehavior.Forever
};
var animation = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTarget(animation, projectImage);
Storyboard.SetTargetProperty(animation, new PropertyPath("Source"));
storyboard.Children.Add(animation);
for (int i = 1; i <= savedCounter; i++)
{
BitmapImage image = new BitmapImage();
image.SetSource(isStoreTwo.OpenFile(projectFolder + "''MyImage" + i + ".jpg", FileMode.Open, FileAccess.Read));//images from isolated storage
var keyframe = new DiscreteObjectKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(100 * i)),
Value = image
};
animation.KeyFrames.Add(keyframe);
}
}
catch (OutOfMemoryException exc)
{
//throw;
}
Resources.Add("ProjectStoryBoard", storyboard);
storyboard.Begin();
}
编辑 这就是我将图像保存到独立存储的方式,我认为这是我可以解决我的问题的地方,如何在将图像保存到独立存储时减小图像的大小?
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = folderName+"''MyImage" + savedCounter + ".jpg";
try
{
// Save picture to the library camera roll.
//library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
如果您能帮助我,我将不胜感激,谢谢。
磁盘上的图像大小无关紧要,因为当您将它们加载到内存中时,它们将被解压缩。图像所需的内存约为 (stride * height)
。 stride
是width * bitsPerPixel)/8
,然后四舍五入到下一个 4 字节的倍数。因此,1024x768 和每像素 24 位的图像将占用大约 2.25 MB。
您应该弄清楚图像的大小,未压缩,并使用该数字来确定内存要求。
您正在获得内存不足异常,因为您同时将所有图像存储在内存中以创建情节提要。我认为您将无法克服图像需要在屏幕上显示的未压缩位图大小。
因此,要解决这个问题,我们必须考虑您的目标,而不是试图修复错误。如果您的目标是每 X 毫秒按顺序显示一个新图像,那么您有几个选择。
-
继续使用情节提要,但使用 OnCompleted 事件将它们链接起来。这样,您不必一次创建所有内容,而只需生成接下来的几个。但是,如果您每 100 毫秒更改一次图像,它可能不够快。
-
使用 CompositionTarget.Render,正如我在这里的回答中提到的。如果您只是预加载下一个,这可能会占用最少的内存(而不是像当前解决方案那样将它们全部预加载)。不过,您需要手动检查经过的时间。
-
重新思考你正在做的事情。如果你说出你要追求什么,人们可能会有更多的选择。
要回答帖子顶部的编辑,请尝试ImageResizer。 有一个NuGet包,上面有一个HanselBlog剧集。 显然,这是基于 Asp.Net 的,但我相信你可以把它屠宰在你的场景中工作。
在设计层解决这类问题通常效果更好。
通过某些配置使应用程序对运行环境智能,使您的应用程序更加健壮。例如,您可以定义一些变量,如图像大小、图像计数、图像质量......基于可用内存,并在运行时在应用中设置这些变量。因此,您的应用程序始终有效;在高内存机器上快,在低内存机器上慢;但永远不会崩溃。(不要相信在托管环境中工作意味着不用担心环境...设计总是很重要)
还有一些已知的设计模式,如延迟加载,你可以从中受益。
我并不特别了解Windows Phone,但是在.net winforms中,在执行长时间运行的任务时需要使用单独的线程。 您使用的是 Background Worker 还是同等产品? 终结器线程可能会被阻塞,这将阻止释放图像的资源。使用与 UI 线程不同的线程将允许自动运行 Dispose 方法。
好的,图像 (1024x768) 的内存大小至少为 3 mb (argb)
不知道 ObjectAnimationUsingKeyFrame 在内部是如何工作的。也许您可以通过销毁BitmapImage(和关键帧)的实例来强制gc,而不会丢失其在动画中的数据。(不可能,请参阅评论!
根据您的一条评论,您正在构建一个延时摄影应用程序。 WP7的商业延时应用程序将图像压缩为视频,而不是静止图像。 例如延时摄影专业版
视频播放的全部意义在于将相似或与时间相关的图像减少为高度压缩的流,这些流不需要大量内存即可播放。
如果可以在应用中添加对视频进行编码的功能,则可以避免尝试模拟视频播放器的问题(使用100多个单个全分辨率帧作为轻拂书)。
将图像处理到视频服务器端可能是另一种选择(但不如相机内友好)。