34

I am working on an Iphone application.

I have png pictures that represents symbols. symbols are all black with a transparent background.

Is there a way I can turn the black color into another one? What I'm looking for is something that can help me choose the color I want and when using the symbols (in a UIImage) I can make them appear the color of my choice.

I have searched around and found a framework called OpenCV that can manipulate images but I cant find out how to recolor the picture.

Any help and suggestion is greatly appreciated.

Thank you

2
  • why dont you edit it in photoshop ? it is much easier for you
    – omsi
    Commented Sep 12, 2012 at 21:15
  • 7
    I have 1500 symbol that changes every week. I'm not sure this is a good idea
    – Y2theZ
    Commented Sep 12, 2012 at 21:18

8 Answers 8

106

The easiest and shortest:

Way to do that in case when you dealing with UIImageView:

Obj-C:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

Swift:

let theImageView = UIImageView(image: UIImage(named:"foo")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate))
theImageView.tintColor = UIColor.redColor()
1
  • The question requires you to perform the background color change on UIImage object instead of UIImageView. In some cases you want to be able to do that instead of setting the tint color on the view container.
    – Rushabh
    Commented Jan 10, 2017 at 19:44
35

hi you want to change remove/ one specific color means use the below category....

.h file:

#import <UIKit/UIKit.h>

@interface UIImage (Color)

+ (UIImage*)setBackgroundImageByColor:(UIColor *)backgroundColor withFrame:(CGRect )rect;


+ (UIImage*) replaceColor:(UIColor*)color inImage:(UIImage*)image withTolerance:(float)tolerance;

+(UIImage *)changeWhiteColorTransparent: (UIImage *)image;

+(UIImage *)changeColorTo:(NSMutableArray*) array Transparent: (UIImage *)image;

//resizing Stuff...
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize;

@end

.m file

#import <QuartzCore/QuartzCore.h>
#import "UIImage+Color.h"

@implementation UIImage (Color)




+ (UIImage* )setBackgroundImageByColor:(UIColor *)backgroundColor withFrame:(CGRect )rect{

    // tcv - temporary colored view
    UIView *tcv = [[UIView alloc] initWithFrame:rect];
    [tcv setBackgroundColor:backgroundColor];


    // set up a graphics context of button's size
    CGSize gcSize = tcv.frame.size;
    UIGraphicsBeginImageContext(gcSize);
    // add tcv's layer to context
    [tcv.layer renderInContext:UIGraphicsGetCurrentContext()];
    // create background image now
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     return image;
//    [tcv release];

}





+ (UIImage*) replaceColor:(UIColor*)color inImage:(UIImage*)image withTolerance:(float)tolerance {
    CGImageRef imageRef = [image CGImage];

    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    NSUInteger bitmapByteCount = bytesPerRow * height;

    unsigned char *rawData = (unsigned char*) calloc(bitmapByteCount, sizeof(unsigned char));

    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    CGColorRef cgColor = [color CGColor];
    const CGFloat *components = CGColorGetComponents(cgColor);
    float r = components[0];
    float g = components[1];
    float b = components[2];
    //float a = components[3]; // not needed

    r = r * 255.0;
    g = g * 255.0;
    b = b * 255.0;

    const float redRange[2] = {
        MAX(r - (tolerance / 2.0), 0.0),
        MIN(r + (tolerance / 2.0), 255.0)
    };

    const float greenRange[2] = {
        MAX(g - (tolerance / 2.0), 0.0),
        MIN(g + (tolerance / 2.0), 255.0)
    };

    const float blueRange[2] = {
        MAX(b - (tolerance / 2.0), 0.0),
        MIN(b + (tolerance / 2.0), 255.0)
    };

    int byteIndex = 0;

    while (byteIndex < bitmapByteCount) {
        unsigned char red   = rawData[byteIndex];
        unsigned char green = rawData[byteIndex + 1];
        unsigned char blue  = rawData[byteIndex + 2];

        if (((red >= redRange[0]) && (red <= redRange[1])) &&
            ((green >= greenRange[0]) && (green <= greenRange[1])) &&
            ((blue >= blueRange[0]) && (blue <= blueRange[1]))) {
            // make the pixel transparent
            //
            rawData[byteIndex] = 0;
            rawData[byteIndex + 1] = 0;
            rawData[byteIndex + 2] = 0;
            rawData[byteIndex + 3] = 0;
        }

        byteIndex += 4;
    }

    UIImage *result = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];

    CGContextRelease(context);
    free(rawData);

    return result;
}

+(UIImage *)changeWhiteColorTransparent: (UIImage *)image
{
    CGImageRef rawImageRef=image.CGImage;

    const float colorMasking[6] = {222, 255, 222, 255, 222, 255};

    UIGraphicsBeginImageContext(image.size);
    CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking);
    {
        //if in iphone
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height);
        CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); 
    }

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef);
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    CGImageRelease(maskedImageRef);
    UIGraphicsEndImageContext();    
    return result;
}




+(UIImage *)changeColorTo:(NSMutableArray*) array Transparent: (UIImage *)image
{
    CGImageRef rawImageRef=image.CGImage;

//    const float colorMasking[6] = {222, 255, 222, 255, 222, 255};

     const float colorMasking[6] = {[[array objectAtIndex:0] floatValue], [[array objectAtIndex:1] floatValue], [[array objectAtIndex:2] floatValue], [[array objectAtIndex:3] floatValue], [[array objectAtIndex:4] floatValue], [[array objectAtIndex:5] floatValue]};


    UIGraphicsBeginImageContext(image.size);
    CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking);
    {
        //if in iphone
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height);
        CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); 
    }

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef);
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    CGImageRelease(maskedImageRef);
    UIGraphicsEndImageContext();    
    return result;
}

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    //UIGraphicsBeginImageContext(newSize);
    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}



@end

i changed the removed white color to transparent by this code....

the call will be...

 self.rawImage.image=[UIImage changeWhiteColorTransparent:originalStateImage];

i hope this idea will help you....

6
  • 2
    Could you give an example usage of the changeColorTo method. i.e. what should the array parameter contain?
    – Tyson
    Commented Mar 4, 2013 at 0:01
  • I need to replace all white pixels with a different color at runtime, keeping the alpha values the same. e.g. RGBA of 255,255,255,255 -> 128,128,128,255. But RGBA of 255,255,255,128 -> 128,128,128,128. Is your changeColorTo method what I am after?
    – Tyson
    Commented Mar 4, 2013 at 0:03
  • You should use UIGraphicsBeginImageContextWithOptions() if you want images to look crisp on Retina devices.
    – Devfly
    Commented May 23, 2013 at 10:29
  • 4
    Give credit to the author. Here's the repo where that code probably came from: github.com/AckeeCZ/ACKategories/blob/master/UIImage%2BColor.h
    – user546719
    Commented Mar 31, 2014 at 20:17
  • 5
    Somehow the link got messed up. github.com/AckeeCZ/ACKategories/tree/master/ACKategories/UIKit The categories in question are in UIImage+Color.h
    – user546719
    Commented Apr 1, 2014 at 15:02
10

hi use this category file to change the image entire color....

.h file:

#import <UIKit/UIKit.h>

@interface UIImage (AddtionalFunctionalities)

//TintColor...
- (UIImage *)imageWithTint:(UIColor *)tintColor;
//scale and resize...
-(UIImage*)scaleToSize:(CGSize)size;

@end

.m file:

#import "UIImage+AddtionalFunctionalities.h"

@implementation UIImage (AddtionalFunctionalities)


- (UIImage *)imageWithTint:(UIColor *)tintColor 
{
    // Begin drawing
    CGRect aRect = CGRectMake(0.f, 0.f, self.size.width, self.size.height);
    CGImageRef alphaMask;

    //
    // Compute mask flipping image
    //
    {
        UIGraphicsBeginImageContext(aRect.size);        
        CGContextRef c = UIGraphicsGetCurrentContext(); 

        // draw image
        CGContextTranslateCTM(c, 0, aRect.size.height);
        CGContextScaleCTM(c, 1.0, -1.0);
        [self drawInRect: aRect];

        alphaMask = CGBitmapContextCreateImage(c);

        UIGraphicsEndImageContext();
    }

    //
    UIGraphicsBeginImageContext(aRect.size);

    // Get the graphic context
    CGContextRef c = UIGraphicsGetCurrentContext(); 

    // Draw the image
    [self drawInRect:aRect];

    // Mask
    CGContextClipToMask(c, aRect, alphaMask);

    // Set the fill color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextSetFillColorSpace(c, colorSpace);

    // Set the fill color
    CGContextSetFillColorWithColor(c, tintColor.CGColor);

    UIRectFillUsingBlendMode(aRect, kCGBlendModeNormal);

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();    

    // Release memory
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(alphaMask);

    return img;
}


-(UIImage*)scaleToSize:(CGSize)size
{
    // Create a bitmap graphics context
    // This will also set it as the current context
    UIGraphicsBeginImageContext(size);

    // Draw the scaled image in the current context
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];

    // Create a new image from current context
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();

    // Pop the current context from the stack
    UIGraphicsEndImageContext();

    // Return our new scaled image
    return scaledImage;
}

@end

the method call will be :

 self.outputImage.image=[sourceImage imageWithTint:[UIColor redColor]];

if u want to use the image means use this:

self.outputImage.image=[sourceImage imageWithTint:[UIColor colorWithPatternImage:[UIImage imageNamed: @"red.jpg"]]];

i hope this will help you...

3
  • Note: this changes entire image to one color... (e.g like black,blue )
    – Arun
    Commented Sep 13, 2012 at 4:59
  • kCGBlendModeNormal should be kCGBlendModeColor
    – Riskov
    Commented Sep 3, 2013 at 14:25
  • Thank u.. works like a charm.. :) I wish I could upvote twice. Commented Feb 23, 2016 at 7:59
6

Set the Image rendering mode then for color purpose use tintcolor property.

yourImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[yourImageView setTintColor:[UIColor redColor]];
1

For iOS 13.0

Obj-C:

self.yourImageView.image = [self.yourImageView.image imageWithTintColor:[UIColor.redColor]];

Swift:

yourImageView.image = yourImageView.image.withTintColor(UIColor.red);

If the image comes from the Asset Catalog, you can change the rendering in the Attribute Inspector

Attribute Inspector screenshot

0

You can create UIView which store UIImageView and change UIview background Color.

UIView *viewForImage = ....;
UIImageView *imageView = .....;
...

[viewForImage addSubview: imageView];
[self.view addSubview:viewForImage];
...

and then use for example

[viewForImage setBackgroundColor: [UIColor redColor]];
0

For playing with images using objective-c, mainly you have to use Quartz 2D/CoreGraphics framework. I suppose it will be the easiest way for you to accomplish your task.

The link to Quartz 2D guideline is here , the guideline is pretty comprehensive. Just have a look somewhere in filling the bitmap with color.

Also I've some records about the heavy image processing in my blog, you can have a look, it might be helpfull. http://levonp.blogspot.de/2012/05/quartz-getting-diff-images-of-two.html

Of course you can do it also using more advanced stuffs like OpenGL, OpenCV, etc.

0

A very simple solution to change the color of the image. Idea: extensions for UIImage and UIImageView.

Swift 3, Xcode 8.1. https://stackoverflow.com/a/40884483/4488252

Code sample from my answer (link above):

// use extension UIImage
newImageView = createNewImageView(x: 100)
newImageView.image =  UIImage(named: "Apple")?.imageWithColor(newColor: UIColor.blue)

// use extension UIImageView
newImageView = createNewImageView(x: 160)
newImageView.image =  UIImage(named: "Apple")
newImageView.imageColor = UIColor.green

Not the answer you're looking for? Browse other questions tagged or ask your own question.