ios 更改 UIImage 颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12872680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing UIImage color
提问by RomanHouse
I'm trying to change color of UIImage. My code:
我正在尝试更改 UIImage 的颜色。我的代码:
-(UIImage *)coloredImage:(UIImage *)firstImage withColor:(UIColor *)color {
UIGraphicsBeginImageContext(firstImage.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[color setFill];
CGContextTranslateCTM(context, 0, firstImage.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGRect rect = CGRectMake(0, 0, firstImage.size.width, firstImage.size.height);
CGContextDrawImage(context, rect, firstImage.CGImage);
CGContextClipToMask(context, rect, firstImage.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathElementMoveToPoint);
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return coloredImg;
}
This code works, but obtained image is not so well as shoud be: bounds pixels of returned image are intermittent and not so smooth as in my first image. How can I resolve this problem?
这段代码有效,但获得的图像并不像应该的那么好:返回图像的边界像素是断断续续的,不像我的第一张图像那样平滑。我该如何解决这个问题?
回答by Ankish Jain
Since iOS 7, this is the most simple way of doing it.
从 iOS 7 开始,这是最简单的方法。
Objective-C:
目标-C:
theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
Swift 2.0:
斯威夫特 2.0:
theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate)
theImageView.tintColor = UIColor.magentaColor()
Swift 4.0:
斯威夫特 4.0:
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)
theImageView.tintColor = .magenta
Storyboard:
故事板:
First configure the image as template ( on right bar - Render as) in your assets. Then the color of the image would be the tint color applied.
回答by user1270061
This is pretty much the answer above, but slightly shortened. This only takes the image as a mask and does not actually "multiply" or color the image.
这几乎是上面的答案,但略有缩短。这仅将图像作为蒙版,实际上并不“相乘”或为图像着色。
Objective C:
目标 C:
UIColor *color = <# UIColor #>;
UIImage *image = <# UIImage #>;// Image to mask with
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
[color setFill];
CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, CGRectMake(0, 0, image.size.width, image.size.height), [image CGImage]);
CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height));
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Swift:
迅速:
let color: UIColor = <# UIColor #>
let image: UIImage = <# UIImage #> // Image to mask with
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
let context = UIGraphicsGetCurrentContext()
color.setFill()
context?.translateBy(x: 0, y: image.size.height)
context?.scaleBy(x: 1.0, y: -1.0)
context?.clip(to: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height), mask: image.cgImage!)
context?.fill(CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
回答by Anna Dickinson
Another way to tint an image is to simply multiply it by a constant color. Sometimes, this is preferable because it doesn't "lift" the color values in black areas; it keeps the relative intensities in the image the same. Using an overlay as a tint tends to flatten out the contrast.
给图像着色的另一种方法是简单地将其乘以恒定颜色。有时,这更可取,因为它不会“提升”黑色区域的颜色值;它使图像中的相对强度保持不变。使用叠加作为色调往往会使对比度变平。
This is the code I use:
这是我使用的代码:
UIImage *MultiplyImageByConstantColor( UIImage *image, UIColor *color ) {
CGSize backgroundSize = image.size;
UIGraphicsBeginImageContext(backgroundSize);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect backgroundRect;
backgroundRect.size = backgroundSize;
backgroundRect.origin.x = 0;
backgroundRect.origin.y = 0;
CGFloat r,g,b,a;
[color getRed:&r green:&g blue:&b alpha:&a];
CGContextSetRGBFillColor(ctx, r, g, b, a);
CGContextFillRect(ctx, backgroundRect);
CGRect imageRect;
imageRect.size = image.size;
imageRect.origin.x = (backgroundSize.width - image.size.width)/2;
imageRect.origin.y = (backgroundSize.height - image.size.height)/2;
// Unflip the image
CGContextTranslateCTM(ctx, 0, backgroundSize.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
CGContextDrawImage(ctx, imageRect, image.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Swift version
迅捷版
extension UIImage{
static func multiplyImageByConstantColor(image:UIImage,color:UIColor)->UIImage{
let backgroundSize = image.size
UIGraphicsBeginImageContext(backgroundSize)
let ctx = UIGraphicsGetCurrentContext()
var backgroundRect=CGRect()
backgroundRect.size = backgroundSize
backgroundRect.origin.x = 0
backgroundRect.origin.y = 0
var r:CGFloat
var g:CGFloat
var b:CGFloat
var a:CGFloat
color.getRed(&r, green: &g, blue: &b, alpha: &a)
CGContextSetRGBFillColor(ctx, r, g, b, a)
CGContextFillRect(ctx, backgroundRect)
var imageRect=CGRect()
imageRect.size = image.size
imageRect.origin.x = (backgroundSize.width - image.size.width)/2
imageRect.origin.y = (backgroundSize.height - image.size.height)/2
// Unflip the image
CGContextTranslateCTM(ctx, 0, backgroundSize.height)
CGContextScaleCTM(ctx, 1.0, -1.0)
CGContextSetBlendMode(ctx, .Multiply)
CGContextDrawImage(ctx, imageRect, image.CGImage)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
回答by ColossalChris
In Swift 3.0
在 Swift 3.0 中
imageView.image? = (imageView.image?.withRenderingMode(.alwaysTemplate))!
imageView.tintColor = UIColor.magenta
In Swift 2.0
在 Swift 2.0 中
yourImage.image? = (yourImage.image?.imageWithRenderingMode(.AlwaysTemplate))!
yourImage.tintColor = UIColor.magentaColor()
Enjoy you Swift pioneers
享受你的 Swift 先驱
回答by Charlton Provatas
Swift 4.2 Solution
Swift 4.2 解决方案
extension UIImage {
func withColor(_ color: UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return self }
color.setFill()
ctx.translateBy(x: 0, y: size.height)
ctx.scaleBy(x: 1.0, y: -1.0)
ctx.clip(to: CGRect(x: 0, y: 0, width: size.width, height: size.height), mask: cgImage)
ctx.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
guard let colored = UIGraphicsGetImageFromCurrentImageContext() else { return self }
UIGraphicsEndImageContext()
return colored
}
}
// Usage:
// let redImage = UIImage().withColor(.red)
回答by Murlakatam
Starting from iOS 10you can use UIGraphicsImageRenderer
:
从iOS 10开始,您可以使用UIGraphicsImageRenderer
:
extension UIImage {
func colored(_ color: UIColor) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { context in
color.setFill()
self.draw(at: .zero)
context.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height), blendMode: .sourceAtop)
}
}
}
回答by Mario A Guzman
If you don't have to do it programmatically, you can just do it using Xcode UI.
如果您不必以编程方式执行此操作,则只需使用 Xcode UI 即可。
If you go to the image in your image assets folder, open the inspector on the right hand side and there is a "Render As" dropdown with the following options:
如果您转到图像资产文件夹中的图像,请打开右侧的检查器,然后会出现一个“渲染为”下拉菜单,其中包含以下选项:
- Default
- Original
- Template
- 默认
- 原来的
- 模板
Once you've made the Template selection, you can change the tintColor of the image however you want - whether it is using the Xcode storyboard UI or programmatically.
完成模板选择后,您可以根据需要更改图像的 tintColor - 无论是使用 Xcode 故事板 UI 还是以编程方式。
See this image:
看这张图片:
回答by algrid
Here's my adaptation of @Anna's answer. Two key points here:
这是我对@Anna 回答的改编。这里有两个关键点:
- Use
destinationIn
blending mode - Call
UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)
to get smooth image
- 使用
destinationIn
混合模式 - 调用
UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)
以获得平滑的图像
Code in in Swift 3:
Swift 3 中的代码:
extension UIImage {
static func coloredImage(image: UIImage?, color: UIColor) -> UIImage? {
guard let image = image else {
return nil
}
let backgroundSize = image.size
UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)
let ctx = UIGraphicsGetCurrentContext()!
var backgroundRect=CGRect()
backgroundRect.size = backgroundSize
backgroundRect.origin.x = 0
backgroundRect.origin.y = 0
var r:CGFloat = 0
var g:CGFloat = 0
var b:CGFloat = 0
var a:CGFloat = 0
color.getRed(&r, green: &g, blue: &b, alpha: &a)
ctx.setFillColor(red: r, green: g, blue: b, alpha: a)
ctx.fill(backgroundRect)
var imageRect = CGRect()
imageRect.size = image.size
imageRect.origin.x = (backgroundSize.width - image.size.width) / 2
imageRect.origin.y = (backgroundSize.height - image.size.height) / 2
// Unflip the image
ctx.translateBy(x: 0, y: backgroundSize.height)
ctx.scaleBy(x: 1.0, y: -1.0)
ctx.setBlendMode(.destinationIn)
ctx.draw(image.cgImage!, in: imageRect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
回答by Bill Chan
Base on @Anna's answer and I rewrite for swift 2.2 and handles image with alpha channel:
基于@Anna 的回答,我重写了 swift 2.2 并使用 alpha 通道处理图像:
static func multiplyImageByConstantColor(image:UIImage,color:UIColor)->UIImage{
let backgroundSize = image.size
UIGraphicsBeginImageContext(backgroundSize)
let ctx = UIGraphicsGetCurrentContext()
var backgroundRect=CGRect()
backgroundRect.size = backgroundSize
backgroundRect.origin.x = 0
backgroundRect.origin.y = 0
var r:CGFloat = 0
var g:CGFloat = 0
var b:CGFloat = 0
var a:CGFloat = 0
color.getRed(&r, green: &g, blue: &b, alpha: &a)
CGContextSetRGBFillColor(ctx, r, g, b, a)
// Unflip the image
CGContextTranslateCTM(ctx, 0, backgroundSize.height)
CGContextScaleCTM(ctx, 1.0, -1.0)
CGContextClipToMask(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
CGContextFillRect(ctx, backgroundRect)
var imageRect=CGRect()
imageRect.size = image.size
imageRect.origin.x = (backgroundSize.width - image.size.width)/2
imageRect.origin.y = (backgroundSize.height - image.size.height)/2
CGContextSetBlendMode(ctx, .Multiply)
CGContextDrawImage(ctx, imageRect, image.CGImage)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
回答by Lowell Bahner
Anna's code works well for copying a UIImage.image over a colored .image background by using kCGBlendModeNormal rather than kCGBlendModeMultiply. For instance, self.mainImage.image = [self NormalImageByConstantColor: self.mainImage.image withColor: yourColor];
will place the contents of mainImage.image over the tint yourColor while preserving the opacity of yourColor. This solved my problem of placing a background color with opacity behind an image to be saved to the Camera Roll.
Anna 的代码适用于通过使用 kCGBlendModeNormal 而不是 kCGBlendModeMultiply 在彩色 .image 背景上复制 UIImage.image。例如,self.mainImage.image = [self NormalImageByConstantColor: self.mainImage.image withColor: yourColor];
将 mainImage.image 的内容放置在色调 yourColor 上,同时保留 yourColor 的不透明度。这解决了我在要保存到相机胶卷的图像后面放置不透明背景颜色的问题。