How to use a UIImage as a mask over a color in Objective-C

前端 未结 4 2052
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-25 15:19

I have a UIImage that is all black with an alpha channel so some parts are grayish and some parts are completely see-through. I want to use that images as a mask over some o

相关标签:
4条回答
  • In iOS 7+ you should use UIImageRenderingModeAlwaysTemplate instead. See https://stackoverflow.com/a/26965557/870313


    Creating arbitrarily-colored icons from a black-with-alpha master image (iOS).

    // Usage: UIImage *buttonImage = [UIImage ipMaskedImageNamed:@"UIButtonBarAction.png" color:[UIColor redColor]];
    
    + (UIImage *)ipMaskedImageNamed:(NSString *)name color:(UIColor *)color
    {
        UIImage *image = [UIImage imageNamed:name];
        CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale);
        CGContextRef c = UIGraphicsGetCurrentContext();
        [image drawInRect:rect];
        CGContextSetFillColorWithColor(c, [color CGColor]);
        CGContextSetBlendMode(c, kCGBlendModeSourceAtop);
        CGContextFillRect(c, rect);
        UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return result;
    }
    

    Credits to Ole Zorn: https://gist.github.com/1102091

    0 讨论(0)
  • I converted this for OSX here as a Category and copied below. Note this is for non-ARC projects. For ARC projects, the autorelease can be removed.

    - (NSImage *)cdsMaskedWithColor:(NSColor *)color
    {
        CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    
        NSImage *result = [[NSImage alloc] initWithSize:self.size];
        [result lockFocusFlipped:self.isFlipped];
    
        NSGraphicsContext *context = [NSGraphicsContext currentContext];
        CGContextRef c = (CGContextRef)[context graphicsPort];
    
        [self drawInRect:NSRectFromCGRect(rect)];
    
        CGContextSetFillColorWithColor(c, [color CGColor]);
        CGContextSetBlendMode(c, kCGBlendModeSourceAtop);
        CGContextFillRect(c, rect);
    
        [result unlockFocus];
    
        return [result autorelease];
    }
    + (NSImage *)cdsMaskedImageNamed:(NSString *)name color:(NSColor *)color
    {
        NSImage *image = [NSImage imageNamed:name];
        return [image cdsMaskedWithColor:color];
    }
    
    0 讨论(0)
  • Here's a variation in Swift 3, written as an extension to UIImage:

    extension UIImage {
        func tinted(color:UIColor) -> UIImage? {
            let image = self
            let rect:CGRect = CGRect(origin: CGPoint(x: 0, y: 0), size: image.size)
            UIGraphicsBeginImageContextWithOptions(rect.size, false, image.scale)
            let context = UIGraphicsGetCurrentContext()!
            image.draw(in: rect)
            context.setFillColor(color.cgColor)
            context.setBlendMode(.sourceAtop)
            context.fill(rect)
            if let result:UIImage = UIGraphicsGetImageFromCurrentImageContext() {
                UIGraphicsEndImageContext()
                return result
            }
            else {
                return nil
            }
        }
    }
    
    // Usage
    let myImage = #imageLiteral(resourceName: "Check.png") // any image
    let blueImage = myImage.tinted(color: .blue)
    
    0 讨论(0)
  • 2020-12-25 16:02

    Translating Jano's answer into Swift:

    func ipMaskedImageNamed(name:String, color:UIColor) -> UIImage {
        let image = UIImage(named: name)
        let rect:CGRect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: image!.size.width, height: image!.size.height))
        UIGraphicsBeginImageContextWithOptions(rect.size, false, image!.scale)
        let c:CGContextRef = UIGraphicsGetCurrentContext()
        image?.drawInRect(rect)
        CGContextSetFillColorWithColor(c, color.CGColor)
        CGContextSetBlendMode(c, kCGBlendModeSourceAtop)
        CGContextFillRect(c, rect)
        let result:UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result
    }
    

    Usage:

    myButton.setImage(ipMaskedImageNamed("grayScalePNG", color: UIColor.redColor()), forState: .Normal)
    

    Edit: According to this article, you can turn an image into a mask whose opaque areas are represented by the tint color. Within the asset catalog, under the Attributes Inspector of the image, change Render As to Template Image. No code necessary.

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