Iphone 更改图像颜色

Iphone 更改图像颜色,iphone,objective-c,ios,uiimage,cgcontext,Iphone,Objective C,Ios,Uiimage,Cgcontext,我正在尝试更改图像的颜色。我的代码: -(UIImage *)coloredImage:(UIImage *)firstImage withColor:(UIColor *)color { UIGraphicsBeginImageContext(firstImage.size); CGContextRef context = UIGraphicsGetCurrentContext(); [color setFill]; CGContextTranslateCT

我正在尝试更改图像的颜色。我的代码:

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

这段代码可以工作,但获得的图像并不像应该的那个样好:返回图像的边界像素是间歇性的,不像我的第一幅图像那个样平滑。如何解决此问题?

另一种给图像着色的方法是简单地将其乘以恒定的颜色。有时,这是更好的,因为它不会“提升”黑色区域中的颜色值;它使图像中的相对强度保持不变。使用覆盖层作为色调往往会使对比度变平

这是我使用的代码:

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版本

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
    }
}

这与上面的答案基本相同,但略为缩短。这仅将图像作为遮罩,实际上不会“倍增”或对图像着色

目标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();
UIColor*color=;
UIImage*图像=;//要遮罩的图像
UIGraphicsBeginImageContextWithOptions(image.size、NO、image.scale);
CGContextRef context=UIGraphicsGetCurrentContext();
[颜色设置填充];
CGContextTranslateCm(上下文,0,image.size.height);
CGContextScaleCTM(上下文,1.0,-1.0);
CGContextClipToMask(上下文,CGRectMake(0,0,image.size.width,image.size.height),[image-CGImage]);
CGContextFillRect(上下文,CGRectMake(0,0,image.size.width,image.size.height));
UIImage*coloredImg=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsSendImageContext();
斯威夫特:

    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()
let color:UIColor=
let image:UIImage=//要使用其进行遮罩的图像
UIGraphicsBeginImageContextWithOptions(image.size、false、image.scale)
let context=UIGraphicsGetCurrentContext()
color.setFill()
上下文?.translateBy(x:0,y:image.size.height)
上下文?.scaleBy(x:1.0,y:-1.0)
context?.clip(到:CGRect(x:0,y:0,宽度:image.size.width,高度:image.size.height),掩码:image.cgImage!)
上下文?.fill(CGRect(x:0,y:0,宽度:image.size.width,高度:image.size.height))
让coloredImg=UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsSendImageContext()

自从iOS 7以来,这是最简单的方法

目标-C:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate) 
theImageView.tintColor = UIColor.magentaColor()
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate) 
theImageView.tintColor = .magenta
Swift 2.0:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate) 
theImageView.tintColor = UIColor.magentaColor()
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate) 
theImageView.tintColor = .magenta
Swift 4.0:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate) 
theImageView.tintColor = UIColor.magentaColor()
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate) 
theImageView.tintColor = .magenta
情节提要:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate) 
theImageView.tintColor = UIColor.magentaColor()
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate) 
theImageView.tintColor = .magenta
首先在资源中将图像配置为模板(在右侧栏上-渲染为)。然后图像的颜色将是应用的着色颜色。
在Swift 3.0中

imageView.image? = (imageView.image?.withRenderingMode(.alwaysTemplate))!
imageView.tintColor = UIColor.magenta
yourImage.image? = (yourImage.image?.imageWithRenderingMode(.AlwaysTemplate))!
yourImage.tintColor = UIColor.magentaColor()
在Swift 2.0中

imageView.image? = (imageView.image?.withRenderingMode(.alwaysTemplate))!
imageView.tintColor = UIColor.magenta
yourImage.image? = (yourImage.image?.imageWithRenderingMode(.AlwaysTemplate))!
yourImage.tintColor = UIColor.magentaColor()

祝你们Swift先锋们玩得愉快

基于@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
}

Anna的代码可以通过使用kCGBlendModeNormal而不是kCGBlendModeMultiply在彩色.image背景上复制UIImage.image。例如,
self.main image.image=[self-NormalImageByConstantColor:self.main image.image withColor:yourColor]
将mainImage.image的内容放置在着色yourColor上,同时保留yourColor的不透明度。这解决了我在图像后面放置不透明度背景色的问题,该图像将保存到相机卷中。

Swift 3.0版Anna的神奇代码:

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

        let myFloatForR = 0
        var r = CGFloat(myFloatForR)
        let myFloatForG = 0
        var g = CGFloat(myFloatForG)
        let myFloatForB = 0
        var b = CGFloat(myFloatForB)
        let myFloatForA = 0
        var a = CGFloat(myFloatForA)

        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(.multiply)
        ctx.draw(image.cgImage!, in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

如果您不必以编程方式进行,那么可以使用Xcode UI进行

如果转到“图像资源”文件夹中的图像,请打开右侧的检查器,此时会出现“渲染为”下拉列表,其中包含以下选项:

  • 违约
  • 原创的
  • 模板
  • 完成模板选择后,可以根据需要更改图像的颜色-无论是使用Xcode序列图像板UI还是以编程方式

    请参见此图:

    Swift 3:

    extension UIImage{
    
        static func multiplyImageByConstantColor(image:UIImage,color:UIColor) -> UIImage{
    
            let backgroundSize = image.size
            UIGraphicsBeginImageContext(backgroundSize)
    
            guard let ctx = UIGraphicsGetCurrentContext() else {return image}
    
            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)
    
            // Unflip the image
            ctx.translateBy(x: 0, y: backgroundSize.height)
            ctx.scaleBy(x: 1.0, y: -1.0)
            ctx.clip(to: CGRect(0, 0, image.size.width, image.size.height), mask: image.cgImage!)
            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
    
    
            ctx.setBlendMode(.multiply)
            ctx.draw(image.cgImage!, in: imageRect)
    
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return newImage!
        }
    }
    

    以下是我对@Anna答案的改编。这里有两个关键点:

    • 在混合模式下使用
      destinationIn
    • 调用
      UIGraphicsBeginImageContextWithOptions(backgroundSize,false,UIScreen.main.scale)
      以获得平滑图像
    在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!
        }
    }
    

    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)
    

    从iOS 10开始,您可以使用UIGraphicsSimageRenderer:

    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)
            }
        }
    
    }
    
    对于iOS 13及更新版本:


    让redImage=image.withTintColor(.red,renderingMode:.alwaysTemplate)

    您应该使用
    UIGraphicsBeginImageContextWithOptions(image.size,NO,image.scale)因为您的版本只会创建非视网膜图形。根据我的经验,user1270061就是这样做的。“燃烧”的另一个答案显然需要特定颜色的源图像。这一个只使用源像素中的alpha值,并将其与所需的颜色相结合-完美。完美-唯一的答案对我来说很好。(5月16日)这正是我想要的解决方案!谢谢如果我想制作一个虚拟的壁画应用程序呢?这是可行的,如果你只想给图像中的墙壁上色怎么办。请查看此链接:-这比其他一些解决方案效果好得多。这对我来说只着色了对象背景,而不是对象本身。可能重复“UIImageRenderingModeAlwaysTemplate:始终将图像绘制为模板图像,忽略其颜色信息。”很好!在Swift 2.0+
    theImageView.image?=(图像视图.image?.imageWithRenderingMode(.AlwaysTemplate))!theImageView.tintColor=UIColor.PigentaColor()
    @AnkishJain此方法是否存在任何性能问题?这不会更改图像的颜色,而是指示视图以不同的色调(颜色)渲染图像。@Womble不太可能。您可以将其用于任何UIImage<代码>img=[img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];[按钮setTintColor:[UIColor REDCLOR]];[按钮设置图像:img for状态:uicontrol状态正常]@Ankish谢谢!您正在使用XCODE 8吗?为什么在扩展UIImage时要传递映像?您应该删除方法的static关键字,只需在内部使用
    self