iPhone: How to Dynamically Color a UIImage

by Chadwick Wood
September 24th, 2010

In my recent work on Sphericle, there were a few instances where I wanted to use the same image over and over, but colored differently each time. For example, I want to show spheres of different colors on a map; there are 360,000 spheres, each having its own color. I didn't want to draw the sphere algorithmically; I wanted the picture of a sphere to be based on an image, but then colored appropriately. The solution: use a grayscale image of a sphere, then draw a color over it using a color burn blend mode. That's what I want to show you today.

The Basic Idea

The process for generating a dynamically-colored UIImage is pretty simple: draw a grayscale image, mask it with itself (to bound the drawing area to the image itself), then overlay the color you want, with the blend mode set to color burn.

For my example code, I'm using an image of a badge:

The Code

Here is the basic code to take the image and color it. But read on for more explanation and example code.

// load the image
NSString *name = @"badge.png";
UIImage *img = [UIImage imageNamed:name];

// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(img.size);

// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();

// set the fill color
[color setFill];

// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);

// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);

// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//return the color-burned image
return coloredImg;

Make it Reusable

Because this is the kind of thing that you might want to use repeatedly in an app, it makes sense to make it reusable somehow. What I did was to create a Category on the UIImage class. The method I created is:

+ (UIImage *)imageNamed:(NSString *)name withColor:(UIColor *)color;

With that, we have a nice convenience method that just needs the name of the image file, and the color you want, and you get your colored image returned to you!