【问题标题】:Replace a low resolution image with an high resolution one用高分辨率图像替换低分辨率图像
【发布时间】:2014-11-20 03:15:42
【问题描述】:

我必须同时显示约 150 张高分辨率图像(每张约 5 MB)。问题是同时加载所有这些图像需要大量时间。所以我想在开始时显示低分辨率图像,同时在背景中加载真正的高分辨率图像。然后当它们准备好时切换它们。

【问题讨论】:

    标签: wpf image backgroundworker bitmapimage


    【解决方案1】:

    我不会为所有的 C# 代码而烦恼。相反,我只使用集合控件和文件路径集合。试试这个例子:

    <ListBox ItemsSource="{Binding FilePaths}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding}" Width="250" Stretch="Uniform" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    ...

    private ObservableCollection<string> filePaths = new ObservableCollection<string>();
    public ObservableCollection<string> FilePaths
    {
        get { return filePaths; }
        set { filePaths = value; NotifyPropertyChanged("FilePaths"); }
    }
    

    ...

    FilePaths = new ObservableCollection<string>(Directory.GetFiles(
        Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "*.png"));
    

    【讨论】:

    • 这样您就可以加载低分辨率图像以快速启动,然后在后台加载高分辨率版本?
    • 如果您可以访问此处提到的低分辨率图像,则可以将 PriorityBinding 与 Binding.IsAsync 示例部分中提到的 IsAsync 属性结合使用
    【解决方案2】:

    一段时间后,我最终得到了这个解决方案。首先,我加载低分辨率图像并将它们添加到网格中:

    foreach (var extElem in ElemList)
    {
       IdImage img = new IdImage();
       img.Id = extElem.ImageID;
       img.CollectionId = extElem.CollectionID;
       BitmapImage bi = new BitmapImage();
       bi.BeginInit();
       bi.UriSource = new Uri(extElem.Url, UriKind.Absolute);
       bi.DecodePixelWidth = 200; //If you want to further reduce the image size (and load time)
       bi.EndInit();
       img.Source = bi;
       grid.Children.Add(img);
    
       _imgList.Add(img);
    }
    

    然后我开始后台操作以加载高分辨率图像并更改位图的来源:

    BackgroundWorker bgw = new BackgroundWorker();
    bgw.DoWork += (s, args) =>
    {
        int i = 0;
        foreach (var extElem in _imgList)
        {
            String url = extElem.HighResImageUri;
            Image img = _imgList.ElementAt(i);
    
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.UriSource = new Uri(url, UriKind.Absolute);
            bi.EndInit();
            bi.Freeze();
    
            Dispatcher.BeginInvoke((Action)(() =>
            {
                img.Source = bi;
            }));
        }
        i++;
    }
    bgw.RunWorkerAsync();
    

    【讨论】:

    • -1。一个好的解决方案是使用带有适当 DataTemplate 和视图模型的 ItemsControl,而不是在代码中创建和操作 UI 元素。在网上搜索MVVM
    • 是的,我这样做了。我使用了 ItemsControl、DataTemplate 等。但是我有一个比我在这里描述的更复杂的应用程序,并且这些图像覆盖在“base.Internalchildren”图像上,甚至超过 150 个(它们是 ca。 2000) 并以较低的分辨率渲染以使动画流畅播放。
    • 那么你的回答只是为了向我们展示如何在 BackgroundWorker 中做某事?
    • 嗯,或多或少是的 :) 我的问题是我不知道如何显示一堆低分辨率图像,然后(当所有内容都加载时)在运行时用高分辨率更新这些图像版本而不会减慢应用程序的速度。我发现我可以使用 BackgroundWorker 来更新 Image 的 Source 属性。因为我正要问所以我想写我的解决方案(针对这个特定问题)。如果您认为这没用,我可以删除问题.-.
    猜你喜欢
    • 1970-01-01
    • 2017-08-23
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 2013-08-25
    相关资源
    最近更新 更多