简体   繁体   English

Windows Phone图像的高内存使用率

[英]Windows Phone high memory usage with images

I am working on a Windows Phone application in Xamarin with MvvmCross. 我正在使用MvvmCross在Xamarin中处理Windows Phone应用程序。 In this application the user selects some images from his phone. 在此应用程序中,用户从手机中选择一些图像。 They get displayed in a list and the user then does stuff with them. 它们显示在列表中,然后用户对其进行填充。

I am using FileOpenPicker for the file selection and from those files i create BitmapImages to display 我正在使用FileOpenPicker进行文件选择,并从这些文件中创建BitmapImages进行显示

foreach (StorageFile file in args.Files) {
                    BitmapImage thumbnail = new BitmapImage();
                    thumbnail.DecodePixelType = DecodePixelType.Physical;
                    try {
                        using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) {
                            thumbnail.DecodePixelHeight = 70;
                            thumbnail.DecodePixelWidth = 70;

                            thumbnail.SetSource(fileStream);
                            fileStream.Dispose();
                        }
                    }
                    catch (OutOfMemoryException e) {
                        Mvx.Trace("MEMORY IS FULL");
                    }

After some other code i put these BitmapImages in a ObservableCollection and display them like this 在一些其他代码之后,我将这些BitmapImages放在ObservableCollection中,并像这样显示它们

<Image Style="{StaticResource imageListImage}" Source="{Binding Thumbnail}"/>

Nothing special about that. 没什么特别的。 The test images that i am using have a total size of 34 MB. 我正在使用的测试图像的总大小为34 MB。 Using the performance and diagnostics tool from VS i was able to determine that the memory usage of the app at start was around 16 Mb. 使用VS i的性能和诊断工具,可以确定应用程序启动时的内存使用量约为16 Mb。 When i loaded the test images in to the app it shot up to 58 MB. 当我将测试图像加载到应用程序中时,它的最大拍摄速度为58 MB。 as if it still used the full size of the images. 好像它仍然使用图像的全部大小一样。 and (Just for testing) when i took the decodepixelheight and width away it rocketed to about 350 MB. (仅供测试),当我拿住了pixel的高度和宽度时,它猛增到350 MB。 I have absolutely no idea why it is using so much memory for the images. 我完全不知道为什么它要为图像使用这么多的内存。

Because the application must be able to use lots more and bigger images I need to find a way to cut down on the memory usage. 因为应用程序必须能够使用更多和更大的图像,所以我需要找到一种减少内存使用量的方法。 Does anyone know a way how I can do this? 有人知道我该怎么做吗?

Your pictures use 34 MB of storage when they are compressed . 图片经过压缩后会占用34 MB的存储空间。 To be displayed, they need to be decompressed. 要显示它们,它们需要解压缩。 A bitmap picture uses 4 bytes per pixel (one byte for each color channel, RGB, plus one byte for the alpha channel). 一个位图图片每个像素使用4个字节(每个颜色通道一个字节,RGB一个字节,一个alpha通道一个字节)。 Therefore, a single 5 megapixels picture will use about 20 MB of RAM. 因此,一张5兆像素的图片将使用约20 MB的RAM。 That's why using DecodePixelHeight / DecodePixelHeight as often as possible is paramount. 这就是为什么尽可能频繁地使用DecodePixelHeight / DecodePixelHeight是至关重要的原因。

Still, sometimes, you have to manipulate huge pictures (such as the 38 MP pictures of the Lumia 1020, 150 MB of RAM each!!). 有时,您仍然需要操纵巨大的图片(例如Lumia 1020的38 MP图片,每个RAM 150 MB!)。 For that purpose, Nokia released the Imaging SDK (now maintained by Microsoft), allowing you to work on portions of the pictures, and not having to load the full thing in memory. 为此,诺基亚发布了Imaging SDK(现在由Microsoft维护),使您可以处理部分图片,而不必将全部内容加载到内存中。

In your case, the main issue is that you load all the thumbnails at once, even though only a few of them will be displayed simultaneously. 在您的情况下,主要问题是您一次加载了所有缩略图,即使其中只有几个缩略图会同时显示。 If you want to reduce the amount of memory used, you must lazily load the thumbnails (that is, only when they are needed). 如果要减少使用的内存量,则必须延迟加载缩略图(即,仅在需要时)。 One way would be to store the file location instead of the BitmapImage , and load the picture as needed. 一种方法是存储文件位置而不是BitmapImage ,然后根据需要加载图片。 Unfortunately, you can't bind directly a path to the Image control (except if the file is in the application's local storage). 不幸的是,您不能直接将路径绑定到Image控件(除非文件位于应用程序的本地存储中)。 In that question , I suggested to use a custom usercontrol for somebody who had a similar issue. 在这个问题中 ,我建议对有类似问题的人使用自定义用户控件。

public sealed partial class LocalImage : UserControl
{
    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof (string),
        typeof (LocalImage), new PropertyMetadata(null, SourceChanged));

    public LocalImage()
    {
        this.InitializeComponent();
    }

    public string Source
    {
        get { return this.GetValue(SourceProperty) as string; }
        set { this.SetValue(SourceProperty, value); }
    }

    private async static void SourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var control = (LocalImage)obj;

        var path = e.NewValue as string;

        if (string.IsNullOrEmpty(path))
        {
            control.Image.Source = null;
        }
        else
        {
            var file = await StorageFile.GetFileFromPathAsync(path);

            using (var fileStream = await file.OpenAsync(FileAccessMode.Read))
            {
                BitmapImage bitmapImage = new BitmapImage();
                await bitmapImage.SetSourceAsync(fileStream);
                control.Image.Source = bitmapImage;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM