2017-03-17 56 views
1

我正在实施类似于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色彩空间?

谢谢。

回答

0

documentation还说:

重要:iOS不支持与设备无关的或通用的色彩空间。 iOS应用程序必须使用设备色彩空间。

所以,如果你想在LAB工作,我想你必须手动进行转换。