Windows 10 UWP的InkCanvas控件不能像WPF那样保存图片了,各种bitmap OOXX都会爆,要保存为图片文件,目前一个可行的方法如下:
1. 首先,通过NuGet安装Win2D.UWP的包:
PM> Install-Package Win2D.UWP
2. 因为我们要访问用户的图片文件夹,所以得在工程的manifest文件里申请对picture library的访问权限。
在项目属性对话框里点“Package Manifest”
在弹出的页面里选择Capablities底下的Pictures Library.
3. 在页面上创建一个InkCanvas和一个保存按钮,XAML代码如下:
<Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <InkCanvas Grid.Row="0" x:Name="MyInkCanvas" /> <Button Grid.Row="1" Content="Save" Click="BtnSave_Click" />
4. BtnSave_Click的后台代码
首先,和Windows 8.1开发一样,我们需要获得StorageFolder和StorageFile对象。文件夹选择了“已保存的图片“
StorageFolder storageFolder = KnownFolders.SavedPictures; var file = await storageFolder.CreateFileAsync("sample.jpg", CreationCollisionOption.ReplaceExisting);
在这里我hard code了一个sample.jpg,并且设置为遇到重名文件就覆盖,即ReplaceExisting。
因为这里用到了await,所以得把事件改async void:
private async void BtnSave_Click(object sender, RoutedEventArgs e)
不过要注意,async void仅用于event handler,平时请用async Task及async Task<T>,不然容易爆。
然后就要用到Win2D了:
CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int)MyInkCanvas.ActualWidth, (int)MyInkCanvas.ActualHeight, 96);
CanvasRenderTarget的参数分别是:resourceCreator(即device对象),画布宽度,画布高度,DPI(分辨率)
然后需要把墨迹塞到DrawingSession对象里去:
using (var ds = renderTarget.CreateDrawingSession()) { ds.Clear(Colors.White); ds.DrawInk(MyInkCanvas.InkPresenter.StrokeContainer.GetStrokes()); }
这里的ds.Clear(Colors.White);的意思是用白色填充画布,所以我们保存的图片并不是透明色的。
最后保存为JPG格式的图片,最后的1f是画质,float类型所以加个f。
using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) { await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Jpeg, 1f); }
其实不仅仅可以保存为jpg,CanvasBitmapFileFormat枚举还支持这些格式:
Auto = 0, Bmp = 1, Png = 2, Jpeg = 3, Tiff = 4, Gif = 5, JpegXR = 6
5. 运行成功,墨迹可以被保存到了用户目录的图片文件夹-已保存的图片下面。
工程github地址:https://github.com/EdiWang/Demo-UWP-InkCanvas-Save-Jpg/tree/master