1
votes

Does anybody know of any ways to use an image as a mask for another image in UWP, the only masking function I can see is CompositionMaskBrush which I don't believe can achieve what I want. An example of what I'm looking to achieve is the following. I have a solid black PNG in the shape of a mobile phone case, the user adds their own image which is then clipped and masked to the dimensions of the solid black PNG - Resulting in the image below.

Any help whatsoever would be greatly appreciated. I've spent quite a while browsing for a solution.

Example Image Here

1
Have you check this case?CoCaIceDew
Yes. From what i can see, that requires opening a capture device such as the camera etc which I have no need for. The images are already loaded in the the app by the user.Adam McMahon
I mean you could also create transparent phone pic as mask and covered on background image. Then use RenderTargetBitmap to capture it.CoCaIceDew
That's kind of my question, how to use the transparent image as a mask... From what I can see, there is no real way, or at east there is no documentation on it. The closest thing I can find is this -github.com/ratishphilip/CompositionProToolkitAdam McMahon
I think I now understand what you mean... My problem is, my mask file is a transparent .png with a black shape of a mobile phone. I need the users image to only appear over the black pixels. Essentially masking the image. Now, I can do this with geometry shapes in XAML BUT I can't find anything that will allow me to paint over black pixels only in C# UWP.Adam McMahon

1 Answers

1
votes

Just posting for anybody else who needs and answer to this, but I finally managed to find a solution using Win2D and an Imageloader.

Here is a link to the ImageLoader. Note that I had to roll back a few versions in order make it work how the documentation states. The link below is to the version that I'm using. Anything later than this version will not work with the sample code I'm going to post. https://www.nuget.org/packages/Robmikh.Util.CompositionImageLoader/0.4.0-alpha

    private Compositor _compositor;
    private IImageLoader _imageLoader;
    private CompositionEffectFactory _effectFactory;

    private async void InitMask()
    {


        // Store our Compositor and create our ImageLoader.
        _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        _imageLoader = ImageLoaderFactory.CreateImageLoader(_compositor);

        // Setup our effect definition. First is the CompositeEffect that will take
        // our sources and produce the intersection of the images (because we selected
        // the DestinationIn mode for the effect). Next we take our CompositeEffect 
        // and make it the source of our next effect, the InvertEffect. This will take 
        // the intersection image and invert the colors. Finally we take that combined 
        // effect and put it through a HueRotationEffect, were we can adjust the colors
        // using the Angle property (which we will animate below). 
        IGraphicsEffect graphicsEffect = new HueRotationEffect
        {
            Name = "hueEffect",
            Angle = 0.0f,
            Source = new InvertEffect
            {
                Source = new CompositeEffect
                {
                    Mode = CanvasComposite.DestinationIn,
                    Sources =
                    {
                        new CompositionEffectSourceParameter("image"),
                        new CompositionEffectSourceParameter("mask")
                    }
                }
            }
        };
        // Create our effect factory using the effect definition and mark the Angle
        // property as adjustable/animatable.
        _effectFactory = _compositor.CreateEffectFactory(graphicsEffect, new string[] { "hueEffect.Angle" });

        // Create MangedSurfaces for both our base image and the mask we'll be using. 
        // The mask is a transparent image with a white circle in the middle. This is 
        // important since the CompositeEffect will use just the circle for the 
        // intersectionsince the rest is transparent.

        var managedImageSurface = await _imageLoader.CreateManagedSurfaceFromUriAsync(new Uri("http://sendus.pics/uploads/" + ImagePass + "/0.png", UriKind.Absolute));
        //var managedImageSurface = await _imageLoader.CreateManagedSurfaceFromUriAsync(new Uri("ms-appx:///Assets/colour.jpg", UriKind.Absolute));
        var managedMaskSurface = await _imageLoader.CreateManagedSurfaceFromUriAsync(new Uri("ms-appx:///" + MaskImage, UriKind.Absolute));

        // Create brushes from our surfaces.
        var imageBrush = _compositor.CreateSurfaceBrush(managedImageSurface.Surface);
        var maskBrush = _compositor.CreateSurfaceBrush(managedMaskSurface.Surface);

        // Create an setup our effect brush.Assign both the base image and mask image
        // brushes as source parameters in the effect (with the same names we used in
        // the effect definition). If we wanted, we could create many effect brushes
        // and use different images in all of them.
        var effectBrush = _effectFactory.CreateBrush();
        effectBrush.SetSourceParameter("image", imageBrush);
        effectBrush.SetSourceParameter("mask", maskBrush);

        // All that's left is to create a visual, assign the effect brush to the Brush
        // property, and attach it into the tree...
        var visual = _compositor.CreateSpriteVisual();

        visual.Size = new Vector2(MaskH, MaskW);
        visual.Offset = new Vector3(0, 300, 0);

        visual.Brush = effectBrush;

        ElementCompositionPreview.SetElementChildVisual(this, visual);
    }