有没有办法在Windows 10(UWP应用)中将笔画从InkCanvas
保存到png / jpg图像?
答案 0 :(得分:1)
我知道这是一篇很老的帖子,但我发现这是为那些可能需要它的人做的。
如果您不想将InkCanvas保存到文件或GIF,请在内存中操作它。我实际上有三个选项。注意,对于其中一些,您需要添加对Win2D.uwp的引用,可以通过搜索确切的名称在NuGet上找到它。它由Microsoft提供。
将InkCanvas转换为字节数组:
private byte[] ConvertInkCanvasToByteArray()
{
var canvasStrokes = cvsSignature.InkPresenter.StrokeContainer.GetStrokes();
if (canvasStrokes.Count > 0)
{
var width = (int)cvsSignature.ActualWidth;
var height = (int)cvsSignature.ActualHeight;
var device = CanvasDevice.GetSharedDevice();
var renderTarget = new CanvasRenderTarget(device, width,
height, 96);
using (var ds = renderTarget.CreateDrawingSession())
{
ds.Clear(Windows.UI.Colors.White);
ds.DrawInk(cvsSignature.InkPresenter.StrokeContainer.GetStrokes());
}
return renderTarget.GetPixelBytes();
}
else
{
return null;
}
}
如果您只需要像素的字节数组,那么您就完成了。但是,如果您现在要生成图像,则使用WriteableBitmap执行此操作。以下是可以调用的同步和异步方法。
private WriteableBitmap GetSignatureBitmapFull()
{
var bytes = ConvertInkCanvasToByteArray();
if (bytes != null)
{
var width = (int)cvsSignature.ActualWidth;
var height = (int)cvsSignature.ActualHeight;
var bmp = new WriteableBitmap(width, height);
using (var stream = bmp.PixelBuffer.AsStream())
{
stream.Write(bytes, 0, bytes.Length);
return bmp;
}
}
else
return null;
}
private async Task<WriteableBitmap> GetSignatureBitmapFullAsync()
{
var bytes = ConvertInkCanvasToByteArray();
if (bytes != null)
{
var width = (int)cvsSignature.ActualWidth;
var height = (int)cvsSignature.ActualHeight;
var bmp = new WriteableBitmap(width, height);
using (var stream = bmp.PixelBuffer.AsStream())
{
await stream.WriteAsync(bytes, 0, bytes.Length);
return bmp;
}
}
else
return null;
}
最后,这是一个异步方法,我正在使用它来在位图上进行裁剪,如果你想这样做的话。这种方法的关键在于注意如何使用这种方法,首先不必将像素字节作为数组。您只需从画布中获取笔画,然后将其直接保存到内存流中
private async Task<WriteableBitmap> GetSignatureBitmapCropped()
{
try
{
var canvasStrokes = cvsSignature.InkPresenter.StrokeContainer.GetStrokes();
if (canvasStrokes.Count > 0)
{
var bounds = cvsSignature.InkPresenter.StrokeContainer.BoundingRect;
var xOffset = (uint)Math.Round(bounds.X);
var yOffset = (uint)Math.Round(bounds.Y);
var pixelWidth = (int)Math.Round(bounds.Width);
var pixelHeight = (int)Math.Round(bounds.Height);
using (var memStream = new InMemoryRandomAccessStream())
{
await cvsSignature.InkPresenter.StrokeContainer.SaveAsync(memStream);
var decoder = await BitmapDecoder.CreateAsync(memStream);
var transform = new BitmapTransform();
var newBounds = new BitmapBounds();
newBounds.X = 0;
newBounds.Y = 0;
newBounds.Width = (uint)pixelWidth;
newBounds.Height = (uint)pixelHeight;
transform.Bounds = newBounds;
var pdp = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
transform,
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
var pixels = pdp.DetachPixelData();
var cropBmp = new WriteableBitmap(pixelWidth, pixelHeight);
using (var stream = cropBmp.PixelBuffer.AsStream())
{
await stream.WriteAsync(pixels, 0, pixels.Length);
}
return cropBmp;
}
}
else
{
return null;
}
}
catch (Exception ex)
{
return null;
}
}
希望这有助于在Windows 10 Universal中使用InkCanvas时提供一些替代方案。
答案 1 :(得分:0)
当然,只需将笔划容器保存到流中并将其写入文件即可。
if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0)
{
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("PNG", new System.Collections.Generic.List<string> { ".png" });
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
if (null != file)
{
try
{
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(stream);
}
}
catch (Exception ex)
{
}
}
}
可以找到更多InkCanvas样本here。
答案 2 :(得分:0)
你所要求的是拍摄屏幕快照。在这种情况下,RenderTargetBitmap似乎可以提供帮助。它可以将任意UIElement渲染为位图。您可以参考我的回复post。