在Windows 10中将InkCanvas笔划保存为png/jpg图像

本文关键字:png jpg 图像 保存 Windows 中将 InkCanvas | 更新日期: 2023-09-27 18:20:34

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

在Windows 10中将InkCanvas笔划保存为png/jpg图像

我知道这是一篇旧帖子,但以下是我为其他可能需要它的人做这件事的方法。

如果您不想将InkCanvas保存为文件或GIF,请在内存中进行操作。实际上我有三个选择。请注意,对于其中的一些内容,您需要添加对Win2D.uwp的引用,可以在NuGet上搜索该名称。它由微软提供。

  1. 将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. 若您只需要一个像素的字节数组,那个么您就完成了。然而,如果你现在想生成一个图像,你可以使用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;
    }
    
  3. 最后,这里有一个异步方法,如果你想在位图上进行裁剪,我可以使用它。这个方法的关键是要注意,使用这个方法,您不必首先将像素字节作为数组。您只需从画布中获取笔划,然后将其直接保存到内存流中

    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示例可以在此处找到。

您想要的是拍摄屏幕快照。在这种情况下,RenderTargetBitmap似乎会有所帮助。它可以将任意UIElement渲染为位图。你可以参考我在这篇文章中的回复。