Take the 2-minute tour ×

My question is if I have a Lion image just I want to change the color of the lion alone not the background color. For that I referred this SO question but it turns the color of whole image. Moreover the image is not looking great. I need the color change like photoshop. whether it is possible to do this in coregraphics or I have to use any other library.

EDIT : I need the color change to be like iQuikColor app

enter image description here

share|improve this question
nice question, if u got the perfect answer, i'll use that –  vijay gupta Nov 8 '11 at 6:30
i'm also having the same issue, i posted the question colorfill issue, –  arunios Nov 15 '11 at 6:48
I am trying jano's answer.. now got struck in 3 rd point... –  user08092013 Nov 15 '11 at 16:35
Wow. This is my app and that is my daughter. XD –  Rocotilos Oct 20 '13 at 5:43
@Rocotilos can you help please? I am trying for the same.. –  slaveCoder Dec 18 '13 at 9:11

4 Answers 4

up vote 16 down vote accepted

Here is the sketch of a possible solution using OpenCV:

  • Mask the color with cvInRangeS and use the resulting mask to apply the new hue.

There are several OpenCV iOS ports in the net, eg: http://www.eosgarden.com/en/opensource/opencv-ios/overview/ I haven't tried this myself, but seems a good research direction.

share|improve this answer
thanks jano.. I will try this.. –  user08092013 Nov 11 '11 at 4:22
Hi jano, I am stuck in step:4, I have applied cvInRangeS function and I got threashold image but not sure what do you mean by "use the resulting mask to apply the new hue." and how to use in step:5? can you please elaborate more about it –  Iducool Feb 26 '13 at 10:30

I'm going to make the assumption that you know how to perform these basic operations, so these won't be included in my solution:

  • load an image
  • get the RGB value of a given pixel of the loaded image
  • set the RGB value of a given pixel
  • display a loaded image, and/or save it back to disk.

First of all, let's consider how you can describe the source and destination colors. Clearly you can't specify these as exact RGB values, since a photo will have slight variations in color. For example, the green pixels in the truck picture you posted are not all exactly the same shade of green. The RGB color model isn't very good at expressing basic color characteristics, so you will get much better results if you convert the pixels to HSL. Here are C functions to convert RGB to HSL and back.

The HSL color model describes three aspects of a color:

  1. Hue - the main perceived color - i.e. red, green, orange, etc.
  2. Saturation - how "full" the color is - i.e. from full color to no color at all
  3. Lightness - how bright the color is

So for example, if you wanted to find all the green pixels in a picture, you will convert each pixel from RGB to HSL, then look for H values that correspond to green, with some tolerance for "near green" colors. Below is a Hue chart, from Wikipedia:

So in your case you will be looking at pixels that have a Hue of 120 degrees +/- some amount. The bigger the range the more colors will get selected. If you make your range too wide you will start seeing yellow and cyan pixels getting selected, so you'll have to find the right range, and you may even want to offer the user of your app controls to select this range.

In addition to selecting by Hue, you may want to allow ranges for Saturation and Lightness, so that you can optionally put more limits to the pixels that you want to select for colorization.

Finally, you may want to offer the user the ability to draw a "lasso selection" so that specific parts of the picture can be left out of the colorization. This is how you could tell the app that you want the body of the green truck, but not the green wheel.

Once you know which pixels you want to modify it's time to alter their color.

The easiest way to colorize the pixels is to just change the Hue, leaving the Saturation and Lightness from the original pixel. So for example, if you want to make green pixels magenta you will be adding 180 degrees to all the Hue values of the selected pixels (making sure you use modulo 360 math).

If you wanted to get more sophisticated, you can also apply changes to Saturation and that will give you a wider range of tones you can go to. I think the Lightness is better left alone, you may be able to make small adjustments and the image will still look good, but if you go too far away from the original you may start seeing hard edges where the process pixels border with background pixels.

Once you have the colorized HSL pixel you just convert it back to RGB and write it back to the image.

I hope this helps. A final comment I should make is that Hue values in code are typically recorded in the 0-255 range, but many applications show them as a color wheel with a range of 0 to 360 degrees. Keep that in mind!

share|improve this answer

Can I suggest you look into using OpenCV? It's an open source image manipulation library, and it's got an iOS port too. There are plenty of blog posts about how to use it and set it up.

It has a whole heap of functions that will help you do a good job of what you're attempting. You could do it just using CoreGraphics, but the end result isn't going to look nearly as good as OpenCV would.

It was developed by some folks at MIT, so as you might expect it does a pretty good job at things like edge detection and object tracking. I remember reading a blog about how to separate a certain color from a picture with OpenCV - the examples showed a pretty good result. See here for an example. From there I can't imagine it would be a massive job to actually change the separated color to something else.

share|improve this answer
thanks jordan.. I will try this.. –  user08092013 Nov 11 '11 at 4:22

I don't know of a CoreGraphics operation for this, and I don't see a suitable CoreImage filter for this. If that's correct, then here's a push in the right direction:

Assuming you have a CGImage (or a uiImage.CGImage):

  • Begin by creating a new CGBitmapContext
  • Draw the source image to the bitmap context
  • Get a handle to the bitmap's pixel data

Learn how the buffer is structured so you could properly populate a 2D array of pixel values which have the form:

typedef struct t_pixel {
  uint8_t r, g, b, a;
} t_pixel;

Then create the color to locate:

const t_pixel ColorToLocate = { 0,0,0,255 }; // << black, opaque

And its substitution value:

const t_pixel SubstitutionColor = { 255,255,255,255 }; // << white, opaque
  • Iterate over the bitmap context's pixel buffer, creating t_pixels.
  • When you find a pixel which matches ColorToLocate, replace the source values with the values in SubstitutionColor.

  • Create a new CGImage from the CGBitmapContext.

That's the easy part! All that does is takes a CGImage, replace exact color matches, and produces a new CGImage.

What you want is more sophisticated. For this task, you will want a good edge detection algorithm.

I've not used this app you have linked. If it's limited to a few colors, then they may simply be swapping channel values, paired with edge detection (keep in mind that buffers may also be represented in multiple color models - not just RGBA).

If (in the app you linked) the user can choose an arbitrary colors, values, and edge thresholds, then you will have to use real blending and edge detection. If you need to see how this is accomplished, you may want to check out a package such as Gimp (it's an open image editor) - they have the algos to detect edges and choose by color.

share|improve this answer
I too tried like this only.. but it takes time..May be I have to use an efficient algorithm. –  user08092013 Nov 11 '11 at 4:28
@Trisha I'd imagine a good implementation would take time for a full size image. But yes, the edge detection will likely take some time to calculate. On modern hardware, you could reasonably divide the processing among one or two secondary threads. As you say, the algo's also quite important. –  justin Nov 11 '11 at 15:09

Your Answer


