How to change the color of a transparent image in iOS
This is probably as good a time as any to mention the next project I’m working on. It’s a turn-based (yes, asynchronous) board game. I decided to work with an existing game, because I wanted it to be really awesome, but also really simple. It’s an abstract game that is well respected in some circles. (I’m not going to reveal which one just yet.) Anyway, I’m working closely with the game’s designer, as well as with the same AI programmer I worked with on For The Win. The main goal of the project is to get the async code really solid, so I can feel like I really understand how it works, and re-use it in future projects.
Anyway, I think I’m also going to try something I’ve wanted to do before, and that is implement a variable color scheme for the app. Essentially you’ll be able to change the app’s background color, and that will also programmatically change the color scheme. I spent about two hours and had the basic color change functionality working pretty great with some code based on an already pretty great open-source color picker.
Anyway, one tiny piece remained… I would need to be able to programmatically tint images I get from the designer on this project. He’s going to give me some icons and other assets that we’ll no doubt want to change colors along with the rest of the app.
Some unknown number of hours later, I’ve got a solution. The number of hours is probably around the same as the number of lines of code in the solution. Here are those lines, implemented in the
drawRect: method of a
UIView subclass with a
UIImage property named image, and a
UIColor property named colorToChangeInto.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -rect.size.height);
CGImageRef maskImage = [self.image CGImage];
CGContextClipToMask(context, rect, maskImage);
I hope this is fairly straight forward. These few lines stand on the backs of many stack overflow answers. (And I did actually write this up into a question of my own at some point.) None of the other answers were exactly what I needed, but several of them got me close. In the end, I was super frustrated because it really seemed like I should be seeing what I wanted to see, but the background of the image was black… turned out I was instantiating the image in IB (in a storyboard), but I hadn’t set the background color. Somehow that defaulted to black. That particular issue probably wasted me an hour or two.
And then writing this blog post… another half-hour, at least.