- (UIImage *) changeColorForImage:(UIImage *)image toColor:(UIColor*)color {
UIGraphicsBeginImageContext(image.size);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
// Retrieve source image and begin image context
CGSize itemImageSize = [image size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
// Fill and end the transparency layer
const float* colors = CGColorGetComponents( color.CGColor );
CGContextSetRGBFillColor(c, colors[0], colors[1], colors[2], .75);
contextRect.size.height = -contextRect.size.height;
contextRect.size.height -= 15;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Now that I know this simple code, I can even create idiotic methods like:
Now that I know this simple code, I can even create idiotic methods like:
- (UIColor*) oppositeColor:(UIColor*)color {
const float* colors = CGColorGetComponents(color.CGColor);
return [UIColor colorWithRed:1-colors[0] green:1-colors[1] blue:1-colors[2] alpha:1];
}
15 comments:
thanks you so much man, it's exaclt what I was looking for.
Louis.
Very much welcome, glad to help out :)
Yo! This code doesn't properly take into account the color space of the input UIColor. Specifically, it fails to render grayscale colors properly. Here is a modified version that takes this into account:
+ (UIImage*)changeColorForImage:(UIImage *)image toColor:(UIColor*)color
{
UIGraphicsBeginImageContext(image.size);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
// Retrieve source image and begin image context
CGSize itemImageSize = [image size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
// Fill and end the transparency layer
CGColorSpaceRef colorSpace = CGColorGetColorSpace(color.CGColor);
CGColorSpaceModel model = CGColorSpaceGetModel(colorSpace);
const CGFloat* colors = CGColorGetComponents(color.CGColor);
if(model == kCGColorSpaceModelMonochrome)
{
CGContextSetRGBFillColor(c, colors[0], colors[0], colors[0], colors[1]);
}else{
CGContextSetRGBFillColor(c, colors[0], colors[1], colors[2], colors[3]);
}
contextRect.size.height = -contextRect.size.height;
contextRect.size.height -= 15;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Hey! This code doesn't properly account for different color spaces of the input UIColor. Specifically, it renders grayscale colors improperly. Here is a modified version that takes the input color space into account.
+ (UIImage*)changeColorForImage:(UIImage *)image toColor:(UIColor*)color
{
UIGraphicsBeginImageContext(image.size);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
// Retrieve source image and begin image context
CGSize itemImageSize = [image size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
// Fill and end the transparency layer
CGColorSpaceRef colorSpace = CGColorGetColorSpace(color.CGColor);
CGColorSpaceModel model = CGColorSpaceGetModel(colorSpace);
const CGFloat* colors = CGColorGetComponents(color.CGColor);
if(model == kCGColorSpaceModelMonochrome)
{
CGContextSetRGBFillColor(c, colors[0], colors[0], colors[0], colors[1]);
}else{
CGContextSetRGBFillColor(c, colors[0], colors[1], colors[2], colors[3]);
}
contextRect.size.height = -contextRect.size.height;
contextRect.size.height -= 15;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Hey Ben,
You are right. Under what condition would be you be in (using?) a different color space?
Thanks!
D
Hi Ben,
thanks for that nice code...
Is it possible to one color to another color ....
not a single color alone like transparent...?
my task was change one entire color[ARGB] to another set of colors[ARGB]
have any suggestions and ideas...
Hi Ben,
Code looks great and thanks for the code...
Is it possible to change one complete color [ARGB not transparent] to another color...?
any idea regarding this please share
Thanks,
Spynet
Hi Ben,
Code looks great and thanks for the code...
Is it possible to change one complete color [ARGB not transparent] to another color...?
any idea regarding this please share
Thanks,
Spynet
Hi Ben,
Code looks great and thanks for the code...
Is it possible to change one complete color [ARGB not transparent] to another color...?
any idea regarding this please share
Thanks,
Spynet
So, I did a small number of fixes to the code which are on https://gist.github.com/4353039. I'd really like to know whether my changes are actually worthy or if I broke some weird case (works for me!).
So, I wrote this gist at https://gist.github.com/4353039, with some fixes and removal of unneeded parts. If I broke some use case I'm unaware of, please let me know, but as far as I've tested it it works fine.
Solved my problem where I wanted to have the possibility to change (unselected) icon colours in UITabBar without using different coluored images.
I also made this change to accommodate for a scaling issue with retina images (diff):
-UIGraphicsBeginImageContextWithOptions(contextRect.size);
+UIGraphicsBeginImageContextWithOptions(contextRect.size, NO, image.scale);
UIImage *image = [UIImage imageNamed:@"triangle.png"];
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, rect, image.CGImage);
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *flippedImage = [UIImage imageWithCGImage:img.CGImage
scale:1.0 orientation: UIImageOrientationDownMirrored];
yourUIImageView.image = flippedImage;
hello, i have one question please.. what if i have a patterned image, so every specific color should be changed into other one.. how could i do this?
appreciate your help
hello, i have one question please.. what if i have a patterned image so every specific color should be changed to another one.. appreciate your help
Post a Comment