Monday, 30 November 2015

Accessing Image Pixel Data in a Xamarin.Forms App

As a Xamarin employee, I spend a lot of my time writing code and content that ultimately ends up on the Xamarin Developer Center. Because of this, it’s not often that I have things to say on this blog, as I’ve already said them in official Xamarin code/content. However, I’m working on a longer term project that won’t be published for a while, and it offers me the opportunity to share some early code, that’s often been requested by the community. Specifically, I’ve been working on accessing image pixel data from a Xamarin.Forms app, so that users will be able to perform image manipulation from Xamarin.Forms.

The purpose of this blog post is to describe a basic architecture for accessing and manipulating pixel data from a Xamarin.Forms project. This will involve using the DependencyService to execute platform-specific code to access and manipulate pixel data. However, the imaging operations can be defined in the Xamarin.Forms PCL project.

Disclaimer: This code featured here is alpha code, so all the usual caveats apply.

Implementation

In my Xamarin.Forms PCL project I’ve created the IBitmap interface, which defines the operations that must be implemented in each platform-specific project.

1 public interface IBitmap<T>
2 {
3 void ToPixelArray ();
4
5 void TransformImage (Func<byte, byte, byte, double> pixelOperation);
6
7 T ToImage ();
8 }

The ToPixelArray method is used to convert the native image type to a byte array of raw pixel data. The TransformImage method is used to perform an imaging operation on the pixel data, such as convert to greyscale, convert to sepia, colour balance etc. The ToImage method is then used to convert the transformed pixel data back to the native image type. Eventually I expect there to be more operations specified in the IBitmap interface, including overloads of some of the existing operations.

The TransformImage method specifies a Func parameter. This Func will be used to perform per-pixel operations. For example, the ConvertToGreyscale Func, shown below, is used to convert an image to its greyscale representation:

1 public static class ImagingOperations
2 {
3 public static Func<byte, byte, byte, double> ConvertToGreyscale = (r, g, b) => 0.299 * (r - g) + g + 0.114 * (b - g);
4 }

This Func will be passed from the Xamarin.Forms PCL project into the TransformImage implementation in each platform specific project, where it will be executed on each pixel in the image. The advantage of this approach is that any per-pixel imaging operations can all be defined once, in the Xamarin.Forms PCL project.

Summary

This blog post has described a basic architecture for accessing and manipulating pixel data from a Xamarin.Forms project. My next blog post will explain the implementation of the IBitmap interface in iOS.