如何在日志中比较2个UIColor对象,分别是kCGColorSpaceModelRGB和UIExtendedSRGBColorSpace实例?

弗拉德·阿列克谢夫(Vlad Alexeev)

现在我真的很困惑。继承人如何实例化变量:

Utils.redColor = UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue)/255.0, alpha: alpha) 

在这里,我列举了Attribute文本的属性,如果它等于Utils.redColor,则跳过颜色:

    text.enumerateAttributes(in: NSRange(0..<text.length), options: []) { (attributes, range, _) -> Void in
                            for (attribute, object) in attributes {
                                if let textColor = object as? UIColor{
                                     NSLog("textColor = \(textColor) red = \(Utils.redColor!)") 
             if (!textColor.isEqual(Utils.redColor!)){
//I need to repaint any textColor other than red
             text.setAttributes(textAttributes , range: range)
            }
          }

因此,如您在此代码中看到的那样,textColor也是一个UIColor对象,但是日志显示:

textColor = kCGColorSpaceModelRGB 0.666667 0.172549 0.172549 1 red = UIExtendedSRGBColorSpace 0.666667 0.172549 0.172549 1

这是两种确切的颜色,但是是两个不同类的实例。这两个UIColor类的对象完全令人困惑!

尽管此比较在Swift2中运行良好,但从未触发过

我该如何解决?为什么会出现此问题?

rick

欢迎来到宽阔的色彩和色彩管理的狂野和毛茸茸的世界。

您的两种颜色是不相等的isEqual(或者是Swift ==isEqual对于拥有它的ObjC类来说这是贯穿始终的),因为它们具有不同的颜色空间。(它们不是不同的类;其中的第一项UIColor.description是颜色空间的标识符,或者在颜色空间没有名称的地方,颜色空间的模型,也就是说,是否基于RGB,CMYK-基于,灰度等)

如果没有颜色空间将它们定义为颜色,那么颜色的四个分量值就没有可靠的含义,因此要同时isEqual使用分量值和颜色空间来测试是否相等。

除了色彩空间(向下跳过解决方案)

UIColor init(red:green:blue:alpha:)使用创建的颜色使用“扩展的sRGB”颜色空间。此色彩空间旨在支持宽广的彩色显示器(例如iPhone 7,iPad Pro 9.7英寸,iMac(2015年末),MacBook Pro(2016年末)以及可能推出的其他产品)中的P3彩色显示器,但必须兼容组件值以及在其他设备上使用的sRGB色彩空间。

例如,sRGB1.0, 0.0, 0.0是您最常使用的“红色” ...但是,如果您在P3颜色空间中使用RGB值创建颜色,则1.0, 0.0, 0.0您会变得更红。如果您有需要同时支持sRGB和P3显示器并直接使用颜色组件的应用程序,这可能会造成混淆。所以扩展sRGB空间让相同的元件值意味着同样的事情,但也允许使用指定的sRGB色域之外的色彩外值0.0-1.0范围例如,Display P3可以得到的最红色表示为Extended sRGB(大致)1.093, -0.227, -0.15

如[该初始化程序的文档说明,对于与iOS 10或更高版本SDK链接的应用程序,init(red:green:blue:alpha:)它在Extended sRGB颜色空间中创建颜色,但是对于较旧的应用程序(即使它们在iOS 10上运行),它会在设备特定的RGB空间(通常可以将其等同于sRGB)。

处理不同的色彩空间

因此,您的颜色替换代码或在属性字符串中创建颜色的任何代码都需要注意颜色空间。有几种可能的方法可以解决这个问题。选择最适合您的一种:

  1. 确保您的字符串创建代码和颜色替换代码都使用相同的设备无关颜色空间。UIColor没有提供用于处理色彩空间的大量实用程序,因此您可以使用Display P3(在iOS 10及更高版本上),或下拉至CGColor

    let sRGB = CGColorSpace(name: CGColorSpace.sRGB)!
    let cgDarkRed = CGColor(colorSpace: sRGB, components: [0.666667, 0.172549, 0.172549, 1])!
    let darkRed = UIColor(cgColor: cgDarkRed)
    
    // example creating attributed string...
    let attrString = NSAttributedString(string: "red", attributes: [NSForegroundColorAttributeName : darkRed])
    
    // example processing text...
    let redAttributes = [NSForegroundColorAttributeName: darkRed]
    text.enumerateAttributes(in: NSRange(0..<attrString.length)) { (attributes, range, stop) in
        for (_, textColor) in attributes where (textColor as? UIColor) != darkRed {
            text.setAttributes(redAttributes , range: range)
        }
    }
    
  2. 如果无法控制输入颜色,则在比较之前将它们转换为相同的颜色空间。这是UIColor执行此操作的扩展:

    extension UIColor {
        func isEqualWithConversion(_ color: UIColor) -> Bool {
            guard let space = self.cgColor.colorSpace
                else { return false }
            guard let converted = color.cgColor.converted(to: space, intent: .absoluteColorimetric, options: nil)
                else { return false }
            return self.cgColor == converted
        }
    }
    

    (然后,您可以仅使用此功能来代替文本处理==isEqual在其中进行文本处理。)

  3. 基于您知道两种颜色的色彩空间兼容的假设,只需获取颜色的原始成分值并直接进行比较即可。有点脆弱,所以我建议不要使用此选项。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章