• 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(50,50);
                        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, 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;
            }

    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, 0, 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(0);
                        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(0))
                        {
                            
                            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;
                }
            }
  • 相关阅读:
    C# 基本数据类型
    java二进制,原码、反码、补码、位运算
    .net邮件发送[c#]
    linux软件安装命令
    VB.net实现从ListView控件中异地获取文本内容源代码
    VB获得进程PID
    任意组合指令达到免杀
    免杀之等价替换法
    ASP技巧base64编码、解码函数
    看到一个思路新颖的下载者制作法
  • 原文地址:https://www.cnblogs.com/Mr-Owl/p/9112638.html
Copyright © 2020-2023  润新知