1

使用 RGB 值时,.NET 内置了将其从整数转换的方法,并且将颜色转换为 int 很简单。有没有办法将 LAB 颜色存储为整数?与 RGB 不同,LAB 颜色值可以为负值。如果我可以避免它,我不想将颜色存储在 RGB 中并在运行时转换它们,因为我不需要 RGB 值。

4

1 回答 1

3

所以正在完成的转换是 RGB -> XYZ 与旧的 2 度观察者和 CIE 标准光源 D65 -> CIELAB。用于执行的代码供参考,如下所示(假设 R、G、B 在 [0, 1] 中)。

考虑到这些从 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
于 2013-01-05T22:36:34.780 回答