Changing UIImage color

前端 未结 13 1362
我寻月下人不归
我寻月下人不归 2020-11-28 19:28

I\'m trying to change color of UIImage. My code:

-(UIImage *)coloredImage:(UIImage *)firstImage withColor:(UIColor *)color {
    UIGraphicsBeginImageContext(         


        
相关标签:
13条回答
  • 2020-11-28 19:47

    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
        }
    }
    
    0 讨论(0)
  • 2020-11-28 19:48

    Here's my adaptation of @Anna's answer. Two key points here:

    • Use destinationIn blending mode
    • Call UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale) to get smooth image

    Code in in 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!
        }
    }
    
    0 讨论(0)
  • 2020-11-28 19:49

    Starting from iOS 10 you can use 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)
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-28 19:49

    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.

    0 讨论(0)
  • 2020-11-28 19:49

    For iOS 13 and newer:

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

    0 讨论(0)
  • 2020-11-28 19:54

    In Swift 3.0

    imageView.image? = (imageView.image?.withRenderingMode(.alwaysTemplate))!
    imageView.tintColor = UIColor.magenta
    

    In Swift 2.0

    yourImage.image? = (yourImage.image?.imageWithRenderingMode(.AlwaysTemplate))!
    yourImage.tintColor = UIColor.magentaColor()
    

    Enjoy you Swift pioneers

    0 讨论(0)
提交回复
热议问题