Windows InkCanvas generic strokes disappear on RenderTargetBitmap.RenderAsync

I'm trying to do the InkCanvas RenderTargetBitmap strokes in a Universal Windows 10 app. Here is my xaml code:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="10" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid x:Name="container">
        <Rectangle Fill="LightBlue" />
        <InkCanvas x:Name="InkCanvas" />
    </Grid>

    <Image Grid.Row="2" x:Name="TheImage" />

    <Button Grid.Row="3" Content="CopyToRendertargt" Click="Button_Click" />

</Grid>

      

And here is my code to set the Image.Source property:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        InkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse;
    }


    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        RenderTargetBitmap renderTarget = new RenderTargetBitmap();

        await renderTarget.RenderAsync(this.container);

        this.TheImage.Source = renderTarget;
    }

}

      

When I click the button, the strokes I made on the InkCanvas disappear and the InkCanvas forzen resizes the application window. Templates are not displayed in RenderTargetBitmap. The image only shows the LightBlue rectangle.

Does anyone have a solution for this?

** UPDATE **

For anyone looking for the right way to save strokes to a bitmap on uwp. I found a UWP way to save InkCanvas Strokes to a bitmap: the InkStrokeContainer object has a SaveAsync (...) method that saves strokes to a stream. If you use this stream as the source for a bitmap, you get the strokes as a bitmap.

        InkStrokeContainer container = TheInkCanvas.InkPresenter.StrokeContainer;
        WriteableBitmap bmp;
        using (InMemoryRandomAccessStream ims =
            new InMemoryRandomAccessStream())
        {
            await container.SaveAsync(ims);
            bmp = await new WriteableBitmap(1, 1)
                .FromStream(ims, BitmapPixelFormat.Bgra8);
        }

      

* Note: WriteableBitmapEx is used in this code example ( https://www.nuget.org/packages/WriteableBitmapEx/ )

+3


source to share


2 answers


The XAML visual and RenderTargetBitmap section of the RenderTargetBitmap documentation describes: Content that cannot be captured will render as blank in the captured image, but other content in the same visual tree can still be captured and displayed (the presence of content that cannot be captured, will not invalidate the entire capture of that XAML composition). Thus, it may be that the content of the InkCanvas is not available for capture.



An alternative is to use Win2D (Microsoft's Direct2D.NET wrapper). Win2D can be used in a UWP app via the nuget package. You will be able to manage ink strokes and save them in an image (jpeg, png and other formats).

0


source


You can use Win2D to render strokes.

  • Add Win2D.uwp to project from NuGet
  • Add this InkCanvasExtensions.cs file to your project
  • Change namespace or add using Zoetrope;

    to source
  • Create an image file or stream and pass it to InkCanvas.RenderAsync ()


InkCanvasExtensions.cs

namespace Zoetrope
{
    using System;
    using System.Threading.Tasks;
    using Microsoft.Graphics.Canvas;
    using Windows.Graphics.Display;
    using Windows.Storage.Streams;
    using Windows.UI;
    using Windows.UI.Xaml.Controls;

    /// <summary>
    /// InkCanvas Extensions
    /// </summary>
    public static class InkCanvasExtensions
    {
        /// <summary>
        /// Render an InkCanvas to a stream
        /// </summary>
        /// <param name="inkCanvas">the ink canvas</param>
        /// <param name="fileStream">the file stream</param>
        /// <param name="backgroundColor">the background color</param>
        /// <param name="fileFormat">the file format</param>
        /// <returns>an async task</returns>
        public static async Task RenderAsync(
            this InkCanvas inkCanvas, 
            IRandomAccessStream fileStream, 
            Color backgroundColor,
            CanvasBitmapFileFormat fileFormat)
        {
            // do not put in using{} structure - it will close the shared device.
            var device = CanvasDevice.GetSharedDevice();
            var width = (float) inkCanvas.ActualWidth;
            var height = (float) inkCanvas.ActualHeight;
            var currentDpi = DisplayInformation.GetForCurrentView().LogicalDpi;

            using (var offscreen = new CanvasRenderTarget(device, width, height, currentDpi))
            {
                using (var session = offscreen.CreateDrawingSession())
                {
                    session.Clear(backgroundColor);

                    session.DrawInk(inkCanvas.InkPresenter.StrokeContainer.GetStrokes());
                }

                await offscreen.SaveAsync(fileStream, fileFormat);
            }
        }
    }
}

      

+2


source







All Articles