2016-02-28 208 views
1

我已經成功地在Xcode 7.2中使用Swift 2代碼將UIColor轉換爲CMYK值。但是,返回值類似於基於公式的轉換:Swift:使用ICC配置文件將RGB(UIColor)轉換爲CMYK

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()更改爲尋找NSData輸入的CGCreateWithICCProfile()。我從Adobe下載了標準CMYK ICC配置文件,並將「CoatedGRACoL2006.icc」拖入我的Asset.xcassets項目文件夾中。編譯代碼,但運行應用程序時會生成一長串錯誤。關於如何將ColorSpace更改爲基於ICC Profile的色彩空間,我們將不勝感激任何輸入,評論或建議。

+0

謝謝emrys57和@weichsel。我能夠重現您的解決方案,以便使用colorSpace的ICC配置文件。有趣的是,在測試了多個ICC配置文件和CGColorRenderingIntent後,我得到了與我的初始colorSpace和intent相同的結果值。現在我想知道CGColorCreateCopyByMatchingToColorSpace方法是否按預期工作。如果任何人有其他建議將UIColors轉換爲CMYK值 - 請發佈! – Prepress

回答

3

您可以使用NSData從您的包中加載配置文件的數據。 NSDataCFData免費橋接,因此只要API需要CFData便可以使用NSData實例。

我搬到你的顏色轉換方法爲擴展名:

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)") 

注意以上內容將從您的捆綁資源中加載配置文件,而不是從資產目錄中加載。 (所以你必須確保在「Copy Bundle Resources」構建階段期間將.icc文件複製到你的包中)。 如果您想使用資產目錄,並且您的目標是iOS 9.0或更高版本,則可以查看NSDataAsset

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的內存管理。我上面創建的副本必須發佈;我沒有寫這個代碼。祝你好運!