[uwp]ImageSource和byte[]相互转换

简介: 原文:[uwp]ImageSource和byte[]相互转换最近做一个小app遇到一个问题,到目前还没有比较好的解决方法(可能是我查的资料不够多) 需求如下: 1.把一个Image中的图像保存到字节数组; 2.把字节数组转换为ImageSource,通过Image控件展示图像. 上面两个需求恰恰是相反的过程,为了实现这个,我倒网上找了好多,但基本都是wp7,wp8,wpf的方案,在win10上没法用。
原文: [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, 0, 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, 0, 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(0, SeekOrigin.Begin);
                imageBuffer = new byte[imageStream.Length];
                var re = await imageStream.ReadAsync(imageBuffer, 0, 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, 0, buffer.Length);
                imageSource = bitmap;
            }
            return imageSource;
        }

 

注意点如下:

  1.解码用的还是jpeg;

  2.还是用的WriteableBitmap,主要还是他的接口决定的;

 

tips:如果照的上面的代码写,某些方法或属性下面还是有红色波浪线的话,记着选中它,然后按Shift+alt+F10,Visual Studio帮你解决。

目录
相关文章
|
C#
【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题
原文:【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题 C#/WPF项目中,用到图像相关的功能时,涉及到多种图像数据类型的相互转换问题,这里做了个整理。
4403 0
C# string类型和byte[]类型相互转换
string类型转成byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str ); byte[]转成string: string str = System.
1531 0
|
BI
Byte[]、Image、Bitmap 之间的相互转换
原文:Byte[]、Image、Bitmap 之间的相互转换 ///         /// 将图片Image转换成Byte[]        ///         /// image对象        /// 后缀名        ///         public static byte[] ImageToBytes(Image Image, System.
1404 0
|
Java 索引
java中byte数组与十六进制字符串相互转换
<p>最近在做加密算法的研究和使用,经常会用到byte数组和十六进制字符串的转换。之前对于此类问题我一般都是使用BigInteger这个类转换一下算了,这样为了看输出不是乱码。这其实都不是根本上的解决方案。</p> <p>最简单的转换方法:</p> <p style=""></p> <pre code_snippet_id="328081" snippet_file_name="bl
2777 0
|
5月前
|
Java
java 读取文件 获取byte[]字节 并执行Gzip的压缩和解压
java 读取文件 获取byte[]字节 并执行Gzip的压缩和解压
49 0
|
8月前
|
存储 Java 计算机视觉
java 之byte
当涉及到处理数据时,Java 提供了多种数据类型,其中包括 `byte` 类型。在本文中,我们将深入探讨 Java 中的 `byte` 数据类型,了解它的特点、用途以及在编程中的实际应用。
|
8月前
|
Java
Java中 String与基本数据类型,包装类,char[],byte[]之间的转换
Java中 String与基本数据类型,包装类,char[],byte[]之间的转换
55 0
|
10月前
|
存储 Java
[java 基础知识] byte int 互转
[java 基础知识] byte int 互转
97 0