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

99封情书 提交于 2019-12-18 11:07:08

问题


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 other color (let's say white to make it easy), so the final product is now a white image with parts of it transparent.

I've been looking around on the Apple documentation site here: http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBHIJEB

But I'm completely new to Quartz/Core Graphics, so I don't can't really make sense of those examples.

Does anyone know of a link to some full code samples that I could use to look at?


回答1:


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




回答2:


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.




回答3:


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)



回答4:


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


来源:https://stackoverflow.com/questions/6823493/how-to-use-a-uiimage-as-a-mask-over-a-color-in-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!