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:

Migrate the deprecated OnBackPressed function in .NET MAUI Android application

This article is devoted to the new API added in Android 13, that adds support to predictive back gestures.

Extend .NET MAUI application with iOS Extensions

Extend the .NET MAUI application with iOS App Extension in 5 steps.

An unhandled error has occurred. Reload

🗙