【问题标题】:How to use a UIImage as a mask over a color in Objective-C如何在 Objective-C 中使用 UIImage 作为颜色遮罩
【发布时间】:2011-07-25 23:07:39
【问题描述】:

我有一个全黑的带有 alpha 通道的 UIImage,所以有些部分是灰色的,有些部分是完全透明的。我想将这些图像用作其他颜色的遮罩(假设为白色以方便使用),因此最终产品现在是白色图像,其中部分是透明的。

我一直在 Apple 文档网站上四处寻找: http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBHIJEB

但我对 Quartz/Core Graphics 完全陌生,所以我无法真正理解这些示例。

有人知道我可以用来查看的一些完整代码示例的链接吗?

【问题讨论】:

    标签: objective-c core-graphics quartz-2d


    【解决方案1】:

    在 iOS 7+ 中,您应该改用 UIImageRenderingModeAlwaysTemplate。见https://*.com/a/26965557/870313


    从带有 alpha 的黑色主图像 (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;
    }
    

    感谢 Ole Zorn:https://gist.github.com/1102091

    【讨论】:

    • 太棒了!非常感谢!
    • 值得注意。如果您使用 UIImageView 显示图像,这里有一个简单的解决方案。 *.com/a/26965557/870313
    【解决方案2】:

    将 Jano 的答案翻译成 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
    }
    

    用法:

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

    编辑:根据article,您可以将图像转换为遮罩,其不透明区域由色调颜色表示。在资产目录中,在图像的 Attributes Inspector 下,将 Render As 更改为 Template Image。无需代码。

    【讨论】:

    • 资产目录解决方案如今似乎是真正的解决方案。效果很好。
    【解决方案3】:

    这是 Swift 3 中的一个变体,作为 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】:

      我将它转换为 OSX here 的类别并复制到下面。请注意,这适用于非 ARC 项目。对于 ARC 项目,可以删除自动释放。

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

      【讨论】:

        最近更新 更多