我已经成功地使用以下函数将XIC 7.2中的Swift 2代码转换为CMICK值。但是,返回的值类似于基于公式的转换:
func RGBtoCMYK(rgbColor: UIColor) -> (c: CGFloat, m: CGFloat, y: CGFloat, k: CGFloat) {
/*
let iccFileName = "CoatedGRACoL2006"
let iccProfile: CFDataRef = CGDataProviderCreateWithFilename(iccFileName) as! CFDataRef
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateWithICCProfile(iccProfile)!
*/
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceCMYK()!
let intent = CGColorRenderingIntent.RenderingIntentPerceptual
let cmykColor = CGColorCreateCopyByMatchingToColorSpace(colorSpace, intent, rgbColor.CGColor, nil)
let c: CGFloat = round(CGColorGetComponents(cmykColor)[0] * 100)
let m: CGFloat = round(CGColorGetComponents(cmykColor)[1] * 100)
let y: CGFloat = round(CGColorGetComponents(cmykColor)[2] * 100)
let k: CGFloat = round(CGColorGetComponents(cmykColor)[3] * 100)
return (c, m, y, k)
}
相反,我想使用ICC配置文件。在注释区域中,我尝试将ColorSpace从CGCreateDeviceCMYK()更改为CGCreateWithICCProfile(),它正在寻找NSData输入。我从Adobe下载了标准的CMYK ICC配置文件并拖动了#34; CoatedGRACoL2006.icc"进入我的Asset.xcassets项目文件夹。代码已编译但在运行应用程序时生成了一长串错误。关于如何将ColorSpace更改为基于ICC配置文件的颜色空间,任何输入,注释或建议都将受到赞赏。
答案 0 :(得分:4)
您可以使用NSData
从捆绑包中加载个人资料的数据。
NSData
和CFData
是免费桥接的,因此只要API需要NSData
个实例,就可以使用CFData
实例。
我将您的颜色转换方法移到了扩展程序中:
extension UIColor {
func colorComponentsByMatchingToColorSpace(colorSpace: CGColorSpace) -> (c: CGFloat, m: CGFloat, y: CGFloat, k: CGFloat) {
let intent = CGColorRenderingIntent.RenderingIntentPerceptual
let cmykColor = CGColorCreateCopyByMatchingToColorSpace(colorSpace, intent, self.CGColor, nil)
let c: CGFloat = round(CGColorGetComponents(cmykColor)[0] * 100)
let m: CGFloat = round(CGColorGetComponents(cmykColor)[1] * 100)
let y: CGFloat = round(CGColorGetComponents(cmykColor)[2] * 100)
let k: CGFloat = round(CGColorGetComponents(cmykColor)[3] * 100)
return (c, m, y, k)
}
}
要从捆绑包加载.icc文件并调用扩展方法,您可以使用以下命令:
guard let iccProfileURL = NSBundle.mainBundle().resourceURL?.URLByAppendingPathComponent("CoatedGRACoL2006.icc") else {
return;
}
guard let iccProfileData = NSData(contentsOfURL: iccProfileURL) else {
return;
}
guard let colorSpace = CGColorSpaceCreateWithICCProfile(iccProfileData) else {
return;
}
let components = UIColor.redColor().colorComponentsByMatchingToColorSpace(colorSpace);
print("\(components)")
请注意,上面的内容会从您的捆绑资源中加载配置文件,而不是从资产目录中加载。 (因此,您必须确保在"复制捆绑资源"构建阶段)中将.icc文件复制到捆绑包中。 如果您想使用资产目录并且目标是iOS 9.0或更高版本,则可以查看NSDataAsset。
答案 1 :(得分:1)
我发现CFDataRef
有些令人困惑,但我看了CGDataProvider works the first time, returns an empty image the second time,这有一个额外的步骤。我试过这段代码:
guard let iccPath = NSBundle.mainBundle().pathForResource("CoatedGRACoL2006", ofType: "icc") else { print("bad file"); return (0,0,0,0) }
guard let iccProfile = CGDataProviderCreateWithFilename(iccPath) else { print("bad profile"); return (0,0,0,0); }
let iccCFDataRef = CGDataProviderCopyData(iccProfile) // extra step
guard let colorSpace = CGColorSpaceCreateWithICCProfile(iccCFDataRef) else { print ("bad colorSpace"); return (0,0,0,0); }
let intent = CGColorRenderingIntent.RenderingIntentPerceptual
guard let cmykColor = CGColorCreateCopyByMatchingToColorSpace(colorSpace, intent, rgbColor.CGColor, nil) else { print("Bad color"); return (0,0,0,0) }
并且 创建了一个没有任何错误的cmyk颜色。但是,在生成要返回的CMYK组件时,我发现它们与您在没有icc配置文件的情况下生成的组件完全相同。 然而然而,我试过
print("Recovered profile: \(CGColorSpaceCopyICCProfile(colorSpace))")
并且确实提供了个人资料,所以为什么数字没有改变,我不知道。这可能是一个不同的问题。
如果你能够在这方面取得进展,我认为你应该注意这些非托管CFthings的内存管理。我上面创建的副本必须发布;我没有写那段代码。祝你好运!
答案 2 :(得分:0)
@ thomash-zoechling的答案已针对Swift 5:
extension UIColor {
func colorComponentsByMatchingToColorSpace(colorSpace: CGColorSpace) -> (c: CGFloat, m: CGFloat, y: CGFloat, k: CGFloat) {
let intent = CGColorRenderingIntent.perceptual
guard let cmykColor = self.cgColor.converted(to: colorSpace, intent: intent, options: nil) else { fatalError("Couldn't convert color to CMYK.") }
let c: CGFloat = (cmykColor.components?[0] ?? 0) * 100
let m: CGFloat = (cmykColor.components?[1] ?? 0) * 100
let y: CGFloat = (cmykColor.components?[2] ?? 0) * 100
let k: CGFloat = (cmykColor.components?[3] ?? 0) * 100
return (c,m,y,k)
}
}
并加载icc配置文件:
guard let profileURL = Bundle.main.url(forResource: "filname", withExtension: "icc") else { return }
guard let data = try? Data(contentsOf: profileURL) else { return }
guard let colorspace = CGColorSpace(iccProfileData: data as CFData) else { return }