我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap。关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说。主要说的是 BitmapImage 和 WriteableBitmap 、二进制 byte 的互转。
我们先写一个简单的xaml
<Image x:Name="Img" Height="200" Width="200" HorizontalAlignment="Center" Source="Assets/SplashScreen.png" ></Image> <Button Margin="10,300,10,10" Content="确定" Click="Button_OnClick" ></Button>用到的图片是我新建自带的。
保存 WriteableBitmap 到文件 private static async Task SaveWriteableBitmapImageFile(WriteableBitmap image, StorageFile file) { //BitmapEncoder 存放格式 Guid bitmapEncoderGuid = BitmapEncoder.JpegEncoderId; string filename = file.Name; 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; } using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.None)) { 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); //Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(imgstream); //Windows.Graphics.Imaging.PixelDataProvider pxprd = await decoder.GetPixelDataAsync(Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8, Windows.Graphics.Imaging.BitmapAlphaMode.Straight, new Windows.Graphics.Imaging.BitmapTransform(), Windows.Graphics.Imaging.ExifOrientationMode.RespectExifOrientation, Windows.Graphics.Imaging.ColorManagementMode.DoNotColorManage); await encoder.FlushAsync(); } } 从文件读 WriteableBitmap private static async Task<WriteableBitmap> OpenWriteableBitmapFile(StorageFile file) { using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); WriteableBitmap image = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); image.SetSource(stream); return image; } } ImageSource 转byte[]ImageSource可以是 BitmapImage 、WriteableBitmap,如果是WriteableBitmap ,那么直接转换
WriteableBitmap 转byte[]
bitmap.PixelBuffer.ToArray(); Image 转byte[]如果我们的 ImageSource 是 BitmapImage ,那么我们不能使用上面的办法,直接保存 WriteableBitmap ,我们可以使用截图
private async Task<string> ToBase64(Image control) { var bitmap = new RenderTargetBitmap(); await bitmap.RenderAsync(control); return await ToBase64(bitmap); }如果 ImageSource 是 WriteableBitmap ,直接保存
我们使用 byte[] 在传输时不好,,不能用在 http 传输上(不是一定的不能),所以我们就把它转为base64,我提供了很多方法把数组转 base64 ,把文件转为 base64 。代码是 https://codepaste.net/ijx28i 抄的。
//WriteableBitmap 转 byte[] private async Task<string> ToBase64(WriteableBitmap bitmap) { var bytes = bitmap.PixelBuffer.ToArray(); return await ToBase64(bytes, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight); } private async Task<string> ToBase64(StorageFile bitmap) { var stream = await bitmap.OpenAsync(Windows.Storage.FileAccessMode.Read); var decoder = await BitmapDecoder.CreateAsync(stream); var pixels = await decoder.GetPixelDataAsync(); var bytes = pixels.DetachPixelData(); return await ToBase64(bytes, (uint)decoder.PixelWidth, (uint)decoder.PixelHeight, decoder.DpiX, decoder.DpiY); } private async Task<string> ToBase64(RenderTargetBitmap bitmap) { var bytes = (await bitmap.GetPixelsAsync()).ToArray(); return await ToBase64(bytes, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight); } private async Task<string> ToBase64(byte[] image, uint height, uint width, double dpiX = 96, double dpiY = 96) { // encode image var encoded = new InMemoryRandomAccessStream(); var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, encoded); encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, height, width, dpiX, dpiY, image); await encoder.FlushAsync(); encoded.Seek(0); // read bytes var bytes = new byte[encoded.Size]; await encoded.AsStream().ReadAsync(bytes, 0, bytes.Length); // create base64 return Convert.ToBase64String(bytes); } private async Task<ImageSource> FromBase64(string base64) { // read stream var bytes = Convert.FromBase64String(base64); var image = bytes.AsBuffer().AsStream().AsRandomAccessStream(); // decode image var decoder = await BitmapDecoder.CreateAsync(image); image.Seek(0); // create bitmap var output = new WriteableBitmap((int)decoder.PixelHeight, (int)decoder.PixelWidth); await output.SetSourceAsync(image); return output; }