在 Windows 10 中将 InkCanvas 笔画保存为 png /jpg 图像
Save InkCanvas strokes as png /jpg image in Windows 10
有没有办法将 InkCanvas
中的笔画保存到 Windows 10(UWP 应用程序)中的 png / jpg 图像中?
当然可以,只需将笔划容器保存到流中并将其写入文件即可。
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 但这是我发现如何为可能需要它的其他人做的。
如果您不想将 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;
}
最后,这里是一个异步方法,如果你想这样做,我可以使用它来对位图进行裁剪。这种方法的关键是注意如何使用这种方法,您不必首先将像素字节作为数组获取。您只需从 canvas 中获取笔画,然后将其直接保存到内存流中
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 时提供一些替代方案。
有没有办法将 InkCanvas
中的笔画保存到 Windows 10(UWP 应用程序)中的 png / jpg 图像中?
当然可以,只需将笔划容器保存到流中并将其写入文件即可。
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 但这是我发现如何为可能需要它的其他人做的。
如果您不想将 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; }
最后,这里是一个异步方法,如果你想这样做,我可以使用它来对位图进行裁剪。这种方法的关键是注意如何使用这种方法,您不必首先将像素字节作为数组获取。您只需从 canvas 中获取笔画,然后将其直接保存到内存流中
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 时提供一些替代方案。