【发布时间】:2020-04-18 20:46:39
【问题描述】:
有没有办法将InkCanvas 中的笔划保存到 Windows 10(UWP 应用)中的 png / jpg 图像中?
【问题讨论】:
标签: c# uwp windows-10
有没有办法将InkCanvas 中的笔划保存到 Windows 10(UWP 应用)中的 png / jpg 图像中?
【问题讨论】:
标签: c# uwp windows-10
我知道这是一篇旧帖子,但这是我为可能需要它的其他人找到的方法。
如果您不想将 InkCanvas 保存为文件或 GIF,请在内存中对其进行操作。我实际上有以下三个选择。请注意,对于其中的某些内容,您需要添加对 Win2D.uwp 的引用,可以通过搜索该确切名称在 NuGet 上找到该引用。它由微软提供。
将 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 时提供一些替代方案。
【讨论】:
当然,只需将笔画容器保存到流中并将其写入文件即可。
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。
【讨论】:
您要问的是拍摄屏幕快照。在这种情况下,RenderTargetBitmap 似乎可以提供帮助。它可以将任意 UIElement 渲染为位图。你可以参考我在这个post的回复。
【讨论】: