且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在iPhone中为透明的PNG图像着色?

更新时间:2023-11-10 20:44:04

更新:这是使用以下代码的 Gist 获取Swift UIColor扩展程序。

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

如果您有灰度图像并希望白色成为着色颜色 kCGBlendModeMultiply 是要走的路。使用此方法,您不能使亮点比着色颜色更亮。

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.

相反,如果您有非灰度图像您应该保留突出显示阴影,混合模式 kCGBlendModeColor 是要走的路。白色将保持白色,黑色将保持黑色,因为图像的亮度保持不变。此模式仅用于着色 - 它与Photoshop的颜色图层混合模式相同(免责声明:可能会出现略有不同的结果)。

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).

请注意,无论是在iOS还是在Photoshop中,着色alpha像素都无法正常工作 - 半透明的黑色像素不会保持黑色。我更新了下面的答案来解决这个问题,花了很长时间才找到。

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.

你也可以使用其中一种混合模式 kCGBlendModeSourceIn / DestinationIn 而不是 CGContextClipToMask

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

如果你想创建一个 UIImage ,以下代码部分可以包含以下代码:

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();






所以这里是用透明图像着色的代码 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);

如果你的图像没有半透明像素,你也可以用另一种方式做到这一点 kCGBlendModeLuminosity

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);






如果你不关心光度,你只需要一个带有颜色的alpha通道的图像,你可以用更有效的方式做到这一点:


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);

或者相反:

// 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);

玩得开心!