Month: September 2012

CIFilters with MonoMac

In a recent project I found I needed to colourise (colorize to you Americans!) a greyscale image. Fortunately Apple have built-in support for various colour filters, including the multiply filter I needed. Unfortunately CoreImage only works on CoreImage images, not NSImages – and there’s no easy way to convert between the two.

Original ImageRed TintGreen TintBlue Tint

Converting from CIImage to NSImage

Fortunately with Extension Methods, converting a CIImage to an NSImage isn’t too hard:

public static NSImage ToNSImage(this CIImage image)
{
	return ToNSImage(image, image.Extent.Size);
}

public static NSImage ToNSImage(this CIImage image, SizeF size)
{
	var imageRep = NSCIImageRep.FromCIImage(image);
	var nsImage = new NSImage(size);
	nsImage.AddRepresentation(imageRep);

	return nsImage;
}

First we get an NSCIImageRep instance from the CIImage – NSCIImageRep is a class that can render a CIImage. Next we create our new NSImage and use the AddRepresentation method to populate the NSImage with the CIImage. Internally the NSCIImageRep instance will render the CIImage to memory in a bitmap format, NSImage will then populate itself with this bitmap.

Tinting the Greyscale image with CoreImage

Now we don’t need to worry about using CIImages with abandon we can focus on the actual tinting. We need to load in our image, then we need to create a tint image, finally we need to multiply the two together just like in Photoshop. Let’s load in our graphics first:

var mainImage = CIImage.FromUrl(NSUrl.FromFilename(NSBundle.MainBundle.PathForResource(
	Path.GetFileNameWithoutExtension(ImagePath), Path.GetExtension(ImagePath))));
var tintImage = CIImage.ImageWithColor(CIColor.FromRgb(1f, 0f, 0f));

We load in the image using FromUrl here since it’s the most efficient manner. If we loaded in via an NSImage, we would be wasting memory in both the load and conversion process – better to load from the file system directly. If you need to use the same image repeatedly, load in the image as a byte array and create an instance of CIImage using the data.  Next we create our filter:

var filter = CIFilter.FromName("CIMultiplyCompositing");

Unfortunately MonoMac doesn’t contain strongly typed bindings for any CoreImage filters, so we need to populate the input parameters using Key-Value Coding:

filter.SetValueForKey(tintImage, (NSString)"inputImage");
filter.SetValueForKey(mainImage, (NSString)"inputBackgroundImage");

We need to cast here because Key-Value coding requires NSString instances. NSString has an implicit conversion operator for string, allowing us to cast string directly to NSString. Note the key names, these must match exactly, each filter has different parameters – a reference for all filter types and their parameters is available here. Now we can perform the tint and display the result:

var processedImage = (CIImage)filter.ValueForKey((NSString)"outputImage");
var outputImage = processedImage.ToNSImage();

ImageView.Image = outputImage;

And that’s it! If the filter fails for any reason ValueForKey will return NULL. The code above will apply a red tint and you should get something like:

Red Tint

Posted by Dan in C#, Guides, Mac, Mac, 0 comments

Implementing IParcelable in Mono for Android

If you want to pass values between activities in Android, you’ll probably want to implement Parcelable sooner or later. This isn’t particularly slick even when writing natively, but add Mono in and it becomes even murkier. Fortunately .NET’s Generics support helps us out a little. The reason for the rather heavy implementation is intents can cross process boundaries, meaning you can’t just provide a memory address. This gives you the ability to call apps / resources you haven’t programmed yourself, but unfortunately it means inter-activity communication is ‘heavy’ for want of a better term. If you’re thinking of using IParcelable in a brand new app that isn’t going to be receiving 3rd party parcels, consider the ‘alternatives’ at the end of this guide first. IParcelable is somewhat of a convenience API for serialising objects to binary and then de-serialising. You might be better off doing this yourself rather than using the ‘Android’ method.

Our Class

For this demo I want to pass an array of a really simple class:

public sealed class SelectListItem
{
	// Convenience constructors
	public SelectListItem() {}
	public SelectListItem(int id, string name)
	{
		Id = id;
		Name = name;
	}

	// The actual properties for this class
	public int Id { get; set; }
	public string Name { get; set; }
}

Reference ‘Mono.Android.Export’

Before we start, make sure to reference the ‘Mono.Android.Export’ assembly:

Mono.Android.Export Assembly Reference

Implementing IParcelable

This class will be used to populate a ListActivity with a series of items that can be selected. First we need to inherit from Java.Lang.Object, and implement the IParcelable interface:

public sealed class SelectListItem : Java.Lang.Object, IParcelable

So why do we have to inherit from Java.Lang.Object? The Android runtime needs to be able to call the methods that we define as part of IParcelable, to do this our class must have a dual-personality. One half of the class is .NET, the other half is Java, it is this Java side that Android can see. When a method is called on the Java side, it will execute the .NET code. Clever huh? Unfortunately this means we now have two objects instead of one in memory, it also means that Mono must keep track of both objects. To do this it uses a global ID or reference, this reference links the two instances together. Unfortunately GREFs, are a very, very limited resource. The emulator only supports ~2,000 and devices usually only support ~50,000 GREFs. For more information on GREFs, check the Architecture and Garbage Collection documents over at Xamarin.

Before we implement the interface, we need to add an additional constructor that can accept a Parcel type. This constructor will populate the instance with the values from the parcel – the parcel being the ‘wrapped’ data of an instance of the same type:

// Create a new SelectListItem populated with the values in parcel
private SelectListItem(Parcel parcel)
{
	Id = parcel.ReadInt();
	Name = parcel.ReadString();
}

Note the order we read in the values, this is very important and must mirror the order in WriteToParcel below.

Next we need to implement the interface:

public int DescribeContents()
{
	return 0;
}

// Save this instance's values to the parcel
public void WriteToParcel(Parcel dest, ParcelableWriteFlags flags)
{
	dest.WriteInt(Id);
	dest.WriteString(Name);
}

DescribeContents is used for flagging ‘special objects’ within the parcel. I’ve never had cause to use this field, and 0 means ‘no special objects’.

WriteToParcel is where we write the instance data to the parcel, pay special attention to the order you write the values. This same order must be mirrored when reading in the parcel above. The flags attribute gives additional information on how the data should be written, it’s unlikely you’ll need to check these flags.

The CREATOR field

All Parcelable objects must have a public static field called CREATOR. The instance behind this field is responsible for creating instances of the object and populating them from the parcel. This can be done in two ways, an internal class that is implementation-specific, or a generic class that can be re-used repeatedly. The first method is the method commonly used in Java applications. However, with .NET we gain a much more robust Generics implementation so we’ll go down that route. However if you’re interested in the Java-favoured implementation it’s available in the sample project as a comment.

Without further ado, let’s look at how to declare our creator:

// The creator creates an instance of the specified object
private static readonly GenericParcelableCreator<SelectListItem> _creator
	= new GenericParcelableCreator<SelectListItem>((parcel) => new SelectListItem(parcel));

[ExportField("CREATOR")]
public static GenericParcelableCreator<SelectListItem> GetCreator()
{
	return _creator;
}

First we declare a private static instance, it’s required to be static by the Android API. Because this instance is static, it’s critical that your creator is thread safe otherwise bad things will happen. After the actual instance declaration we create a public static method, and decorate it with the ExportField attribute. Unfortunately this attribute can only be used on methods, so we can’t decorate our field directly. ExportField will ensure the Java version of our class gains a public static field named CREATOR.

A Generic ParcelableCreator Implementation

Earlier I mentioned that when developing with Java, each Parcelable requires a custom creator. Fortunately with .NET we gain a robust Generic implementation and we can use a generic creator that we can use again and again:

public sealed class GenericParcelableCreator<T> : Java.Lang.Object, IParcelableCreator
	where T : Java.Lang.Object, new()
{
	private readonly Func<Parcel, T> _createFunc;

	/// <summary>
	/// Initializes a new instance of the <see cref="ParcelableDemo.GenericParcelableCreator`1"/> class.
	/// </summary>
	/// <param name='createFromParcelFunc'>
	/// Func that creates an instance of T, populated with the values from the parcel parameter
	/// </param>
	public GenericParcelableCreator(Func<Parcel, T> createFromParcelFunc)
	{
		_createFunc = createFromParcelFunc;
	}

	#region IParcelableCreator Implementation

	public Java.Lang.Object CreateFromParcel(Parcel source)
	{
		return _createFunc(source);
	}

	public Java.Lang.Object[] NewArray(int size)
	{
		return new T[size];
	}

	#endregion
}

The creator must also be usable directly by Android, so again we have to inherit from Java.Lang.Object. We add two restrictions to the generic type parameter, first it must inherit from Java.Lang.Object (as all Parcelables must), and second it must have an empty constructor. This allows us to create an array of instances of the type, as required by IParcelableCreator.

Next in the constructor we require a delegate that can create and populate an instance of T. If you check back at our instantiation of the creator, we use a lambda expression that instantiates the instance using the private constructor we created that accepts a Parcel. Finally we implement the two methods required by IParcelableCreator, these simply create and populate the type, or create an array of the type.

Also remember that the creator must be thread-safe, if it isn’t bad things happen. To ensure thread safety we’ve made the state immutable, immutable types are by definition thread safe. If you need to create your own creator, be careful to follow thread safety guidelines. Microsoft have a good book on patterns and thread safety you can download for free.

Sample Code

You can download the sample project from GitHub here.

Select Item Item Selection Item Selected

Alternative to IParcelable

The problem with Parcelables is that you’re using up your very limited GREF resource. Additionally running two instances of an object across two garbage collectors isn’t the best use of memory or CPU resources. You’ll actually double up on instances as well, the instances that get packaged up in a parcel, and the instances that get extracted. The first set (senders) you can often clear from memory quickly, however the second set (received values) could be memory resident for quite some time as they’re used by the activity. The alternative is to either send just enough information for the activity to generate its own data, or you can send the data in an alternative format. You can send byte arrays, so you can use ISerializable and serialise your objects to binary. The other option is to use JSON (or other text-based format) and pass JSON strings between activities instead.

Unfortunately there is no ‘best’ solution, only the solution that meets your specific needs best.

Posted by Dan in C#, Mono for Android, Programming, Tutorials, 2 comments

Getting Forward / Backward mouse buttons working in Parallels Desktop For Mac

This is a follow-on post from my earlier blog post ‘Getting Back / Forward mouse buttons working in Mac OS X‘.

The big problem now is getting forward / backward working in Parallels (and VMware Fusion if it doesn’t work on that either). The reason for the problem is that Parallels emulates the mouse so you can easily move the mouse into and out of the VM window. Additionally the emulator lets you use gestures from the touch pad in Windows (very cool). The problem is, the emulator doesn’t support more than 3 buttons.

The Easy Fix

The easiest fix is to turn off SmartMouse:

This will give Windows direct access to the mouse, and you’ll be able to use the MS driver directly. Unfortunately if you do this, you’ll have to give / take the mouse from the VM manually using CMD+OPT.

The Real Fix

The real fix is to use my favourite HID tool – ControllerMate. I won’t go over how to configure rules that only apply to VMs, etc. that’s all covered in my previous blog post. Instead, let’s jump right to the rule itself:

Drag on mouse buttons #4 and #5 as inputs, and then link them up to keystrokes building blocks. For the back building block you need to use ALT + Left Arrow, and for the forward block you need ALT + Right arrow, like so:

Once set up, back & forward will be fully functional in Windows programs that support the keyboard shortcut.

Make sure these rules are only executed for the VM – these shortcuts won’t work for Mac!

Posted by Dan in Guides, Mac, 1 comment