简体   繁体   English

将LAB颜色存储为整数

[英]Storing LAB colors as integers

When using RGB values, .NET has built in ways for it to be converted from an integer and it's straightforward to convert a color to an int. 当使用RGB值时,.NET已经建立了将其从整数转换的方式,并且很容易将颜色转换为int。 Is there a way of storing LAB colors as integers instead? 有没有一种方法可以将LAB颜色存储为整数? Unlike RGB, LAB color values can be negative. 与RGB不同,LAB颜色值可以为负。 I don't want to have to store the colors in RGB and convert them at runtime if I can avoid it as I have no need for RGB values. 如果不需要,我不需要将颜色存储为RGB并在运行时进行转换,因为我不需要RGB值。

So the transformation being done is RGB -> XYZ with the old 2 degree observer and CIE Standard Illuminant D65 -> CIELAB. 因此,要完成的转换是使用旧的2度观察器进行RGB-> XYZ转换,并使用CIE Standard Illuminant D65-> CIELAB。 The code, for reference, for performing that is given below (R, G, B is assumed to be in [0, 1]). 以下给出的用于执行的代码(假定R,G,B在[0,1]中)。

Considering these transformations starting from 8 bits per channel in RGB, the range for L* is [0, 100], a* (-85.92, 97.96], b* (-107.54, 94.20]. These values are close approximations. In theory, a* and b* are unbounded, but you will find some places that talk about a limit of +-128, +-110, etc. My suggestion is then to simply sum 128 to each value, multiply it by 100, and then round to integer (that should be precise enough for a color). Any given L*a*b triplet can then be represented by a 16 bits unsigned integer. You could pack them into a 64 bit integer. And after unpacking you would subtract 128 from each value. If you can keep three signed short integers, things get much simpler. 考虑到这些转换从RGB中每通道8位开始,L *的范围为[0,100],a *(-85.92,97.96],b *(-107.54,94.20]。这些值是近似值。 ,a *和b *是无界的,但是您会发现一些地方讨论极限为+ -128,+-110等。我的建议是将每个值简单地相加128,再乘以100,然后四舍五入为整数(对于颜色来说应该足够精确),然后,任何给定的L * a * b三元组都可以由16位无符号整数表示。您可以将它们打包为64位整数。解压缩后会减去128如果可以保留三个有符号的短整数,则事情变得简单得多。

def rgb_xyz(r, g, b): # 2o. D65
    triple = [r, g, b]

    v, d = 0.04045, 12.94
    for i, c in enumerate(triple):
        triple[i] = 100 * (c / d if c <= v else ((c + 0.055)/1.055)**2.4)

    multipliers = (
            (0.4124, 0.3576, 0.1805),
            (0.2126, 0.7152, 0.0722),
            (0.0193, 0.1192, 0.9505))

    x, y, z = [sum(row[i] * triple[i] for i in range(3))
            for row in multipliers]
    return x, y, z

def xyz_cielab(x, y, z):
    triple = [x, y, z]

    t0, a, b = 0.008856, 7.787, 16/116.
    ref = (95.047, 100.0, 108.883)
    for i, c in enumerate(triple):
        triple[i] /= ref[i]
        c = triple[i]
        triple[i] = c ** (1/3.) if c > t0 else a * c + b

    l = 116 * triple[0] - 16
    a = 500 * (triple[0] - triple[1])
    b = 200 * (triple[1] - triple[2])
    return l, a, b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM