简体   繁体   English

在 Windows 10 中将 InkCanvas 笔画另存为 png /jpg 图像

[英]Save InkCanvas strokes as png /jpg image in Windows 10

有没有办法在 Windows 10(UWP 应用程序)中将InkCanvas笔画保存为 png/jpg 图像?

I know this is an old post but here is how I found to do it for others who might need it.我知道这是一篇旧帖子,但这是我发现如何为可能需要它的其他人做的。

If you don't want to save your InkCanvas to a file or as a GIF, to manipulate it in memory.如果您不想将 InkCanvas 保存为文件或 GIF,请在内存中对其进行操作。 I actually have three options below.我实际上有以下三个选项。 Note, for some of this, you will need to add a reference to Win2D.uwp, which can be found on NuGet by searching that exact name.请注意,对于其中的某些内容,您需要添加对 Win2D.uwp 的引用,该引用可以通过搜索确切名称在 NuGet 上找到。 It is provided by Microsoft.它由微软提供。

  1. Convert the InkCanvas to a byte array:将 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; } }
  2. If all you need is a byte array of the pixels, you are done.如果您只需要一个像素的字节数组,那么您就完成了。 However, if you now want to generate an image, you use the WriteableBitmap to do so.但是,如果您现在想要生成图像,则可以使用 WriteableBitmap 来执行此操作。 Here are sync and async methods that can be called to do this.以下是可以调用来执行此操作的同步和异步方法。

     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; }
  3. Finally, here is an async method that I am using to be able to do a crop on the bitmap if you want to do that.最后,这是一个异步方法,如果您想这样做,我可以使用它来对位图进行裁剪。 The key thing with this method is notice how with this approach, you don't have to get the pixel bytes as an array first.这种方法的关键是注意如何使用这种方法,您不必首先将像素字节作为数组获取。 You just get the strokes from the canvas and then it is saved directly into a memory stream您只需从画布中获取笔划,然后将其直接保存到内存流中

    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; } }

Hope this helps provide some alternatives when using InkCanvas in Windows 10 Universal.希望这有助于在 Windows 10 Universal 中使用 InkCanvas 时提供一些替代方案。

Sure, just save the stroke container to a stream and write it to a file.当然,只需将笔画容器保存到流并将其写入文件。

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)
        {
        }
    }
}

More InkCanvas samples can be found here .可以在此处找到更多 InkCanvas 示例。

What you are asking is kind of taking screen snapshot.您要问的是拍摄屏幕快照。 In that case, RenderTargetBitmap seems can help.在这种情况下,RenderTargetBitmap 似乎可以提供帮助。 It can render an arbitrary UIElement into a bitmap.它可以将任意 UIElement 渲染为位图。 You can refer to my reply in this post .你可以参考我在这篇文章中的回复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM