UWP關於圖片緩存的那些破事兒

看似簡單的功能,實施起來倒是有着一堆大坑。json

按着基本功能來寫吧數組

1.選擇圖片並顯示到Image控件中網絡

2.圖片序列化爲byte數組以及反序列化dom

3.本地存儲與讀取async

 

 

1.選擇圖片:ide

   邏輯就是使用FileOpenPicker選擇一個圖片文件後,將該文件從StorageFile對象轉化成能夠賦值給Image.Source的ImageSource類的對象。ui

這裏須要注意的是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)this

   1.1 選取圖片文件並實例化爲WriteableBitmap對象spa

   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對象code

 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;
            }
        }
相關文章
相關標籤/搜索