[uwp]ImageSource和byte[]相互转换
最近做一个小app遇到一个问题,到目前还没有比较好的解决方法(可能是我查的资料不够多)
需求如下:
1.把一个Image中的图像保存到字节数组;
2.把字节数组转换为ImageSource,通过Image控件展示图像.
上面两个需求恰恰是相反的过程,为了实现这个,我倒网上找了好多,但基本都是wp7,wp8,wpf的方案,在win10上没法用。。纠结。
后来在知乎日报uwp的源码中发现了一个把ImageSource存储为文件的方法。(github:https://github.com/sherlockchou86/ZhiHuDaily.UWP),感谢作者为win10生态圈的贡献。
代码如下:
public async Task SaveImageAsync(WriteableBitmap image, string filename)
{
try
{
if (image == null)
{
return;
}
Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
if(filename.EndsWith("jpg"))
BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
else if(filename.EndsWith("png"))
BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
else if(filename.EndsWith("bmp"))
BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
else if(filename.EndsWith("tiff"))
BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
else if(filename.EndsWith("gif"))
BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
var folder = await _local_folder.CreateFolderAsync("images_cache", CreationCollisionOption.OpenIfExists);
var file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting); using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = image.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, , pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)image.PixelWidth,
(uint)image.PixelHeight,
96.0,
96.0,
pixels);
await encoder.FlushAsync();
}
}
catch
{ }
}
SaveImageAsync
有了这个,我的需求就能解决了,因为在上面的代码中,有一个随机访问流ras,所以我们可以把ras利用拓展方法AsStream()转化为普通的流,然后用Read()或者ReadAsync()读取到字节数组即可。
于是需求一的代码如下:
public static async Task<byte[]> SaveToBytesAsync(this ImageSource imageSource)
{
byte[] imageBuffer;
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var file = await localFolder.CreateFileAsync("temp.jpg", CreationCollisionOption.ReplaceExisting);
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;
}
值得注意的几点:
1.用了拓展方法;
2.ImageSource一般可以通过BitmapImage和WriteableImage来设置,但这儿只能用WriteableImage,因为要用到接口IWriteableBitmap;
3.ras随机访问流转为普通FCL普通流后,用Seek将Positon设置到0,读出的数据出错;
4.注意图像编码的设置,这儿只针对jpeg格式;
5.这是一个投机的办法,先存储为文件,再存储为字节数组,但核心还是一个ras(IRandomAccessSteam).
需求二代码如下:
public static async Task<ImageSource> SaveToImageSource(this byte[] imageBuffer)
{
ImageSource imageSource = null;
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;
}
return imageSource;
}
注意点如下:
1.解码用的还是jpeg;
2.还是用的WriteableBitmap,主要还是他的接口决定的;
tips:如果照的上面的代码写,某些方法或属性下面还是有红色波浪线的话,记着选中它,然后按Shift+alt+F10,Visual Studio帮你解决。
[uwp]ImageSource和byte[]相互转换的更多相关文章
- 【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题
C#/WPF项目中,用到图像相关的功能时,涉及到多种图像数据类型的相互转换问题,这里做了个整理.包含的内容如下: Bitmap和BitmapImage相互转换. RenderTargetBitmap ...
- dword word byte 相互转换 .xml
pre{ line-height:1; color:#800080; background-color:#d2c39b; font-size:16px;}.sysFunc{color:#627cf6; ...
- C#中string和byte[]相互转换问题解决
本来想讲string转换为byte数组,通过在VS上打 ‘str. “来找,结果半天没发现跳出来的函数中有想要的,哭瞎 /(ㄒoㄒ)/~~ 这回将两种情况都记下来了.... string ---> ...
- WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换
1 WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换 2012-12-18 17:27:04| 分类: Windows Phone 8|字号 订 ...
- java 中 image 和 byte[] 相互转换
java 中 image 和 byte[] 相互转换可恶的…………其实也挺好的 只是把好不容易写出来的东西记下来,怕忘了…… 下面,我来介绍一个简单的 byte[] to image, 我们只需要 ...
- String 与 byte[]相互转换
1. 从byte[]转换成string string result = System.Text.Encoding.UTF8.GetString(byteArray); 2.从string 转换成byt ...
- C#中字符串与byte[]相互转换
字符串转换为byte[] 给定一个string,转换为byte[],有以下几种方法. 方法1: static byte[] GetBytes(string str) { byte[] bytes = ...
- C#图像处理:Stream 与 byte[] 相互转换,byte[]与string,Stream 与 File 相互转换等
C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...
- 2015.5.11 string与byte[]相互转换
string类型转成byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str ); 反过来,byte[]转成stri ...
随机推荐
- OpenCL 事件的使用,以及回调函数
▶ 事件的两种使用方法.第一种是用事件 a 标记进入命令队列的操作 A,于是后续进入命令队列的操作 B 可以被要求等到前面事件 a 完成(即操作 A 完成)以后才能开始调度执行.第二种是使用用户自定义 ...
- MyEclipse编译报:javaScript Validator错误
转自:https://blog.csdn.net/lkpmemory/article/details/8833329 Myeclipse编译报错如下: Errors occurred during t ...
- 再谈C#编码规范
编码规范是老生常谈的问题,现在再看代码规范可能不会再去在意变量,控件的命名方法等,而是更加关注代码的实用性. 首先我们要明白一下几点, 1.代码写出来除了让他跑起来还有个非常非常重要的作用是维护,因为 ...
- win bat命令后台运行控制台应用
@echo off if "%1"=="h" goto begin start mshta vbscript:createobject()(window.clo ...
- Spring IoC底层原理
-------------------siwuxie095 Spring IoC 底层原理 1.IoC 即 Invers ...
- for 续8
---------siwuxie095 一个问题分析: 在 CMD 窗口输入: dir dir /b dir /b /ah dir C:\Windows dir C:\ ...
- Java 设计模式系列(五)原型模式
Java 设计模式系列(五)原型模式 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 一.原型模 ...
- Oracle GoldenGate 三、加密
写在开始前 从上周开始,我花了大量的业余时间阅读GoldenGate官方文档,并根据文档实践和进一步学习了解GoldenGate,以下便是根据官方文档理解总结的GoldenGate学习内容: Orac ...
- CentOS7通过 yum安装路径查询方法
CentOS7通过 yum安装路径查询方法 rpm -qa 然后执行 rpm -ql 软件名称 就可以显示软件的安装路径. 原文博客的链接地址:https://cnblogs.com/qzf/
- C++ 类 & 对象-C++ 内联函数-C++ this 指针-C++ 类的静态成员
C++ 内联函数 C++ 内联函数是通常与类一起使用.如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方. 对内联函数进行任何修改,都需要重新编译函数的所有客户端 ...