我的《上海轨道交通》UWP版中有个“保存运营线路图”的功能,可以把工程目录底下“Assets\shanghaimetro-xl.jpg”存到用户的设备上,并且让用户选择一个保存位置:
这是个比较常见的功能,在UWP里实现也不复杂。最简单的是安装我的Edi.UWP.Helpers库:http://www.nuget.org/packages/Edi.UWP.Helpers/
GayHub地址:https://github.com/EdiWang/UWP-Helpers/
里面的BitmapExtensions有个拓展方法叫做
public static Task<FileUpdateStatus> SaveToPngImage(this WriteableBitmap bitmap, PickerLocationId location, string fileName);
因为接受的参数是WriteableBitmap,所以第一步是需要把工程底下的图片文件转换为WriteableBitmap格式:
public static async Task<WriteableBitmap> LoadWriteableBitmap(string relativePath) { var storageFile = await Package.Current.InstalledLocation.GetFileAsync(relativePath.Replace('/', '\\')); var stream = await storageFile.OpenReadAsync(); var wb = new WriteableBitmap(1, 1); wb.SetSource(stream); return wb; }
然后就可以调用那个拓展方法保存了:
var rmbp = await Helper.LoadWriteableBitmap("Assets/shanghaimetro-xl.jpg"); await rmbp.SaveToPngImage(PickerLocationId.PicturesLibrary, "shmetro");
具体的实现代码如下(也可以到我的gayhub上去看):
public static async Task<FileUpdateStatus> SaveToPngImage(this WriteableBitmap bitmap, PickerLocationId location, string fileName) { var savePicker = new FileSavePicker { SuggestedStartLocation = location }; savePicker.FileTypeChoices.Add("Png Image", new[] { ".png" }); savePicker.SuggestedFileName = fileName; StorageFile sFile = await savePicker.PickSaveFileAsync(); if (sFile != null) { CachedFileManager.DeferUpdates(sFile); using (var fileStream = await sFile.OpenAsync(FileAccessMode.ReadWrite)) { BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream); Stream pixelStream = bitmap.PixelBuffer.AsStream(); byte[] pixels = new byte[pixelStream.Length]; await pixelStream.ReadAsync(pixels, 0, pixels.Length); encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, pixels); await encoder.FlushAsync(); } FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(sFile); return status; } return FileUpdateStatus.Failed; }
有这么几点要说明:
1. 因为我��,只写了png格式,大家可以自己扩充,注意BitmapEncoder.PngEncoderId这个也得改成对应格式的。
2. 为了防止异步爆炸和另一个线程访问图片文件的情况,得用CachedFileManager.DeferUpdates和CachedFileManager.CompleteUpdatesAsync
3. 因为是设计助手类库给别人爆,所以没有写try-catch,以便调用者自己管理异常情况,请注意异常处理。