私は、Photoshopのiosのマジックワンドツールに似たカラー選択ツールを実装しています。ラボの色空間でピクセルバッファを作成する
私はすでに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比較を使用しました。それは働いていましたが、非常に遅かったです。チェックする前に100万画素(またはそれ以上)をLABカラーに変換しなければならなかったからです。
それがすぐに動作するように、私は、LABの色空間にピクセルバッファを保存する方が良いと思いました(他のものには使用されていません)。
だから私は、私は間違っているかもしれないが、私はLABのcolourspaceとコンテキストの代わりに、デバイスRGBにCGImageを描く場合、理論的には、それはこの新しい構造体にデータをマップする必要があります同様の構造体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
}
を作成。
私が抱えている問題は、実際に色空間を作成していることです(この理論が実際に機能するかどうかをテストするだけではありません)。三刺激値を指定する3つの数字の配列、 中:私は
CGColorSpace(labWhitePoint: <UnsafePointer<CGFloat>!>, blackPoint: <UnsafePointer<CGFloat>!>, range: <UnsafePointer<CGFloat>!>)
よる
リンゴのドキュメントへの白色点、このコンストラクタを使用しようとしていますLABのcolourspaceを作成するには
拡散白色点のCIE1931 XYZ空間である。 ブラックポイント:拡散黒点の三刺激値をCIE1931 XYZ-空間で指定する3つの数字からなる の配列。 範囲:色空間の のa *とb *成分の有効な値の範囲を指定する4つの数字の配列 。 a *成分は緑色の から赤色までの値を表し、b *成分は青色から までの黄色の値を表します。
だから私はCGFloats
var whitePoint:[CGFloat] = [0.95947,1,1.08883]
var blackPoint:[CGFloat] = [0,0,0]
var range:[CGFloat] = [-127,127,-127,127]
の3つの配列を作成しました私は、問題は、私はエラー「サポートされていない色空間」を取得しておくことです
let colorSpace = CGColorSpace(labWhitePoint: &whitePoint, blackPoint: &blackPoint, range: &range)
色空間を構築してみてください私は完全に間違って何かをしているに違いない。私はLAB色空間を構築しようとしている他の人を探すのに多くの時間を費やしましたが、目的のCバージョンを探すことさえしようとするものはありません。
実際にLABの色空間を正しく作成するにはどうすればよいですか?
ありがとうございました。