我正在實施類似於ios中的photoshop魔棒工具的顏色選擇工具。在實驗室顏色空間中創建像素緩衝區
我已經得到它在RGB中的工作,但爲了使它更加準確我想使它在LAB色彩空間中工作。
它目前的工作方式是它需要一個UIImage,創建該圖像的CGImage版本。然後它在RGB色彩空間中創建CGContext,在該上下文中繪製CGImage,獲取上下文數據,然後將其綁定到使用結構RGBA32的像素緩衝區。
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = inputCGImage.width
let height = inputCGImage.height
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = RGBA32.bitmapInfo
guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colspace, bitmapInfo: bitmapInfo) else {
print("unable to create context")
return nil
}
context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let buffer = context.data else {
print("unable to get context data")
return nil
}
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
struct RGBA32: Equatable {
var color: UInt32
var redComponent: UInt8 {
return UInt8((color >> 24) & 255)
}
var greenComponent: UInt8 {
return UInt8((color >> 16) & 255)
}
var blueComponent: UInt8 {
return UInt8((color >> 8) & 255)
}
var alphaComponent: UInt8 {
return UInt8((color >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
color = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
static let clear = RGBA32(red: 0, green: 0, blue: 0, alpha: 0)
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool {
return lhs.color == rhs.color
}
}
它然後使用該像素緩衝器,以使用非常簡單的歐幾里德距離,如下詳述的快速比較的顏色值來選擇的像素。
https://en.wikipedia.org/wiki/Color_difference
正如我所說的它的工作原理但對於更精確的結果我希望它的工作是CIE Lab色彩空間。
最初我嘗試將每個像素轉換爲LAB顏色,因爲他們被檢查,然後使用CIE94比較詳細的上述色差鏈接。它工作,但速度很慢,我猜是因爲它在檢查之前必須將一百萬像素(或左右)轉換爲LAB色。
然後,它讓我感到,爲了使它快速工作,將像素緩衝區存儲在LAB色彩空間(它不用於其他任何事情)會更好。
所以我創建了一個類似的結構LABA32
struct LABA32:Equatable {
var colour: UInt32
var lComponent: UInt8 {
return UInt8((colour >> 24) & 255)
}
var aComponent: UInt8 {
return UInt8((colour >> 16) & 255)
}
var bComponent: UInt8 {
return UInt8((colour >> 8) & 255)
}
var alphaComponent: UInt8 {
return UInt8((colour >> 0) & 255)
}
init(lComponent: UInt8, aComponent: UInt8, bComponent: UInt8, alphaComponent: UInt8) {
colour = (UInt32(lComponent) << 24) | (UInt32(aComponent) << 16) | (UInt32(bComponent) << 8) | (UInt32(alphaComponent) << 0)
}
static let clear = LABA32(lComponent: 0, aComponent: 0, bComponent: 0, alphaComponent: 0)
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: LABA32, rhs: LAB32) -> Bool {
return lhs.colour == rhs.colour
}
,如果我畫CGImage與LAB色彩空間,而不是設備RGB一個方面,應該將數據映射到這個新的結構,我可能是錯的,但在理論上。
我遇到的問題實際上是創建色彩空間(更不用說測試這個理論是否真的有效)。
要創建LAB色彩空間我想使用此構造
CGColorSpace(labWhitePoint: <UnsafePointer<CGFloat>!>, blackPoint: <UnsafePointer<CGFloat>!>, range: <UnsafePointer<CGFloat>!>)
根據蘋果文檔
白點:3個數字組成的數組,在指定的三刺激值, 漫反射白色點的CIE 1931 XYZ空間。 黑色點:一個 3個數字的數組,指定三色值,在CIE 1931 XYZ空間中,漫反射黑點。 範圍:由4個數字 組成的數組,指定顏色空間的a *和b *分量的有效值範圍。 a *分量表示從綠色 到紅色的值,而b *分量表示從藍色到 黃色的值。
CGFloats
的所以我創建了3個陣列var whitePoint:[CGFloat] = [0.95947,1,1.08883]
var blackPoint:[CGFloat] = [0,0,0]
var range:[CGFloat] = [-127,127,-127,127]
我再嘗試構建色彩空間
let colorSpace = CGColorSpace(labWhitePoint: &whitePoint, blackPoint: &blackPoint, range: &range)
的問題是,我不斷收到錯誤「不支持色彩空間」所以我必須做一些完全錯誤的事情。我花了很多時間尋找其他嘗試構建LAB色彩空間的人,但似乎沒有任何相關的東西,甚至試圖找到Objective-C版本。
那麼我該如何正確創建LAB色彩空間?
謝謝。