【问题标题】:Save InkCanvas strokes as png /jpg image in Windows 10在 Windows 10 中将 InkCanvas 笔画保存为 png / jpg 图像
【发布时间】:2020-04-18 20:46:39
【问题描述】:

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

【问题讨论】:

标签: c# uwp windows-10


【解决方案1】:

我知道这是一篇旧帖子,但这是我为可能需要它的其他人找到的方法。

如果您不想将 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 时提供一些替代方案。

【讨论】:

    【解决方案2】:

    当然,只需将笔画容器保存到流中并将其写入文件即可。

    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。

    【讨论】:

    • 是否可以在保存的图像中包含整个 InkCanvas 区域。墨迹的保存创建了一个矩形,它只是整个画布的一个小切口。
    • 这会创建文件,但它似乎是 gif 格式而不是 png 或 jpg。
    • 正如 tagy22 所说,它以 GIF 格式而不是 PNG 创建它,即使如果您在文件选择器中选择它,它也会以 .png 扩展名保存它。
    【解决方案3】:

    您要问的是拍摄屏幕快照。在这种情况下,RenderTargetBitmap 似乎可以提供帮助。它可以将任意 UIElement 渲染为位图。你可以参考我在这个post的回复。

    【讨论】:

    • 我已经尝试使用 RenderTargetBitmap 将 InkCanvas 的内容保存为图像,问题是它不适用于 UWP(Windows 10)中的 InkCanvas。
    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 2012-06-27
    • 2017-04-16
    • 2014-03-21
    • 1970-01-01
    相关资源
    最近更新 更多