WPF 异步加载高清大图

不管什么东西,但凡太大了,总是让人又爱又恨啊!(很有道理的样子,大家鼓掌└( ̄  ̄└)(┘ ̄  ̄)┘)

猿:老板,现在这社会啊,真是浮躁啊,之前还是什么1080P,然后就到了2K,现在又到了4K……他们是想把毛孔都看清楚?

老板:能不能做?

猿:已经做好了啊,但是……反正这次我们能说会道的X经理也没能忽……说服客户。

老板:是什么问题嘛,说出来我帮你想想办法。(老板真是好人啊,语重心长)

猿(ノへ ̄、):客户不是升级了4K摄像机吗,哎哟,那玩意儿,老长了,就跟火箭筒似的,扛起来那感觉(? •?_•?)?,真是拉风……

老板:咳咳……

猿:嗯,4K,拍出来的照片分辨率4096x2160,一张图片就有30多M,然后……我们的程序挂了,内存崩了。╮( ̄▽ ̄")╭

老板:嗯,这个问题嘛……

猿:昨晚我加班到凌晨三点,各种调试,各种查资料,终于搞定了,今天早上让小X过去更换了,然后……

老板:辛苦了,办公室里有吃的,晚上加班尽管吃!

猿:( ̄▽ ̄")……

猿:然后内存是没爆了,但是大图出来的使用有2~3秒的空白……也不能操作……X经理正在给我们争取时间……

老板:这样啊,我给你一个我朋友的电话,他也是搞软件的,很牛X的……

嗯,各位童鞋,看到这里就应该明白,对话已经结束。这就开始我们的代码……

XAML我们就简单点:用ListView做个列表,一个用于显示大图的Image,一个遮罩层Border

 1  <Grid>
 2         <Grid.ColumnDefinitions>
 3             <ColumnDefinition Width="420"/>
 4             <ColumnDefinition Width="*"/>
 5         </Grid.ColumnDefinitions>
 6         <ListView  x:Name="lvImages" ScrollViewer.CanContentScroll="False" SelectionChanged="lvImages_SelectionChanged">
 7             <ListView.ItemTemplate>
 8                 <DataTemplate>
 9                     <Image Source="{Binding Converter={StaticResource ImageSourceConverter}, Mode=OneTime,ConverterParameter=400}" Width="400" />
10                 </DataTemplate>
11             </ListView.ItemTemplate>
12         </ListView>
13         <ScrollViewer  Grid.Column="1" >
14             <ScrollViewer.Background>
15                 <ImageBrush ImageSource="{Binding SelectedItem, ElementName=lvImages,Converter={StaticResource ImageSourceConverter}}" Stretch="Uniform"/>
16             </ScrollViewer.Background>
17             <Image Name="bigImage"   MouseWheel="bigImage_MouseWheel" RenderTransformOrigin="0.5,0.5">
18                 <Image.RenderTransform>
19                     <ScaleTransform x:Name="scale"/>
20                 </Image.RenderTransform>
21             </Image>
22         </ScrollViewer>
23         <Border Name="conver" Background="#60000000" Visibility="Hidden" Grid.ColumnSpan="2">
24             <Path Data="M30.330999,48.228C31.299783,48.422099 32.299767,48.531501 33.330949,48.531501 34.360932,48.531501 35.363415,48.422099 36.335999,48.228L36.335999,66.659003 30.330999,66.659003z M43.268281,44.750998L52.394999,60.832034 47.175917,63.796996 38.038999,47.713359C39.994767,47.070048,41.753928,46.067427,43.268281,44.750998z M23.209264,44.598998C24.700174,45.940215,26.447487,46.971526,28.389,47.638133L19.002135,63.568 13.824999,60.518466z M47.700966,38.078002L63.757998,47.260428 60.782928,52.473998 44.726998,43.300773C46.044784,41.78905,47.055174,40.028529,47.700966,38.078002z M18.923298,37.936999C19.546999,39.89281,20.5418,41.665007,21.844,43.188594L5.7032509,52.206 2.7709999,46.960906z M18.4298,30.342997C18.240998,31.305102 18.131697,32.306304 18.131697,33.328299 18.131697,34.360797 18.237098,35.373698 18.435,36.3502L0.0077514648,36.370997 0,30.365096z M66.659098,30.285998L66.666998,36.294497 48.231798,36.313998C48.4272,35.347804 48.531301,34.352805 48.531301,33.328002 48.531301,32.294097 48.4272,31.284898 48.227999,30.308202z M60.963728,14.451999L63.895998,19.696799 47.743868,28.718999C47.120075,26.764499,46.123985,24.996299,44.817999,23.474099z M5.8831024,14.181999L21.936999,23.357735C20.616765,24.868125,19.607615,26.627213,18.960647,28.578999L2.9039993,19.403264z M47.663984,3.0889991L52.839998,6.1383522 43.456712,22.064999C41.96595,20.723838,40.213178,19.687466,38.276999,19.020785z M19.487081,2.8649989L28.617,18.94893C26.66778,19.585601,24.902254,20.590758,23.394619,21.910998L14.261999,5.8297189z M30.330999,0L36.335999,0 36.335999,18.430999C35.363416,18.2357 34.36093,18.127599 33.330949,18.127599 32.299765,18.127599 31.299782,18.2357 30.330999,18.430999z"
25                           Stretch="Uniform" Margin="200" Fill="Red" RenderTransformOrigin="0.5,0.5">
26                 <Path.RenderTransform>
27                     <RotateTransform x:Name="rotate" Angle="0"/>
28                 </Path.RenderTransform>
29             </Path>
30         </Border>
31     </Grid>

后台代码:

 1 private void Window_Loaded(object sender, RoutedEventArgs e)
 2         {
 3             //高清大图,你懂的。
 4             var path = Combine(AppDomain.CurrentDomain.BaseDirectory, "images");//using static System.IO.Path;
 5             var files = Directory.GetFiles(path);
 6             lvImages.ItemsSource = files;
 7         }
 8
 9
10         private async void lvImages_SelectionChanged(object sender, SelectionChangedEventArgs e)
11         {
12            //在选中项更改时进行处理,
13             if (lvImages.SelectedIndex > -1)
14             {
15                 //选中的项
16                 var current = e.AddedItems[0];
17
18                 bigImage.Source = null;
19
20                 //坐和放宽,很快就好。
21                 conver.Visibility = Visibility.Visible;
22                 rotate.BeginAnimation(RotateTransform.AngleProperty, new DoubleAnimation(360, TimeSpan.FromMilliseconds(1000))
23                 { RepeatBehavior = RepeatBehavior.Forever });
24
25                 //await一下
26                 try
27                 {
28                     var source = await Task.Run<ImageSource>(() =>
29                     {
30                         var p = current.ToString();
31                         var s = new BitmapImage();
32                         s.BeginInit();
33                         s.CacheOption = BitmapCacheOption.OnLoad;
34                         //打开文件流
35                         using (var stream = File.OpenRead(p))
36                         {
37                             s.StreamSource = stream;
38                             s.EndInit();
39                             //这一句很重要,少了UI线程就不认了。
40                             s.Freeze();
41                         }
42                         return s;
43                     });
44                     //出炉
45                     bigImage.Source = source;
46                 }
47                 catch { }
48                 //好了,不用转了
49                 rotate.BeginAnimation(RotateTransform.AngleProperty, null);
50                 conver.Visibility = Visibility.Hidden;
51             }
52             else
53             {
54                 var s = bigImage.Source;
55                 s = null;
56                 bigImage.Source = null;
57             }
58         }
59
60         private void bigImage_MouseWheel(object sender, MouseWheelEventArgs e)
61         {
62            //高清大图嘛,当然要放大了仔细看看
63             var d = e.Delta / 1000.0;
64             if (scale.ScaleX + d < 1)
65             {
66                 scale.ScaleX = scale.ScaleY = 1;
67                 return;
68             }
69             scale.ScaleX += d;
70             scale.ScaleY += d;
71         }

一个简单的ImageSourceConverter:

 1  public class ImageSourceConverter : IValueConverter
 2     {
 3         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 4         {
 5             if (value == null)
 6                 return value;
 7             var source = new BitmapImage();
 8             source.BeginInit();
 9             source.UriSource = new Uri(value.ToString(), UriKind.Absolute);
10             //设置解码的分辨率大小,也就是搞个缩略图
11             source.DecodePixelWidth = parameter != null ? int.Parse(parameter.ToString()) : 100;
12             source.EndInit();
13             return source;
14
15         }
16
17         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
18         {
19             throw new NotImplementedException();
20         }
21     }

看图:

时间: 2024-12-22 06:20:08

WPF 异步加载高清大图的相关文章

浅谈android中加载高清大图及图片压缩方式(二)

这一讲就是本系列的第二篇,一起来聊下关于android中加载高清大图的问题,我们都知道如果我们直接加载原图的话,一个是非常慢,需要等待一定时间,如果没有在一定的时间内给用户响应的话,将会极大影响用户的体验.另一个是如果你的手机内存小的话,可能会直接崩溃.这也就是直接加载高清原图问题.遇到这些问题很容易想到的一点就是图片压缩,本篇文章也就是讲述图片压缩方式来实现加载高清大图的效果.但是现在问题就来了,通过上篇博客我们知道,手机的分辨率有很多,如何保证我同一张图片在不同分辨率的手机上能适当的压缩比例

加载高清大图崩溃问题

SDWebImage加载高清大图崩溃问题: 经验证没测试出来,在网上查找根源应该是在iOS7上有问题,特此记录一下 第一种:老版本SDWebImage_v4.2.0 更改源码 这里面对图片的处理是直接按照原大小进行的,如果几千是分辨率这里导致占用了大量内存. 1.在UIImage+MultiFormat 中增加方法,对图片做一次等比的压缩. +(UIImage *)compressImageWith:(UIImage *)image { float imageWidth = image.size

IOS 多个UIImageView 加载高清大图时内存管理

当我们在某一个View  多个UIImageView,且UIImageView都显示的是高清大图,就有可能出现内存警告的问题.如果第一次进入这个view,没有发生内存警告,当再次进入这个view,如果上一次的内存没有及时释放,这一次次的累加,便可导致内存崩溃. 1,UIImage 加载图片的方式.      如果是本地图片,尽量不要使用 [UIImage  imageNamed:nil]; 这种方式,如果使用这种方式加载,只要程序不退出,它便一直会在内存中.     我们可以使用 :      

利用runLoop加载高清大图

一.什么是runLoop 1.说白了,runloop就是运行循环 2.runloop,他是多线程的法宝 通常来讲,一个线程一次只能执行一个任务,执行完之后就退出线程.但是,对于主线程是不能退出的,因此我们需要让主线程即使任务执行完毕,也可以继续等待接收事件而不退出,那么runloop就可以做到. 但是非主线程通常来说就是为了执行某一任务的,执行完毕就需要归还资源,因此默认是不运行runloop的. 3.每一个线程对应都有一个runloop,只是默认只有主线程的runloop是开启的,其他子线程的

关于SDWebImage加载高清图片导致app崩溃的问题

链接是对于SDWebImage的使用方法 http://www.cnblogs.com/JimmyBright/p/4457258.html 使用SDWebImage加载高清图片的时候,往往会报内存溢出的错误导致程序直接crash.比如说,你的程序加载10张左右的单反相片,这些相片每张都在10M左右,使用SDWebImage下载缓存再显示的方法,程序肯定会直接挂掉,查看内存图标一般是这种情况 这个程序一般运行内存消耗是13M左右,但是在加载了某张10M左右的图片后,突然有一个上升,飙升到178M

【.net深呼吸】WPF异步加载大批量图像

如何在WPF中加载大批量数据,并且不会阻塞UI线程,尤其是加载大量图片时,这活儿一直是很多朋友都相当关注的.世上没有最完美的解决之道,咱们但求相对较优的方案. 经过一些试验和对比,老周找到了一种算是不错的方案,重点是这个方案比较简单,无须闯五关斩六将,只要你对数据绑定有些基础就好了. 好,F话少扯,咱们开始吧. 老周手里没有那么多照片,那就用同一张图片做测试吧.假设我要在应用程序运行时加载 2 万张图片,我想2W张应该可以了,没见过谁会傻到要加载100W张那么变态. 大致情况是:数据源集合是一个

wpf 异步加载 只需6段代码

private BackgroundWorker worker = null; ProgressBar probar = new ProgressBar(); private int percentValue = 0; private int percent; public MainWindow() { InitializeComponent(); } private void Button_Click_1(object sender, RoutedEventArgs e) { worker =

Android引入高速缓存的异步加载全分辨率

Android引进高速缓存的异步加载全分辨率 为什么要缓存 通过图像缩放,我们这样做是对的异步加载优化的大图,但现在的App这不仅是一款高清大图.图.动不动就是图文混排.以图代文,假设这些图片都载入到内存中.必然会OOM.因此,在用户浏览完图像后.应当马上将这些废弃的图像回收,可是.这又带来了另一个问题.也就是当用户在浏览完一次图片后,假设还要返回去再进行又一次浏览,那么这些回收掉的图像又要又一次进行载入,保不准就要那些无聊到蛋疼的人在那一边看你回收GC.一边看你又一次载入.这两件事情,肯定是互

Android_性能优化之ViewPager加载成百上千高清大图oom解决方案

一.背景 最近做项目需要用到选择图片上传,类似于微信.微博那样的图片选择器,ContentResolver读取本地图片资源并用RecyclerView+Glide加载图片显示就搞定列表的显示,这个没什么大问题,重点是,点击图片进入大图浏览,比如你相册有几百张图片,也就意味着在ViewPager中需要加载几百个view,况且手机拍出来的图片都是1-2千万左右像素的高清大图(笔者手机2千万像素 也就是拍照出来的照片3888*5152),大小也有5-7个兆,ViewPager滑动不了十几张就oom了,