UWP关于图片缓存的那些破事儿
看似简单的功能,实施起来却是有着一堆大坑。
按着基本功能来写吧
1.选择图片并显示到Image控件中
2.图片序列化为byte数组以及反序列化
3.本地存储与读取
1.选择图片:
逻辑就是使用FileOpenPicker选择一个图片文件后,将该文件从StorageFile对象转化成可以赋值给Image.Source的ImageSource类的对象。
(这里需要注意的是WriteableBitmap,BitmapImage,SoftwareBitmapSource都可以赋值给Image.Source,你赋值给Image.Source的是什么对象,你就只能用as符把Image.Source转化成什么对象。 比如:你使用WriteableBitmap赋值给Image.Source,那么你后面只能用 var t = imageSource as WriteableBitmap, 你如果使用var t = imageSource as BitmapImage的话编译器不会报错,但是t的值最后会是null)
1.1 选取图片文件并实例化为WriteableBitmap对象
private async void ChoosePhoto()
{
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
StorageFile imgFile_tmp = await fileOpenPicker.PickSingleFileAsync();
if (imgFile_tmp == null)
{
return;
}
else
{
this.imgFile = imgFile_tmp;
using (IRandomAccessStream stream = await imgFile.OpenAsync(FileAccessMode.Read))
{
var srcImage = new WriteableBitmap(,);
await srcImage.SetSourceAsync(stream);
Image_Thumbnail.Source = srcImage;
}
}
}
1.2 选取图片文件并实例化为BitmapImage对象
private async void ChoosePhoto()
{
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
StorageFile imgFile_tmp = await fileOpenPicker.PickSingleFileAsync();
if (imgFile_tmp == null)
{
return;
}
else
{
this.imgFile = imgFile_tmp;
using (IRandomAccessStream stream = await imgFile.OpenAsync(FileAccessMode.Read))
{
var srcImage = new BitmapImage();
await srcImage.SetSourceAsync(stream);
Image_Thumbnail.Source = srcImage;
}
}
}
1.3 选取图片实例化为SoftwareBitmapSource对象
private async void ChoosePhoto()
{
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
StorageFile imgFile_tmp = await fileOpenPicker.PickSingleFileAsync();
if (imgFile_tmp == null)
{
return;
}
else
{
SoftwareBitmap softwareBitmap;
this.imgFile = imgFile_tmp;
using (IRandomAccessStream stream = await imgFile.OpenAsync(FileAccessMode.Read))
{
// Create the decoder from the stream
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Get the SoftwareBitmap representation of the file
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
}
if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
{
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(softwareBitmap);
// Set the source of the Image control
Image_Thumbnail.Source = source;
}
}
2.图片序列化为byte数组以及反序列化
2.1 WriteableBitmap对象(Image.Source赋值的时候使用的是WriteableBitmap)序列化为byte数组
public static async Task<byte[]> SaveToBytesAsync(ImageSource imageSource)
{
byte[] imageBuffer;
var localFolder = ApplicationData.Current.TemporaryFolder;
var file = await localFolder.CreateFileAsync("temp.jpg", CreationCollisionOption.GenerateUniqueName);
using (var ras = await file.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.None))
{
WriteableBitmap bitmap = imageSource as WriteableBitmap;
var stream = bitmap.PixelBuffer.AsStream();
byte[] buffer = new byte[stream.Length];
await stream.ReadAsync(buffer, , buffer.Length);
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ras);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, buffer);
await encoder.FlushAsync(); var imageStream = ras.AsStream();
imageStream.Seek(, SeekOrigin.Begin);
imageBuffer = new byte[imageStream.Length];
var re = await imageStream.ReadAsync(imageBuffer, , imageBuffer.Length);
}
await file.DeleteAsync(StorageDeleteOption.Default);
return imageBuffer;
}
2.2Byte数组反序列化为ImageSource(WriteableBitmap)
public static async Task<ImageSource> SaveToImageSource(byte[] imageBuffer)
{
ImageSource imageSource = null;
try
{
using (MemoryStream stream = new MemoryStream(imageBuffer))
{
var ras = stream.AsRandomAccessStream();
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, ras);
var provider = await decoder.GetPixelDataAsync();
byte[] buffer = provider.DetachPixelData();
WriteableBitmap bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await bitmap.PixelBuffer.AsStream().WriteAsync(buffer, , buffer.Length);
imageSource = bitmap;
}
}
catch (Exception ex)
{ }
return imageSource;
}
2.3 BitmapImage对象序列化为byte数组
需要注意的是这里所调用的BitmspImage对象,必须是使用BitmapImage(uri)方法实例化出来的BitmapImage对象,因此下列方法主要用于实现对网络图片的序列化与反序列化。
如果使用从FileOpenPicker选取出来图片文件实例化出来的BitmapImage对象的话,该对象的UriSource属性为空,故下列方法无法实现。
RandomAccessStreamReference random = RandomAccessStreamReference.CreateFromUri(himage.UriSource);
IRandomAccessStreamWithContentType streamWithContent = await random.OpenReadAsync();
byte[] buffer = new byte[streamWithContent.Size];
await streamWithContent.ReadAsync(buffer.AsBuffer(), (uint)streamWithContent.Size, InputStreamOptions.None);
2.4 byte数组反序列化为BitmapImage对象
BitmapImage image = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(obj.ImgArray.AsBuffer());
stream.Seek();
await image.SetSourceAsync(stream);
}
3.本地存储与读取
(需要注意的是:StorageFile这类的存储操作貌似只允许存一些简单的数据类型,所以我的解决方法就是把自定义的类的对象里的图片转化为byte数组,然后再将自定义类的对象的List转化成json字符串存进文件,读取文件的时候再读出这些Json字符串并反序列化为我需要的类型)
3.1 存储数据
public static async Task SaveData(string filename, T data)
{
try
{
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream raStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
using (IOutputStream outStream = raStream.GetOutputStreamAt())
{ var json = JsonConvert.SerializeObject(data);
DataContractSerializer serializer = new DataContractSerializer(typeof(string));
serializer.WriteObject(outStream.AsStreamForWrite(), json);
var t =JsonConvert.DeserializeObject<T>(json);
await outStream.FlushAsync();
}
}
}
catch (Exception exc)
{
throw exc;
}
}
3.2 加载数据
public static async System.Threading.Tasks.Task<List<ShowInfo>> LoadData(string filename)
{
try
{
if (ApplicationData.Current.LocalFolder.TryGetItemAsync(filename) != null)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);
using (IInputStream inStream = await file.OpenSequentialReadAsync())
{
DataContractSerializer serializer = new DataContractSerializer(typeof(string));
var json = (string)serializer.ReadObject(inStream.AsStreamForRead());
var data = JsonConvert.DeserializeObject<List<ShowInfo>>(json);
return data;
}
}
else
{
return new List<ShowInfo>();
} }
catch (FileNotFoundException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
}
UWP关于图片缓存的那些破事儿的更多相关文章
- 关于CAE的那点儿破事儿
CAE是计算机辅助工程的英文简写,所涵盖的范围甚是广泛.现在很多人提到CAE,总是联想到结构有限元计算,更有甚者认为有限元就是CAE.还有人把所有的工程数值计算都称作有限元.本文就这一话题,来谈谈关于 ...
- 优化 UWP 中图片的内存占用
跟图片打交道的 UWP 应用或多或少都会遇到图片带来的性能问题,就算不主要处理图片,做个论坛做个新闻客户端都涉及到大量图片.一个帖子.一篇文章里多半都是些高清大图,这些图片一张即可占用程序 1~2M ...
- Android图片缓存之Lru算法
前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...
- android使用ImageLoader实现图片缓存(安卓开发必备)
相信大家在学习以及实际开发中基本都会与网络数据打交道,而这其中一个非常影响用户体验的就是图片的缓存了,若是没有弄好图片缓存,用户体验会大大下降,总会出现卡顿情况,而这个问题尤其容易出现在ListVie ...
- Android图片缓存之Glide进阶
前言: 前面学习了Glide的简单使用(Android图片缓存之初识Glide),今天来学习一下Glide稍微复杂一点的使用. 图片缓存相关博客地址: Android图片缓存之Bitmap详解 And ...
- Android图片缓存之初识Glide
前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...
- Android图片缓存之Bitmap详解
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...
- AFNetworking图片缓存问题
AFNetworking网络库已经提供了很好的图片缓存机制,效率是比较高的,但是我发现没有直接提供清除缓存的功能,可项目通常都需要添加 清除功能的功能,因此,在这里我以UIImageView+AFNe ...
- IOS编程 图片缓存模块设计
手机客户端为什么会留存下来?而不是被一味的Wap替代掉?因为手机客户端有Wap无可替代的优势,就是自身较强的计算能力. 手机中不可避免的一环:图片缓存,在软件的整个运行过程中显得尤为重要. 先简单说一 ...
随机推荐
- usb设备(移动硬盘或U盘),弹出时提示“有进程或程序占用,无法弹出”。解决办法
测试环境:Win7(其他Windows系统环境,也可参考) 总结办法来源,https://bbs.csdn.net/topics/392297251?page=1文章中热心网友的评论指引 1. 控制面 ...
- Numpy一文全了解
1,Numpy是一个python包,它是一个由多维数组对象和处理数组的例程集合组成的库. 2. Numpy的操作:(1)数组的算数和逻辑运算 :(2)傅里叶变换和用于图形操作 (3)与线性代数有 ...
- Python设计模式 - UML - 定时图(Timing Diagram)
简介 定时图也是一种交互图,用来描述对象或实体随时间变化的状态或值,及其相应的时间或期限约束.定时图应用较广,并不局限于软件工程领域. 定时图侧重与时间线相关的值或状态的改变,这些改变可能来自于收到消 ...
- Opencv-Python学习笔记(二)
2. 使用OpenCV3处理图像 2.1 不同色彩空间的转换 OpenCV中有数百种关于在不同色彩空间之间转换的方法. 三种常用色彩空间:灰度.BGR.HSV(Hue色调,Saturation饱和度, ...
- 关于jqGrid组件数据显示不出问题
jqGrid组件一开始怎么数据都返回了渲染不出来,查找了一天,最后发现点击搜索之后doSearch()事件触发的方法并不是数据请求接口,而是再次请求了初次登录的接口,从初次登录返回的数据,数据格式没问 ...
- LeetCode解题录-51~100
[leetcode]51. N-QueensN皇后 Backtracking Hard [leetcode]52. N-Queens II N皇后 Backtracking Hard [leet ...
- vue学习笔记(nvm安装)
https://github.com/creationix/nvm https://github.com/coreybutler/nvm-windows 慕课网:https://www.imooc.c ...
- 线程同步的实现方式(volatile、synchronized、CountDownLatch)
题目: 自定义容器,提供新增元素(add)和获取元素数量(size)方法.启动两个线程. 线程1向容器中新增10个数据.线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止. 方法一:v ...
- Json格式获取接口返回的值
关键字:Set Variable Get Json Value to json Get From Dictionary 具体关键字用法不再说明,可百度一下 ...
- How to Reset VW Steering Assist 1S1909144P with OBDSTAR X300 DP
Vehicle model:VW Polo 2015 (or other Audi, Seat, Skoda, VW with unit 1S1 909 144 P) Module:Control u ...