📜 ⬆️ ⬇️

Using graphic effects in UWP applications using Win2D


Meet: Win2D is an easy-to-use Windows Runtime API for more convenient use of DirectX features. Drawing graphics is done with GPU acceleration. Win2D is available for C #, C ++ and VB developers in both Windows 8.1 and Windows 10.

With Win2D you can draw shapes, lines, text and images, as well as add to all this various effects. In addition, you can add some effects to the video image.

I propose to consider the examples of the main library functionality.

You can install Win2D.uwp from Visual Studio using NuGet Package Manager. The github page of this open-source project is here . English documentation here: Win2D documentation
')
After installing the XAML page header, you can add:

xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml" 

And in the page markup, the CanvasControl control:

 <canvas:CanvasControl Width="500" Height="300" x:Name="canv" Draw="CanvasControl_Draw" ClearColor="LightGray"/> 

This is not the same Canvas element, which is a page layout element and may contain other elements as a host. There is some similarity between Canvas and CanvasControl, but the performance is completely different.

When the CanvasControl element is drawn, the Draw event occurs, which in the example is assigned the CanvasControl_Draw event handler. The official example suggests to draw a figure (ellipse) and a text for the beginning:

 void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args) { args.DrawingSession.DrawEllipse(155, 115, 80, 30, Colors.Black, 3); args.DrawingSession.DrawText("Hello, world!", 100, 100, Colors.Yellow); } 

Here's what happens:



In order to avoid memory leaks, you must always correctly destroy resources. This is done, as a rule, when the page is unloaded:

 void Page_Unloaded(object sender, RoutedEventArgs e) { this.canv.RemoveFromVisualTree(); this.canv = null; } 

So far, nothing unusual. You can draw the same thing using XAML shapes. By the way, examples of drawing in the usual XAML you can find here: Draw shapes

Work with images. It is much more interesting. I added the file mydog.jpg to the project and selected the action in the properties for the assembly “Contents” (to be exact, I didn’t even choose, it was chosen by default).

For images in Win2D, the CanvasBitmap class from the Microsoft.Graphics.Canvas namespace is responsible. Add a variable to our application named cbi:

 CanvasBitmap cbi; 

The image is loaded during the Canvas element event with the name CreateResources, therefore we will add this event to our XAML code:

 <canvas:CanvasControl Width="500" Height="300" x:Name="canv" Draw="CanvasControl_Draw" CreateResources="CanvasControl_CreateResources" ClearColor="LightGray"/> 

The download itself is done using the following code:

 cbi = await CanvasBitmap.LoadAsync(sender, "mydog.jpg"); 

Since it occurs asynchronously, we are invited to bring it into a separate task:

 private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction()); } async Task CreateResourcesAsync(CanvasControl sender) { cbi = await CanvasBitmap.LoadAsync(sender, "mydog.jpg"); } 

TrackAsyncAction in this case requires the CreateResourcesAsync task to finish before the CreateResources is completed. It remains to load in Canvas:

 private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(cbi); } 



It was loaded, but not really interesting yet just to display a picture. Add just a couple of lines of code and get a Gaussian blur effect.

 var blur = new GaussianBlurEffect(); blur.BlurAmount = 1.7f; blur.Source = cbi; args.DrawingSession.DrawImage(blur); 



A full list of effects is available on the Microsoft.Graphics.Canvas.Effects documentation namespace description page. By the way, effects can also be created using the Lumia Imaging SDK . The source code for Lumia-imaging-sdk can also be found on GitHub . In addition, some effects are available using the Windows.UI.Composition namespace.

Sometimes it is necessary to display the graphics not immediately, but during the execution of the program. Save it to a file, display it or get an array of pixels. This type of work is called Offscreen drawing.

Let's say, here's an example in which the XAML element CanvasControl is not used at all, but the element element is used

 <Image x:Name="img" Width="500" Height="300"></Image> 

You can process the picture and display it by adding a saturation effect, like this:

 CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); using (var ds = offscreen.CreateDrawingSession()) { var satur = new SaturationEffect(); satur.Saturation = 0.2f; satur.Source = cbi; ds.DrawImage(satur); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; } 

I like it even more (although I can’t say anything about performance comparison)



In order to create a small composition and superimpose the text on the picture, we need the namespace:

 using Microsoft.Graphics.Canvas.Text; 

And a similar snippet:

 CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); using (var ds = offscreen.CreateDrawingSession()) { ds.DrawImage(cbi); var format = new CanvasTextFormat() { FontSize = 32, HorizontalAlignment = CanvasHorizontalAlignment.Left, VerticalAlignment = CanvasVerticalAlignment.Top, WordWrapping = CanvasWordWrapping.Wrap, FontFamily = "Decor", }; using (CanvasTextLayout tl = new CanvasTextLayout(ds, "10  2010", format, 250, 50)) //  250   50 { ds.DrawTextLayout(tl, 10, 10, Color.FromArgb(120, 20, 20, 20)); } format.Dispose(); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; } 



Combine 2 images using the blend effect:

 CanvasBitmap cbi; CanvasBitmap cbi2; CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); cbi2 = await CanvasBitmap.LoadAsync(device, "present.png"); using (var ds = offscreen.CreateDrawingSession()) { BlendEffect blendEffect = new BlendEffect() { Background = cbi, Foreground = cbi2, Mode = BlendEffectMode.SoftLight }; ds.DrawImage(blendEffect); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; } 



Some effects can be combined. With the following snippet, combining a variety of effects, you can get a text glow effect.

 var myTextBitmap = new CanvasRenderTarget(sender, 300, 100); using (var ds = myTextBitmap.CreateDrawingSession()) { ds.Clear(Color.FromArgb(0, 0, 0, 0)); ds.DrawText(" !", 0, 0, Colors.White, new CanvasTextFormat { FontSize = 24, FontWeight = Windows.UI.Text.FontWeights.Bold }); } var effectGraph = new CompositeEffect(); effectGraph.Mode = CanvasComposite.Add; effectGraph.Sources.Add(new ColorMatrixEffect { Source = new GaussianBlurEffect { Source = new MorphologyEffect { Source = myTextBitmap, Mode = MorphologyEffectMode.Dilate, Width = 7, Height = 4 }, BlurAmount = 3f }, ColorMatrix = new Matrix5x4 { M11 = 0f, M12 = 0f, M13 = 0f, M14 = 0f, M21 = 0f, M22 = 0f, M23 = 0f, M24 = 0f, M31 = 0f, M32 = 0f, M33 = 0f, M34 = 0f, M41 = 0f, M42 = 1f, M43 = 0f, M44 = 1f, M51 = 1f, M52 = -0.5f, M53 = 0f, M54 = 0f } }); effectGraph.Sources.Add(myTextBitmap); args.DrawingSession.DrawImage(effectGraph,100,100); 



An interesting text effect that is often associated with Win2D is the animated effect of burning text.



Direct links to the BurningTextExample.xaml and BurningTextExample.xaml.cs example, I, perhaps, even leave here: BurningTextExample.xaml / BurningTextExample.xaml.cs .

Just as in the case of the UWP Community Toolkit, it is possible to download the application with usage examples for Win2D. The application is called Win2D Example Gallery . The source code of the application is on github .

Personally, I liked the following picture the most:



As it turned out, it is completely drawn using DrawLine, DrawEllipse, DrawCircle, etc.

The library is updated regularly and therefore you can expect new beautiful effects.

Source: https://habr.com/ru/post/308310/


All Articles