Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tint a transparent PNG image in iPhone?

I know it's possible to tint a rectangular image by drawing a CGContextFillRect over it and setting the blend mode. However, I can't figure out how to do a tint on a transparent image such as an icon. It must be possible since the SDK does it itself on tab-bars in such. Would anyone be able to provide a snippet?

UPDATE:

Lots of great suggestions have been given for this problem since I originally asked. Be sure to read through all the answers to figure out what suits you best.

UPDATE (Apr 30, 2015):

With iOS 7.0, I can now just do the following, which would satisfy the needs of my original question. But if you have more complicated cases, check out all the answers.

UIImage *iconImage = [[UIImage imageNamed:@"myImageName"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];     UIImageView *icon = [[UIImageView alloc] initWithImage:iconImage]; icon.tintColor = [UIColor redColor]; 
like image 910
anna Avatar asked Aug 18 '10 15:08

anna


People also ask

Do transparent Pngs work on iPhone?

Images with a transparent background (i.e., a transparent . png) can be uploaded to be used as a logo or a sticker on your video.

Why are my transparent images not transparent on iPhone?

If you've uploaded a file in this format, yet your logo appears with a white background, the reason is likely related to an issue on Apple's end: iOS devices (iPhone/iPad) with iOS version 13 and higher do not support transparent backgrounds, therefore the result image will come out with a white background.

Can you change transparency on PNG?

If you want to change the opacity of a smaller area than the entire PNG, you can select a rectangular area of the PNG and apply the opacity effect only in this region. The opacity region can be changed in the preview with your mouse or in the options using the left/right offsets and width/height parameters.

How do I make a transparent PNG color?

go to Image > Transparent Color... choose the color (white), set the desired tolerance with the slider, click OK. go to File > Save as... and save the image as . PNG.


1 Answers

Update: Here is a Gist for a Swift UIColor extension using the code below.


If you have a greyscale image and want white become the tinting color, kCGBlendModeMultiply is the way to go. With this method, you cannot have highlights lighter than your tinting color.

On the contrary, if you have either a non-greyscale image, OR you have highlights and shadows that should be preserved, the blend mode kCGBlendModeColor is the way to go. White will stay white and black will stay black as the lightness of the image is preserved. This mode is just made for tinting - it is the same as Photoshop's Color layer blend mode (disclaimer: slightly differing results may happen).

Note that tinting alpha-pixels does not work correctly neither in iOS nor in Photoshop - half-transparent black pixels would not stay black. I updated the answer below to work around that issue, it took quite a long time to find out.

You can also use one of the blend modes kCGBlendModeSourceIn/DestinationIn instead of CGContextClipToMask.

If you want to create a UIImage, each of the following code sections can be surrounded by the following code:

UIGraphicsBeginImageContextWithOptions (myIconImage.size, NO, myIconImage.scale); // for correct resolution on retina, thanks @MobileVet CGContextRef context = UIGraphicsGetCurrentContext();  CGContextTranslateCTM(context, 0, myIconImage.size.height); CGContextScaleCTM(context, 1.0, -1.0);  CGRect rect = CGRectMake(0, 0, myIconImage.size.width, myIconImage.size.height);  // image drawing code here  UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

So here's the code for tinting a transparent image with kCGBlendModeColor:

// draw black background to preserve color of transparent pixels CGContextSetBlendMode(context, kCGBlendModeNormal); [[UIColor blackColor] setFill]; CGContextFillRect(context, rect);  // draw original image CGContextSetBlendMode(context, kCGBlendModeNormal); CGContextDrawImage(context, rect, myIconImage.CGImage);  // tint image (loosing alpha) - the luminosity of the original image is preserved CGContextSetBlendMode(context, kCGBlendModeColor); [tintColor setFill]; CGContextFillRect(context, rect);  // mask by alpha values of original image CGContextSetBlendMode(context, kCGBlendModeDestinationIn); CGContextDrawImage(context, rect, myIconImage.CGImage); 

If your image has no half-transparent pixels, you could also do it the other way around with kCGBlendModeLuminosity:

// draw tint color CGContextSetBlendMode(context, kCGBlendModeNormal); [tintColor setFill]; CGContextFillRect(context, rect);  // replace luminosity of background (ignoring alpha) CGContextSetBlendMode(context, kCGBlendModeLuminosity); CGContextDrawImage(context, rect, myIconImage.CGImage);  // mask by alpha values of original image CGContextSetBlendMode(context, kCGBlendModeDestinationIn); CGContextDrawImage(context, rect, myIconImage.CGImage); 

If you don't care for luminosity, as you just have got an image with an alpha channel that should be tinted with a color, you can do it in a more efficient way:

// draw tint color CGContextSetBlendMode(context, kCGBlendModeNormal); [tintColor setFill]; CGContextFillRect(context, rect);  // mask by alpha values of original image CGContextSetBlendMode(context, kCGBlendModeDestinationIn); CGContextDrawImage(context, rect, myIconImage.CGImage); 

or the other way around:

// draw alpha-mask CGContextSetBlendMode(context, kCGBlendModeNormal); CGContextDrawImage(context, rect, myIconImage.CGImage);  // draw tint color, preserving alpha values of original image CGContextSetBlendMode(context, kCGBlendModeSourceIn); [tintColor setFill]; CGContextFillRect(context, rect); 

Have fun!

like image 176
fabb Avatar answered Sep 30 '22 14:09

fabb