最近做一个小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[]相互转换的更多相关文章

  1. 【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题

    C#/WPF项目中,用到图像相关的功能时,涉及到多种图像数据类型的相互转换问题,这里做了个整理.包含的内容如下: Bitmap和BitmapImage相互转换. RenderTargetBitmap ...

  2. dword word byte 相互转换 .xml

    pre{ line-height:1; color:#800080; background-color:#d2c39b; font-size:16px;}.sysFunc{color:#627cf6; ...

  3. C#中string和byte[]相互转换问题解决

    本来想讲string转换为byte数组,通过在VS上打 ‘str. “来找,结果半天没发现跳出来的函数中有想要的,哭瞎 /(ㄒoㄒ)/~~ 这回将两种情况都记下来了.... string ---> ...

  4. WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换

    1 WriteableBitmap/BitmapImage/MemoryStream/byte[]相互转换 2012-12-18 17:27:04|  分类: Windows Phone 8|字号 订 ...

  5. java 中 image 和 byte[] 相互转换

      java 中 image 和 byte[] 相互转换可恶的…………其实也挺好的 只是把好不容易写出来的东西记下来,怕忘了…… 下面,我来介绍一个简单的 byte[] to image, 我们只需要 ...

  6. String 与 byte[]相互转换

    1. 从byte[]转换成string string result = System.Text.Encoding.UTF8.GetString(byteArray); 2.从string 转换成byt ...

  7. C#中字符串与byte[]相互转换

    字符串转换为byte[] 给定一个string,转换为byte[],有以下几种方法. 方法1: static byte[] GetBytes(string str) { byte[] bytes = ...

  8. C#图像处理:Stream 与 byte[] 相互转换,byte[]与string,Stream 与 File 相互转换等

    C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...

  9. 2015.5.11 string与byte[]相互转换

    string类型转成byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str ); 反过来,byte[]转成stri ...

随机推荐

  1. OpenCL 事件的使用,以及回调函数

    ▶ 事件的两种使用方法.第一种是用事件 a 标记进入命令队列的操作 A,于是后续进入命令队列的操作 B 可以被要求等到前面事件 a 完成(即操作 A 完成)以后才能开始调度执行.第二种是使用用户自定义 ...

  2. MyEclipse编译报:javaScript Validator错误

    转自:https://blog.csdn.net/lkpmemory/article/details/8833329 Myeclipse编译报错如下: Errors occurred during t ...

  3. 再谈C#编码规范

    编码规范是老生常谈的问题,现在再看代码规范可能不会再去在意变量,控件的命名方法等,而是更加关注代码的实用性. 首先我们要明白一下几点, 1.代码写出来除了让他跑起来还有个非常非常重要的作用是维护,因为 ...

  4. win bat命令后台运行控制台应用

    @echo off if "%1"=="h" goto begin start mshta vbscript:createobject()(window.clo ...

  5. Spring IoC底层原理

    -------------------siwuxie095                                 Spring IoC 底层原理         1.IoC 即 Invers ...

  6. for 续8

    ---------siwuxie095                 一个问题分析: 在 CMD 窗口输入: dir dir /b dir /b /ah dir C:\Windows dir C:\ ...

  7. Java 设计模式系列(五)原型模式

    Java 设计模式系列(五)原型模式 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 一.原型模 ...

  8. Oracle GoldenGate 三、加密

    写在开始前 从上周开始,我花了大量的业余时间阅读GoldenGate官方文档,并根据文档实践和进一步学习了解GoldenGate,以下便是根据官方文档理解总结的GoldenGate学习内容: Orac ...

  9. CentOS7通过 yum安装路径查询方法

    CentOS7通过 yum安装路径查询方法 rpm -qa 然后执行 rpm -ql 软件名称 就可以显示软件的安装路径. 原文博客的链接地址:https://cnblogs.com/qzf/

  10. C++ 类 & 对象-C++ 内联函数-C++ this 指针-C++ 类的静态成员

    C++ 内联函数 C++ 内联函数是通常与类一起使用.如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方. 对内联函数进行任何修改,都需要重新编译函数的所有客户端 ...