Images in Composition

I am developing my apps with more visual transitions, animations, etc. all managed in the Visual Layer, is really smoother than using XAML animations, there are no dependency properties and might be, you remember that animating some properties were not optimized.

To clarify adding images in Composition let’s explain the example I am achieving.

In my case I want to fade from Image to another Image, when I began to do this I uses the ArithmeticCompositeEffect with the following definition:

var effectDef = new ArithmeticCompositeEffect
            {
                Name = "effect",
                ClampOutput = false,
                MultiplyAmount = 0,
                Source1Amount = 1,
                Source2Amount = 0,
                Source1 = new CompositionEffectSourceParameter("ImageSource"),
                Source2 = new CompositionEffectSourceParameter("Source2")
            };

And it works really well like in the ‘Finding Dory’ tweets I did. So I decided to follow that way, when is showing one of the Images I could update the other one with other Uri/File source and animate again. But it makes a disgusting flickering I think you cannot avoid.

The only way to do this is extracting the base of the CompositionImage class from the SamplesCommon project and set two SpriteVisuals in a ContainerVisual and animate the Opacity of each.

So I decided to make a diagram of all the flow in there, to understand what is happening, because meanwhile the Composition API is final, it has been changing the way of the Images and other sources are obtained.

In this case I want to set an Image in the Visual of a custom class that inherits from control:

composition

The steps to set a Visual in the Element are the following were you will need the SamplesCommon source project reference:

  1. Gain access to the Visual Layer (Composition) by calling the GetElementVisual of static ElementCompositionPreview.
  2. From the compositor of the Visual create an SpriteVisual and a SurfaceBrush.
    1. The SpriteVisual will be the Child of the Control Visual.
    2. The SurfaceBrush will be brush that fills the SpriteVisual (like ImageBrush in the Background of a Grid in XAML)
  3. Create a CompositionDrawingSurface using SurfaceLoader Helper
  4. Set that surface to the SurfaceBrush previously created.
  5. Set the SurfaceBrush as Brush of the SpriteVisual.
  6. Set the Child Visual of the Visual by calling SetChildElementVisual of the static ElementCompositionPreview.

It might appear a bit complex, but what it really means is you have a lot of control of what to do. For instance (I have not tried it yet) you have access to a DrawingSession that means you can make a lot of geometric and drawing operations in that step, might be even use Win2D effects (I have to check that and also if is a transparent session)

This Surface ‘Image’ brush of the SpriteVisual is one of you can set, you can take a look more options in here: https://msdn.microsoft.com/en-us/windows/uwp/graphics/composition-brushes.

Also you have now the composition properties of the Visual and the ‘Child’ SpriteVisual and you can animate all of them smooth, which is really important.

And the SurfaceBrush has properties like the XAML ImageBrush like alignments, stretch, etc. which make the things easier to work with.

Hope this makes easier to understand the flow of the Visual Layer and how interoperates with Win2D objects. As always @juanpaexpedite

 

 

 

 

Bonobo Git Server and Visual Studio 2015

bonobo

EN: I always wanted to create a private Git repository and after test my first commit from Visual Studio here I attach a guide I hope make it an easy walkthrough to configure it: gitlocal_en

ES: Siempre he querido crear un repositorio privado de Git y después de mi primer commit con el desde Visual Studio adjunto aquí una guía que espero que te haga el camino más fácil para configurarlo.gitlocal_sp

Win2D Particles

One of the apps I am preparing has a particles adornment, I made the first version ‘solve version’ and now I have implemented the ‘code version’.

deer

The CanvasAnimatedControl

This Win2D Control is like having XNA in UWP apps, you can subscribe the following events:

private void Initialize()
{
    MainCanvas.CreateResources += MainCanvas_CreateResources;
    MainCanvas.SizeChanged += MainCanvas_SizeChanged;
    MainCanvas.Update += MainCanvas_Update;
    MainCanvas.Draw += MainCanvas_Draw;
}

Where CreateResources is where you generate and download all the source images you will need in the other events. SizeChanged is just the base event to keep the bounds, Update is when you modify the position and effect of the particles, and finally the Draw event when you paint each particle in the control.

Particles Generator

Basically it has the following structure:

  1. Create the textures (small circles with blur)
  2. Create a List of particles at different positions.
  3. Add displacement with turbulente effect per particle. (turbulence gives more natural effect)
  4. Update Turbulence

And then draw the result each time.

Creating the Textures

In order to use only Win2D, I created 4 bitmaps (CanvasRenderTarget) of different sizes with a chained painting session where:

  1. Paint two circles in a canvas
  2. Apply blur effect to the previous canvas.
using (CanvasDrawingSession targetSession = canvas.CreateDrawingSession())
{
    targetSession.Clear(transparent);
    targetSession.FillCircle(center, nextRadius, outerColor);
    targetSession.FillCircle(center, nextRadius - 6, innerColor);
}
var blurEffect = new GaussianBlurEffect() { BlurAmount = 2f };
CanvasRenderTarget blurredcanvas = new CanvasRenderTarget(device, viewportsize, viewportsize, parent.Dpi);
blurEffect.Source = canvas;
using (CanvasDrawingSession targetSession = blurredcanvas.CreateDrawingSession())
{
    targetSession.Clear(transparent);
    targetSession.DrawImage(blurEffect);
}

Each of these bitmaps will be used as sources of every particle drawing, which has a displacement with turbulence effect, when you apply this effect you must create a big viewport, 100 px in this case, because is drawn the original image and the displacement image, so to avoid this just create this safety viewport.

Decrease ‘float viewportsize = 100;’ if you want to watch the weird result.

Creating the Particles

Now we have the images let’s create the particles, you have to consider the window bounds and the size changes. I added a random orientation for each particle and if you want only falling particles:

public void CreateParticles(bool fall)
{
    particles = new List<Particle>();

    int i = -1;
    int minpos = minRadius * sizes * 2;
    while (++i < amountparticles)
    {
        var x = generator.Next(minpos, (int)bounds.Width);
        var y = generator.Next(minpos, (int)bounds.Height);
        var s = generator.Next(0, sizes);
        var ox = generator.NextDouble() > 0.5 ? 1 : -1;
        var oy = fall ? 1 : generator.NextDouble() > 0.5 ? 1 : -1;

        var particle = new Particle(x, y,s,ox,oy, particleBitmaps[s], particlefall:fall);
        particles.Add(particle);
    }
}

As you see is just creating a list with random values for each property. In the constructor of each particle I add the effects.

Displacement with turbulence

random = generator.Next(2, 50);
factor = 0.7f * random / 10.0f;
var octaves = generator.Next(1, 5);
turbulence = new Transform2DEffect() { Source = new TurbulenceEffect() { Octaves = octaves } };
displacement = new DisplacementMapEffect() { Source = source, Displacement = turbulence };

The idea of the displacement is to displace and deform the particle according to the turbulence effect. If you want to see what is the turbulence, in the drawing session, draw the turbulence effect instead the displacement.

Update the turbulence

Now we have the turbulence created we have to move the particle around it is position using the following turbulence which also deforms the particle:

private void UpdateTurbulence(float elapsedTime)
{
    TurbulenceMatrix = Matrix3x2.CreateTranslation((float)Math.Cos(elapsedTime + random) * 2 - 2, (float)Math.Sin(elapsedTime) * 2 - 2);
    turbulence.TransformMatrix = TurbulenceMatrix;
    displacement.Amount = (float)Math.Sin(elapsedTime * factor) * random;
}

It is relative simple to create this environment, I have to recognize that in my 1320 goes slow, but in desktop works really well, I cannot assure is because the displacement effect, might be reducing the update times could be great so I let you go and test it.

I hope you enjoy the article and take the idea about how to create images/textures in Win2D and then apply to a CanvasAnimatedControl like in the XNA old ages so simplifies the code a lot.

And as always you have the code in the Particles2D project of my repo : Github

Follow me to know the latest code about Windows10 @juanpaexpedite

‘Remember Build 2015’ Composition Example

I decided before continuing with my apps to dig more into Composition and make some kind of clean layout to make some experiments with Composition API.

Sooner than later will be the next Build and I usually rewatch cool videos from it so I decided to make this example around the 2015 edition.

build2015

gallery

sessions

In this case I set the Composition animations in another library to begin having it ready for an app. The animations that are called to my previous demo (id software demo) are NOT equals so please be careful about this.

One important thing I wanted in an app is the idea to change the focus visually so I make the things appear at different times and I consider that the implementation looks great!

NOTE1: I have added waits in some of the attached properties, might be more solid code if the logic is in the loaded event, in order to have all the attached properties on time including the binding, because in this example I had to set in order from left to right the attached properties to had them when is needed!

NOTE2: I use attached properties because are inline and visually more clean, that makes if you need to read more properties before act a bit more complex so if you consider you can use behaviors too.

It is recommended to run the app without debugging to watch all times right!!

Properties

In this example we have the following Attached Properties:

DoubleEffectParameter, BoolEffectParameter

These are generic attached properties to use joined with other attached properties to adjust the values of the other properties.

Delay

Use it in conjunction with an Effect Property to make transitions one before another is in seconds of double.

FadeOut

Allows a control go from Composition Opacity 0 to one using the previous parameters, as example:

<Grid Background="{StaticResource GradientSky}" a:Effects.DoubleEffectParameter="10"  a:Effects.FadeOut="True" />

Appear

It makes an offset and opacity appearing effect animation at the same time.

<Grid Width="1600" a:Effects.Delay="3.5" a:Effects.DoubleEffectParameter="2" a:Effects.Appear="True" HorizontalAlignment="Left" IsHitTestVisible="False"/>

Disappear

It takes the height of an element and animates it until disappears to the top.

<StackPanel  a:Effects.Delay="1" a:Effects.BoolEffectParameter="False" a:Effects.Disappear="True"/>

Blend

It is a cool one that makes a transition among images, I use it in the example for the gallery, move the mouse around images and it will make a transition. Being GalleryImage a Grid:

GalleryImage.SetValue(Effects.BlendForegroundProperty, newuri);

I have not tested by using binding to a property, theorically should work.

Column

columns

In this case the Column Attached Property makes the appear effect begin when the scrollviewer arrives to the column value position.

Parallax

You need to specify which is one the scroller to get its Composition Layer and then the factor of parallax you want to apply. The effect is interesting because shows that you are scrolling even when the main content has not appear (eg. column 1 appearing).

Easy to use as the following example:

<Image x:Name="Background0"  a:Effects.ElementParameter="{Binding ElementName=Scroller}" a:Effects.Parallax="0.2"/ 

NOTE: I wanted to create a color Composition transition from blue to orange, that’s why exists Gradient but at this moment it has to be with Win2D, so to focus in Composition I omitted it.

Animating Scrolling

I did not test this feature until this example and works great, the idea is emulate a Pivot or a Hub Control with just simply a scrollviewer and grids, you can do it by using:

  #region Scroller
        private void Scroll()
        {
            Scroller.ChangeView(screenWidth * currentgrid, null, null);
        }
        #endregion

        #region Button Events
        private void InitializeEvents()
        {
            FirstButton.Tapped += ScrollButton_Tapped;
            SecondButton.Tapped += ScrollButton_Tapped;
            ThirdButton.Tapped += ScrollButton_Tapped;
        }

        int currentgrid = 0;
        private void ScrollButton_Tapped(object sender, TappedRoutedEventArgs e)
        {
            if (sender.Equals(FirstButton))
                currentgrid = 1;
            else if (sender.Equals(SecondButton))
                currentgrid = 2;
            else if (sender.Equals(ThirdButton))
                currentgrid = 3;
            Scroll();
        }

NOTE: If you can you can hide the bar and lock the scroll, it makes the scroll method still working so it is a really interesting option!

Behaviors

I tested the tilt effect behavior from r2d2rigo and works cool! so I decided to use it in the example for the list.

Html Processing

If you never have processed html using htmlagilitypack, this is a good example, might be there is a better thing to extract values from attributes, if you know it, would you give me a clue?

Issues

I have some odd behaviors that I want to comment

  • I had to force a height in the ItemsControl of the sessions because the margin was impossible to force to make it a relative height.
  • Because something odd between Github and Nuget the code I had to use of HtmlAgilityPack is not perfect, there are methods that do not appear to me.
  • The Scroll method works pretty well except sometimes when go again to HorizontalOffset Zero, but I understand might be a bug.

And finally the source code:
Composition Examples inside the Parallax Project Folder

Hope enjoy @juanpaexpedite

Search Groove in Composition Example

Composition API has really great features and with the new examples is even better.

bowie

If you take a look to the ContinuitySample, you will learn how to get a Visual that will still in screen when the app navigates in a Frame, which was a doubt I had and I was to test in few days, so thank you Composition team to make it quicker than us🙂.

And Parallax Music example has really cool scrollviewer effect which is the one where I want to add some code to find artist IDs.

Of course is not the main purpose of the Composition example but cause they give us the chance to play with Groove let’s add the search option.

After you tested the that example with your id add the following:

IDatasource.cs

//At the end of the interface add this method declaration
    Task SearchArtistId(string name);

RemoteDataSource.cs

//At the end of the class
#region Search
private static readonly string SEARCH = "music/search?q=";

private async Task Search(string query)
{
    var service = SERVICE + "/" + SEARCH + query + "&accessToken=Bearer+" + WebUtility.UrlEncode(Token);
    var response = await _client.GetAsync(new Uri(service));
    var content = await response.Content.ReadAsStringAsync();
    return content;
}

public async Task SearchArtistId(string name)
{
    var content = await Search(name);
    if (content != null)
    {
        JsonObject jsonObject = JsonObject.Parse(content);
        var _artist = jsonObject["Artists"].GetObject()["Items"].GetArray()[0].GetObject();
        return _artist["Id"].GetString();
    }
    return null;
}
#endregion

Now we have the implementation, let’s add the XAML and events.

MainPage.xaml

Before the ProgressRing add:

<!--#region Added for look up-->
<StackPanel Orientation="Horizontal" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignTopWithPanel="True">
    <TextBox x:Name="SearchBox" Width="320"/>
    <Button x:Name="SearchButton" >
        <SymbolIcon Symbol="Find" />
    </Button>
</StackPanel>
<!--#endregion-->

MainPage.xaml.cs

Remove readonly for DEFAULT_ARTIST_ID and now add the following:

public MainPage()
{
    this.InitializeComponent();

    this.InitializeSearch();
    ...
}

#region Search
private void InitializeSearch()
{
    SearchButton.Tapped += async (s, e) =>
    {
        var text = SearchBox.Text;
        if (!String.IsNullOrEmpty(text) && text.Length > 2)
        {
            var result = await _dataSource.SearchArtistId(text);
            DEFAULT_ARTIST_ID = result;
            InitializeData();
        }
    };
}
#endregion

Piece of cake, isn’t it?. I’ve never used Groove and works really efficient. The following I post will be some examples of Composition that I want to make for some of my controls.

Regards @juanpaexpedite

XAML Attached Properties Composition Effects

Hello, today I made my first XAML step with Composition. This is the XAML result after making alchemy with XAML, Composition and the Win2D effects.

saturation1

The idea is to create Effect attachable properties to add for instance a saturated background that can even follow binding saturation changes and size changes.

beach

Prerequisites

– I did not find any NuGet of the Microsoft.UI.Composition.Toolkit, so I copy it from the composition-master from the Microsoft Windows Composition repository, you should download it and reference for the project.
– Learn a bit about Effects, just their properties and what they do, you can take a look to the official documentation and in my ‘old’ Win2D posts:
Win2d Posts
– Know what are attached properties and how to implement that in XAML.
– Know what are dependency properties and how to add to a dependency object and user them in XAML.

Common code for composition

If you know a bit of the prerequisites, now you need how to get the visual layer from a UIElement, the compositior and how to create the CompositionImageFactory. All of these are required to manipulate the visual layer:

public class CompositionManager
{
    public static ContainerVisual GetVisual(UIElement element)
    {
        var hostVisual = ElementCompositionPreview.GetElementVisual(element);
        ContainerVisual root = hostVisual.Compositor.CreateContainerVisual();
        ElementCompositionPreview.SetElementChildVisual(element, root);
        return root;
    }

    public static Compositor GetCompositor(Visual visual)
    {
        return visual.Compositor;
    }

    public static CompositionImageFactory CreateCompositionImageFactory(Compositor compositor)
    {
        return CompositionImageFactory.CreateCompositionImageFactory(compositor);
    }
}

Saturation class

Now we know how to gain access to the visual layer, let’s create a Dependency object class called Saturation that will have the following fields and properties:

Element

Is the attached element for the Saturation class

#region Element
private UIElement element;
private FrameworkElement frameworkElement;
#endregion

Source

Is the dependency property that will take as Image Source for our Saturation Effect

#region Source
public string Source
{
    get { return (string)GetValue(SourceProperty); }
    set { SetValue(SourceProperty, value); }
}
public static readonly DependencyProperty SourceProperty =
    DependencyProperty.Register(nameof(Source), typeof(string), typeof(Saturation), 
		new PropertyMetadata(null));
#endregion

Composition

We need to get the Visual Composition layer of the Element:

Image from blog.windows.com

#region Composition
private ContainerVisual visual;
private Compositor compositor;
private CompositionImageFactory imageFactory;
#endregion

Variable Effect

We want to change the value of the Saturation in the Saturation Effect, to make that, we need to set the Saturation as ‘animatable’. We have to set a name for the SaturationEffect and know the path of the Saturation (like when we use Storyboards).

#region Effect
private string EffectSource = "EffectSource";
private string SaturationEffect = "SaturationEffect";
private string SaturationEffectPath = "SaturationEffect.Saturation";
private SaturationEffect effect;
private CompositionEffectFactory effectFactory;
#endregion

Composition Brush and Image

This is the image we will create

#region CompositionImage
private CompositionSurfaceBrush surfaceBrush;
private CompositionImage imageSource;
#endregion

What we paint on the composition image

We have to create the image with the effect using the following:

#region Brush & Sprite
private CompositionEffectBrush effectBrush;
private SpriteVisual spriteVisual;
#endregion

Some of these fields might sound a bit confusing, but I made the methods simple and step by step to make things clear.

Initialization

When the attached property sets (I will explain later) we will call to this method.

public void Initialize(UIElement attachedelement)
{
    element = attachedelement;
    frameworkElement = element as FrameworkElement;
    CreateImageFactory(element);
    CreateEffect();
    CreateSurface();
    CreateBrush();
    CreateSpriteVisual();
    Insert();
    DetectElementChange();
}

Where CreateImageFactory is an standard method to get the visual, compositor and create an imageFactory to work:

using static Universal.Managers.CompositionManager;

private void CreateImageFactory(UIElement element)
{
    visual = GetVisual(element);
    compositor = GetCompositor(visual);
    imageFactory = CreateCompositionImageFactory(compositor);
}

To make code more readable the CompositionManager class that is common to for any effect you need I added as static.

Creating the Effect

This step is important to understand:

  • To create an effect that can change a property during the runtime, we need to assign to the Effect a name.
  • To add a source to the effect that comes from composition instead from Win2D we assign a CompositionEffectSourceParameter
  • Update Level is the value that converts percentage to 0.0 to 1.0f values and sets to the animatable property.
  • Effect Factory creates the effect with the path defined before to allow us to change the saturation level.
private void CreateEffect()
{
    effect = new SaturationEffect()
    {
        Name = SaturationEffect,
        Saturation = 0.0f,
        Source = new CompositionEffectSourceParameter(EffectSource)
    };

    UpdateLevel();
    effectFactory = compositor.CreateEffectFactory(effect, new[] { SaturationEffectPath });
}

(UpdateLevel method is explained later).

Surface, Brush and SpriteVisual

private void CreateSurface()
{
    surfaceBrush = compositor.CreateSurfaceBrush();
    var uriSource = UriManager.GetFilUriFromString(Source);
    imageSource = imageFactory.CreateImageFromUri(uriSource);
    surfaceBrush.Surface = imageSource.Surface;
}

private void CreateBrush()
{
    effectBrush = effectFactory.CreateBrush();
    effectBrush.SetSourceParameter(EffectSource, surfaceBrush);
    effectBrush.Properties.InsertScalar(SaturationEffectPath, 0f);
}

private void CreateSpriteVisual()
{
    spriteVisual = compositor.CreateSpriteVisual();
    spriteVisual.Brush = effectBrush;
    spriteVisual.Size = new Vector2(GetElementWidth(), GetElementHeight());
}

Where GetElementWidth and GetElementHeight are safe methods to avoid NaN from the Element values.

Level of Saturation

The Level dependency property:

#region Level
public double Level
{
    get { return (double)GetValue(LevelProperty); }
    set { SetValue(LevelProperty, value); }
}

public static readonly DependencyProperty LevelProperty =
    DependencyProperty.Register(nameof(Level), typeof(double), typeof(Saturation), new PropertyMetadata(0.0, LevelChanged));

private static void LevelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as Saturation).UpdateLevel();
}

private void UpdateLevel()
{
    if (effectBrush != null)
    {
        var newvalue = (float)(Level / 100.0);
        effectBrush.Properties.InsertScalar(SaturationEffectPath, newvalue);
    }
}
#endregion

Insert the composition created and detect size changes

Finally let’s add the composition to the Element in its visual layer and detect its size changes:

private void Insert()
{
    visual.Children.InsertAtBottom(spriteVisual);
}

private void DetectElementChange()
{
    frameworkElement.SizeChanged += (s, e) =>
    {
        UpdateSpriteVisual();
    };
}

Conclusions

Composition allows to change parameters and follow size changes without recreating all the image, effect, etc. which makes the interface more responsive and efficient.
It is similar to animate/change an effect value as it is were a Storyboard.
The image source of an effect is using CompositionEffectSourceParameter.
You have to get the visual layer from an UIElement using the methods in the CompositionManager.

Source code

The source code is available on GitHub in the UniversalExamples-SaturationEffectPage

It is my first step in Composition, in following articles I will take a look how to add more effects, animate plenty of equal instances and many more.

To be up to date @juanpaexpedite and happy coding.

IoT Vector pack

IoTVectorpack_post

I decided to gift my IoT vector pack to be used in any IoT app, I made with the great Inkscape, rename from .doc to .svg  IoTVectorpack .

If you want to learn how to use to clip a control all the information here:

Sensing world with Windows 10 IoT screenshot.jpg

In the link I created a document that explains in details all the steps even how to make the clipping to show the level of a sensor in a range.

Let’s improve the IoT designs🙂.

As always get all my latest at