Search code examples
c#wpftransparencyoutline

Render only the outline of an arbitrarily shaped object


I'm working with WPF and C# and I'm cutting out a person out of an image by using an opacity mask. I now need to get only the outline of this person and remove the actual image of that person so that only the outline remains.

I figured out that I could use a dropshadow-effect to get something like an outline of the person (this suffices my purpose but feel free to suggest a better approach). However, I don't know how I can remove the rest of the person so that only the outline/dropshadow remains?


Solution

  • It's a few months too late, but maybe this will help you or someone else. I came here looking for help on nearly the same topic but there is one difference: I have already found an answer. It's simple but too slow for my purposes with larger images (>800*600), so I'm looking for something more efficient -- not much chance of that, it seems.

    First, use CopyPixels to get a byte array of the Image (or the opacity mask). Define a PathGeometry. Then for each pixel which passes the test (in my case, alpha > 0), add a 1*1 pixel RectangleGeometry to the PathGeometry. Then use PathGeometry.GetOutlinedPathGeometry to get the outline of the shape as a Geometry.

    Here's a function I wrote in VB.Net which may help you by way of illustration.

        Public Function GetImageOutline(bi As BitmapImage) As Geometry
        Dim stride As Integer = bi.PixelWidth * 4
        Dim height As Integer = bi.PixelHeight
        Dim pg As New PathGeometry With {.FillRule = FillRule.Nonzero}
        Dim pixels(height * stride - 1) As Byte
        bi.CopyPixels(pixels, stride, 0)
        For i As Integer = 0 To pixels.Count - 1 Step 4
            '\\\Find non-transparent pixels (Alpha > 0):
            If pixels(i + 3) > 0 Then
                Dim x As Double = (i Mod stride) \ 4
                Dim y As Double = Math.Floor(i / stride)
                Dim pixG As New RectangleGeometry(New Rect(x, y, 1, 1))
                pg.AddGeometry(pixG)
            End If
        Next
        Return pg.GetOutlinedPathGeometry()
    End Function