user9375565
user9375565

Reputation:

Transform a colored image to a grayscale image using XAML?

Using XAML preferably,

I need to dynamically apply a gray-scale filter on a colored image from bottom to top. That's to say, i would like to be able to change the offset value of the gray-scale filter applied to my image pro grammatically.

For example, I would like to programmatically set 50% of the image in color (from the bottom of the image to its middle), and the other 50% of the image in gray-scale (e.g. from the middle of the image to its top).

I have read a lot of different answers, tried a lot of different things, and thought about a lot of different ways to do this.

However, this solution poses an issue that I do not seem to be able to resolve. When changing the height value of the gray-scale image, the image automatically rescale itself due to the 'Stretch' property which is set to Uniform (and that I do not wish to change to None).

XAML:

<Image x:Name="myImage" HorizontalAlignment="Left" VerticalAlignment="Top" Source="C:\Users\Clement\Desktop\test.png" Canvas.Left="159" Canvas.Top="81" Width="500" Height="375" >
            <Image.OpacityMask>
                <LinearGradientBrush EndPoint="0.5,0" MappingMode="RelativeToBoundingBox" StartPoint="0.5,1">
                    <GradientStop x:Name="myImageLinearGradientBrushStop" Color="Black"/>
                    <GradientStop Color="Transparent" Offset="1"/>
                </LinearGradientBrush>
            </Image.OpacityMask>
</Image>

Code-behind (in a timerEventProcessor that repeats itself every 50ms):

myImageLinearGradientBrushStop.Offset = percent * 0.01;

As mentioned previously, I have browsed a lot of different websites, read a lot of similar questions and tried a lot of different answers and still cant satisfactorily solve the problem.

Upvotes: 5

Views: 7988

Answers (2)

user9375565
user9375565

Reputation:

Thanks to Clemens' help, I was able to get a solution to my problem!

This is the final XAML code for those whom might be interested:

<Grid Width="500" Height="375">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Image x:Name="image" Grid.RowSpan="2" Source="C:\Users\Clement\Desktop\test_image.png" />

            <Grid Margin="0,0,0,166" Grid.RowSpan="2">
                <Image Width="{Binding ActualWidth, ElementName=image}"
           Height="{Binding ActualHeight, ElementName=image}"
           HorizontalAlignment="Center" VerticalAlignment="Top">
                    <Image.Source>
                        <FormatConvertedBitmap Source="{Binding Source, ElementName=image}"
                                   DestinationFormat="Gray8"/>
                    </Image.Source>
                    <Image.OpacityMask>
                        <ImageBrush ImageSource="C:\Users\Clement\Desktop\test_image.png"/>
                    </Image.OpacityMask>
                </Image>
            </Grid>
        </Grid>

Here I simply added the OpacityMask to the Gray8 image to bring back its transparency.

Happy coding!

Upvotes: 2

Clemens
Clemens

Reputation: 128157

The XAML below uses a Grid with two rows to display two Images on top of each other. The Width and Heigh of the top Image are bound to the size of the bottom Image, which spans both Grid rows. An inner Grid is used to clip the top Image.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Image x:Name="image" Grid.RowSpan="2" Source="..."/>

    <Grid>
        <Image Width="{Binding ActualWidth, ElementName=image}"
               Height="{Binding ActualHeight, ElementName=image}"
               HorizontalAlignment="Center" VerticalAlignment="Top">
            <Image.Source>
                <FormatConvertedBitmap Source="{Binding Source, ElementName=image}"
                                       DestinationFormat="Gray8"/>
            </Image.Source>
        </Image>
    </Grid>
</Grid>

Upvotes: 5

Related Questions