Creating beautiful image effects using .NET MAUI

Creating beautiful image effects using .NET MAUI

10 July 2022

.NET MAUI/Xamarin

Buy Me A Coffee

Hello!

In this article, we will create and apply the blur effect to the Image control using .NET MAUI behaviors.

The effect allows the blurring of out-of-focus parts of an image. It is usually used in portrait photos.

For this article, I use a .NET MAUI combination of filename-based multi-targeting and folder-based multi-targeting. For more information, see Combine filename and folder multi-targeting.

Let's start by creating a new BlurBehavior.cs file:

public partial class BlurBehavior
{
	public static readonly BindableProperty RadiusProperty = BindableProperty.Create(nameof(Radius), typeof(float), typeof(BlurBehavior), 5f, propertyChanged: OnRadiusChanged);

	public float Radius
	{
		get => (float)GetValue(RadiusProperty);
		set => SetValue(RadiusProperty, value);
	}

	static void OnRadiusChanged(BindableObject bindable, object oldValue, object newValue)
	{
		var behavior = (BlurBehavior)bindable;
		if (behavior.imageView is null)
		{
			return;
		}

		behavior.SetRendererEffect(behavior.imageView, Convert.ToSingle(newValue));
	}
}

Now we need to implement our BlurBehavior for each platform.

Android

Create BlurBehavior.Android.cs:

public partial class BlurBehavior : PlatformBehavior<Image, ImageView>
{
	ImageView? imageView;
	protected override void OnAttachedTo(Image bindable, ImageView platformView)
	{
		imageView = platformView;
		SetRendererEffect(platformView, Radius);
	}

	protected override void OnDetachedFrom(Image bindable, ImageView platformView)
	{
		SetRendererEffect(platformView, 0);
	}

	void SetRendererEffect(ImageView imageView, float radius)
	{
		if (OperatingSystem.IsAndroidVersionAtLeast(31))
		{
			var renderEffect = radius > 0 ? GetEffect(radius) : null;
			imageView.SetRenderEffect(renderEffect);
		}
	}

	static RenderEffect? GetEffect(float radius)
	{
		return OperatingSystem.IsAndroidVersionAtLeast(31) ?
			RenderEffect.CreateBlurEffect(radius, radius, Shader.TileMode.Decal!) :
			null;
	}
}

In Android 12, Google introduced the RenderEffect API. This enables developers to effortlessly apply graphic effects such as blurs, color filters, and more to Views.

iOS/MacCatalyst

Create BlurBehavior.iOS.cs:

public partial class BlurBehavior : PlatformBehavior<Image, UIImageView>
{
	private CGImage? originalImage;
	UIImageView? imageView;

	protected override void OnAttachedTo(Image bindable, UIImageView platformView)
	{
		imageView = platformView;

		originalImage = platformView.Image?.CGImage;
		SetRendererEffect(imageView, Radius);
	}

	protected override void OnDetachedFrom(Image bindable, UIImageView platformView)
	{
		SetImage(platformView, originalImage);
	}

	static void SetImage(UIImageView imageView, CGImage? image)
	{
		if (image is null)
		{
			return;
		}

		imageView.Image = new UIImage(image);
	}

	void SetRendererEffect(UIImageView imageView, float radius)
	{
		if (originalImage is null)
		{
			return;
		}

		var myContext = CIContext.Create();
		var inputImage = new CIImage(originalImage);
		var filter = new CIGaussianBlur
		{
			InputImage = inputImage,
			Radius = radius
		};
		var resultImage = myContext.CreateCGImage(filter.OutputImage!, inputImage.Extent);
		SetImage(imageView, resultImage);
	}
}

Windows

Create BlurBehavior.Windows.cs:

public partial class BlurBehavior : PlatformBehavior<Image, Microsoft.UI.Xaml.Controls.Image>
{
	Microsoft.UI.Xaml.Controls.Image? imageView;
	protected override async void OnAttachedTo(Image bindable, Microsoft.UI.Xaml.Controls.Image platformView)
	{
		imageView = platformView;
		SetRendererEffect(platformView, Radius);
	}

	protected override void OnDetachedFrom(Image bindable, Microsoft.UI.Xaml.Controls.Image platformView)
	{
		SetRendererEffect(platformView, 0);
	}

	void SetRendererEffect(Microsoft.UI.Xaml.Controls.Image imageView, float radius)
	{
		var graphicsEffect = new GaussianBlurEffect()
		{
			Name = "Blur",
			Source = new CompositionEffectSourceParameter("Source"),
			BlurAmount = radius
		};

		var compositor = ElementCompositionPreview.GetElementVisual(imageView).Compositor;
		var blurEffectFactory = compositor.CreateEffectFactory(graphicsEffect);

		var brush = blurEffectFactory.CreateBrush();
		var destinationBrush = compositor.CreateBackdropBrush();
		brush.SetSourceParameter("Source", destinationBrush);

		var blurSprite = compositor.CreateSpriteVisual();
		blurSprite.Brush = brush;
		blurSprite.Size = imageView.ActualSize;
		ElementCompositionPreview.SetElementChildVisual(imageView, blurSprite);
	}
}

Finally, apply behavior to our image:

<Image Source="dotnet_bot.png" HeightRequest="200">
	<Image.Behaviors>
		<blur:BlurBehavior Radius="10" />
	</Image.Behaviors>
</Image>

As a result, you should receive such app:

Blur

The full code with different effects can be found on GitHub.

Happy coding!

Buy Me A Coffee

Related:

The first project with .NET MAUI

How to migrate Xamarin.Forms app to .NET MAUI step by step.

Create a gallery app using .NET MAUI Blazor

Create infinite scrolling gallery app using .NET MAUI Blazor. Replicate Google Photos and Instagram Gallery UI.

An unhandled error has occurred. Reload

🗙