13

The RenderTargetBitmap class worked with simple Canvas + InkManager (in Windows 8.1) to render ink strokes to an image. UWP introduced InkCanvas and a new Inking API. However, it seems like the RenderTargetBitmap does not work with that. When I try to capture ink strokes with RenderAsync method, no ink strokes get rendered only other objects like Rectangle and so on.

Is it a bug or this new API is not meant to be used this way? If not, then how can I render an image out of InkCanvas?

Thanks!

Artem Kulikov
  • 2,250
  • 19
  • 32
mudbox
  • 301
  • 2
  • 7
  • [inkCanvas].InkPresenter.StrokeContainer.SaveAsync can save as a .gif – tao Aug 22 '15 at 08:29
  • 1
    Yes, I'm aware of that. However, I guess it's an ISF (Ink Stroke Format) embedded in a .gif. The gif itself very ugly when opened, I can't use that. I definitely want to use RenderTargetBitmap, but it does not work as expected. I also tried decode the gif with BitmapDecoder, get the pixel data and encode it with BitmapEncoder to another format, also with no luck (it contains only zeros, the whole image is black). What I really want is to render a png or jpg image from it with white background for example. Maybe manipulate it later. Can anyone help? – mudbox Aug 22 '15 at 11:37
  • 1
    I tried to get back to the older InkManager + Canvas combination, but InkManager throws COM Exception when instantiated. – mudbox Aug 22 '15 at 11:41
  • 1
    OK, I'll have a solution which includes Win2D (Direct2D .NET wrapper from Microsoft). Win2D can be used in an UWP app via a nuget package. Very good stuff. I managed to save ink strokes to image (jpeg, png, and other formats) with this. – mudbox Aug 24 '15 at 19:32
  • @mudbox, I suggest you to write what you have found into an answer so it could help others. – Justin XL Sep 11 '15 at 09:28

2 Answers2

17

Here is how I solved this issue with Win2D. First of all, add Win2D.uwp nuget package to your project. Then use this code:

CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight, 96);

using (var ds = renderTarget.CreateDrawingSession())
{
    ds.Clear(Colors.White);
    ds.DrawInk(inkCanvas.InkPresenter.StrokeContainer.GetStrokes());
}

using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
    await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Jpeg, 1f);
mudbox
  • 301
  • 2
  • 7
  • can you explain the code plz ? it's not clear. I want to draw on image picked from a file .. – Amine Da. Oct 10 '15 at 02:29
  • 2
    Everything you need to know is here. Please go through the content. http://microsoft.github.io/Win2D/html/Introduction.htm If you want to draw an image: 1. Make sure you added Win2D.uwp nugget package to your project (it only works with UWP as far as I know) 2. You'll need a CanvasControl in XAML `` – mudbox Oct 11 '15 at 11:32
  • 1
    3. Since loading a bitmap is async, you'll need [this trick](http://blogs.msdn.com/b/win2d/archive/2014/12/05/async-resource-loading-in-win2d.aspx) – mudbox Oct 11 '15 at 11:42
  • Thanks ! Just to clarify I meant to draw strokes on an image and save it with the strokes as the same file . – Amine Da. Oct 11 '15 at 21:18
  • 2
    Then you need a control that holds the image in XAML (e.g.: Image, Canvas, etc.). You'll also need an InkCanvas (UWP) control on top of the image control. If you don't need to show the final rendered image in the UI, you can ["offset draw"](http://microsoft.github.io/Win2D/html/Offscreen.htm). You just need to get the image source from the control that you want to draw as a background (I don't know this part, maybe you have to convert to bitmap), then load and call `DrawImage` on the drawing session. In the same session, you draw the ink strokes with `DrawInk`. – mudbox Oct 13 '15 at 06:47
  • To complete @mudbox's answer, you can load a bitmap like this `CanvasBitmap backgroundBitmap = await CanvasBitmap.LoadAsync(device, filePath);` and pass it into ds: `ds.DrawImage(backgroundBitmap);` – crazyphoton Dec 01 '15 at 12:19
1

Please try InkPresenter.StrokeContainer property http://blogs.windows.com/buildingapps/2015/09/08/going-beyond-keyboard-mouse-and-touch-with-natural-input-10-by-10/

  • 1
    Welcome to Stack Overflow! Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – hg8 Sep 11 '15 at 09:04