Tinting a grayscale NSImage (or CIImage)

Pierre Bernard picture Pierre Bernard · Sep 11, 2009 · Viewed 15.9k times · Source

I have a grayscale image which I want to use for drawing Cocoa controls. The image has various levels of gray. Where it is darkest, I want it to draw a specified tint color darkest. I want it to be transparent where the source image is white.

Basically, I want to reproduce the behavior of tintColor seen in UINavigationBar on the iPhone.

So far, I have explored several options:

  • Draw the tint color over the grayscale image using SourceOver composition -> This requires a non-opaque tint color -> The result comes out much darker than desired

  • Use a CIMultiplyCompositing CIFilter to tint the image -> I can't [CIImage drawAtPoint:fromRect:operation:fraction:] to draw only part of the image. The same works fine with NSImage -> I get occasional crashes which I cannot make sense of

  • Transform the grayscale image into a mask. I.e. Black should be opaque. White should be transparent. Gray should have intermediate alpha values. -> This would seem to be the best solution -> Try as I might, I cannot achieve this.

Answer

bluebamboo picture bluebamboo · Apr 22, 2013

The above solution didn't work for me. But this much easier solution works great for me

- (NSImage *)imageTintedWithColor:(NSColor *)tint
{
    NSImage *image = [self copy];
    if (tint) {
        [image lockFocus];
        [tint set];
        NSRect imageRect = {NSZeroPoint, [image size]};
        NSRectFillUsingOperation(imageRect, NSCompositeSourceIn);
        [image unlockFocus];
    }
    return image;
}