Press "Enter" to skip to content

Applying filters to image in Xamarin Forms

When working in applications that involve image sharing you might need to provide some functionality related to image manipulation like applying filters. But there’s not a built-in way to do this using Xamarin Forms, so that’s when custom renderers come to the rescue. In this post, I will guide you to an implementation to achieve this on iOS and Android.

PCL Implementation:

First, we define an enum with the filters we support. In the case of this sample we support 5 filters: No Filter, Black and white, Saturated, Hifi, Vintage. So our enum looks like this:

public enum FilterType
{
    NoFilter,
    BlackAndWhite,
    Saturated,
    Hifi,
    Vintage
}

Then we define the model with the information the ui will need to render properly and keep the state for each filter.

Now we will extend the Image Xamarin Forms control to provide the additional properties to be able to apply filters to our image.

Basically, we add a bindable property to set our OriginalSource, to keep the reference of the original image so that we can restore it when another filter was already applied. Also, we need to add a few commands to provide feedback to the renderer when the filter is selected and when filtered image needs to be saved:

  • SelectFilterCommand - Provides feedback to the renderer that a filter was selected. Command code is implemented on the renderer and the command is executed from the ViewModel once a filter is selected.
  • ApplyFilterCommand - Request the renderer to save the image with the filter applied. Command code is implemented on the renderer and the command is executed from the ViewModel once we want to save the filter that is applied.
  • FilterAppliedCommand - Provides feedback to the ViewModel that the filter was a saved. Command code is implemented on the ViewModel and is executed from the render once the filtered image is saved. Gets the path and bytes of the saved image with the applied filter.

ViewModel:

XAML:

iOS:

On the renderer OnElementChanged we implement the code for the command execution of SelectFilterCommand(when filter is selected), ApplyFilterCommand(to save an applied filter).

On iOS we used CoreImage and also the GPU Image Component that allows you filters and other effects to images and videos. We have a method ApplyEffect that receives a CIFilter and UIImage that the filter will be applied on.

The main method we use for applying the filter is the following:

Renderer's main method is ApplyFilter, which takes care of applying the filter to the original image and update the currently shown image. In this method we first restore the original image from our OriginalSource property on the FilterImage control then we call the right filter method based on the FilterType selected to apply the correct filter to the image and update our native control with Control.Image = filteredImage.

Here is the full renderer implementation:

Android:

On the renderer OnElementChanged we implement the code for the command execution of SelectFilterCommand(when the filter is selected), ApplyFilterCommand(to save an applied filter).

We use Android.Graphics to manipulate the image. There is a method per filter with the specifics to apply each filter:

  • ApplyHifi
  • ApplyBlackAndWhite
  • ApplySaturation
  • ApplyVignette

Renderer's main method is ApplyFilter, which takes care of applying the filter to the original image and update the currently shown image. In this method we first restore the original image from our OriginalSource property on the FilterImage control then we call the right filter method based on the FilterType selected to apply the correct filter to the image and update our native control with Control.SetImageBitmap(resizedBitmap).

Here is the full renderer implementation:

Used:

GPUImage
PropertyChanged.Fody
FFImageLoading

You can download the full code here:
https://github.com/CrossGeeks/Xamarin.Samples/tree/master/Xamarin%20Forms/ImageFilterSample

Happy coding!!

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *