在iOS swift中通过十六进制颜色将显示P3转换为eSRGB?

zqdjd7g9  于 2022-12-01  发布在  iOS
关注(0)|答案(2)|浏览(109)

我正在使用UIColorPickerViewController。当我使用Sliders节时,默认值是显示p3,如在图像下方。

我的应用使用的是UIExtendedSRGBColorSpace。因此我需要转换为UIExtendedSRGBColorSpace。当我从显示P3转换为eSRGB时,它返回UIExtendedSRGBColorSpace -0.511642 1.01827 -0.310624 1
转换器代码在这里。

extension CGColorSpace {
static let extendedSRGB = CGColorSpace(name: CGColorSpace.extendedSRGB)! }

func updateFromP3ToExtendedsRGB() -> UIColor?
    {
        guard self.cgColor.colorSpace?.name == CGColorSpace.displayP3 else { return nil }
        let convertColor = self.cgColor.converted(to: .extendedSRGB, intent: .relativeColorimetric, options: nil)
        if let convertCGColor = convertColor
        {
            return UIColor(cgColor: convertCGColor)
        }
        
        return nil
    }

我得到了负值。问题是。
我需要保存颜色与十六进制代码。当我改变为十六进制代码的转换颜色,它变成不同的颜色,如黄色ffffffb1

下面是转换十六进制代码的代码。

func toHexString() -> String {
        var r:CGFloat = 0
        var g:CGFloat = 0
        var b:CGFloat = 0
        var a:CGFloat = 0

        getRed(&r, green: &g, blue: &b, alpha: &a)
        let argb:Int = (Int)(a*255)<<24 | (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0
        return NSString(format:"%06x", argb) as String
    }

那么,我的问题是如何通过十六进制字符串将显示p3转换为eSRGB?

inb24sb2

inb24sb21#

如果从UIColor转换,则十六进制值始终为sRGB颜色空间您应该从CGColor. Apple UIColor转换

extension CGColor {
    func toHex() -> String? {
        guard let components = components else { return nil }
        
        if components.count == 2 {
            let value = components[0]
            let alpha = components[1]
            return String(format: "#%02lX%02lX%02lX%02lX", lroundf(Float(alpha*255)), lroundf(Float(value*255)), lroundf(Float(value*255)), lroundf(Float(value*255)))
        }
        
        guard components.count == 4 else { return nil }
        
        let red   = components[0]
        let green = components[1]
        let blue  = components[2]
        let alpa  = components[3]
        
        let hexString = String(format: "#%02lX%02lX%02lX%02lX",lroundf(Float(alpa*255)), lroundf(Float(red*255)), lroundf(Float(green*255)), lroundf(Float(blue*255)))
        
        return hexString
    }
}

extension UIColor {
    func toHexString() -> String {
        cgColor.toHex() ?? ""
    }
    
    func toDisplayP3HexString() -> String {
        guard let displayP3Color = self.cgColor.converted(to: CGColorSpace(name: CGColorSpace.displayP3)!, intent: .defaultIntent, options: nil) else {
            return ""
        }
        return displayP3Color.toHex() ?? ""
    }
}
disbfnqx

disbfnqx2#

您发布的代码应该无法编译。CGColor converted的第一个参数必须是CGColorSpace。但是您传递的.extendedSRGB看起来像CGColorSpace.extendedSRGB,实际上是CFString,而不是CGColorSpace
当您的代码按如下方式更新时,它会给出看似正确的结果:

extension UIColor {
    func updateFromP3ToExtendedsRGB() -> UIColor? {
        guard self.cgColor.colorSpace?.name == CGColorSpace.displayP3 else { return nil }
        guard let eSRGBSpace = CGColorSpace(name: CGColorSpace.extendedSRGB) else { return nil }
        let convertColor = self.cgColor.converted(to: eSRGBSpace, intent: .relativeColorimetric, options: nil)
        if let convertCGColor = convertColor {
            return UIColor(cgColor: convertCGColor)
        }

        return nil
    }
}

如果P3颜色为75FB4C(117、251、76),则eSRGB颜色为03FF00。
真正奇怪的是,屏幕截图显示75FB4C为116(不是117)、251、76。但0x75是十进制的117,而不是116。将74FB4C转换为eSRGB会得到一个带负分量的奇怪值。因此,一位数的差异会产生巨大的差异。这似乎是由于颜色模型之间的舍入误差造成的。
如果你走另一条路,从00FF00的eSRGB开始,你会得到预期的75FB4C的P3颜色。
你的代码转换成十六进制基本上是好的。真正的问题是颜色转换给你一个无效的颜色与负分量。十六进制字符串代码是不是真的打算与负值工作。但颜色不应该有任何负分量。
在十六进制字符串函数中,你应该做的一件事是检查返回值go getRed:green:blue:alpha:,因为它在某些情况下可能会失败。

相关问题