揭秘色彩空间L*a*b L*u*v 【内包含R'G'B'与Lab 互转代码】

XYZ 的衍生色彩空间 Lab* Luv*

由于XYZ色彩空间所描述的色彩并不是均匀的, 如蓝色的区域就会很密, x从0.2变到0.3, 颜色会有很大的不同, 绿色的y分量从0.7变到0.8 颜色只改变了一点点, 所以我们需要一个更加均匀的色彩空间CIE 1976 Lab 和 CIE 1976 Luv
Lab色彩空间中, ab 表示色度, Luv 色彩空间中, uv 表示色度。
其中, Lab 计算起来会比Luv复杂一些,更多的是非线性运算

image

XYZ转Lab*方法

image

XYZ转Luv*方法

image

Lab R'G'B'互转代码

在对颜色的处理中, 我们经常会用到Lab色彩空间, 这里把XYZ和Lab互转的源码贴出来,代码是自己亲手敲出来的,并且进行了严格的验证
这里使用的是sRGB色彩空间 方便大家理解
关于XYZ色彩空间的揭秘, 可以看我这篇博文:https://www.jianshu.com/p/1d45395c1ec8

#include <math.h>

typedef float (*FUNC_GAMMA)(float x);

static const float XYZn[3] = { 95.0489,100.0,108.8840 };

const float rgb2xyz_709[9] = {
        0.4124, 0.3576, 0.1805,
        0.2126, 0.7152, 0.0722,
        0.0193, 0.1192, 0.9505
};

const float xyz2rgb_709[9] = {
        3.2406   ,     -1.5372  ,      -0.4986,
        -0.9689  ,     1.8758   ,      0.0415,
        0.0557   ,     -0.2040  ,      1.0570
};

static void mul32f_3x3(const float* matrix, const float* in, float* out)
{
    out[0] = matrix[0] * in[0] + matrix[1] * in[1] + matrix[2] * in[2];
    out[1] = matrix[3] * in[0] + matrix[4] * in[1] + matrix[5] * in[2];
    out[2] = matrix[6] * in[0] + matrix[7] * in[1] + matrix[8] * in[2];
}

static float f(float t)
{
    float res = 0.0;
    const float sigma = 6.0 / 29.0;
    if (t > sigma* sigma* sigma) {
        res = pow(t, 1.0/3.0);
    }
    else {
        res = (t/(3*sigma*sigma)) + 4.0/29.0;
    }
    return res;
}

static float f_invert(float t) {
    float res = 0.0;
    float sigma = 6.0 / 29.0;
    if (t > sigma) {
        res = pow(t, 3.0);
    }
    else {
        res = 3.0 * sigma * sigma * (t - 4.0 / 29.0);
    }
    return res;
};

static void xyz2Lab(float* xyz, float* Lab)
{
    float X = xyz[0]/ XYZn[0];
    float Y = xyz[1]/ XYZn[1];
    float Z = xyz[2]/ XYZn[2];

    Lab[0] = 116.0 * f(Y) - 16.0;
    Lab[1] = 500.0 * (f(X) - f(Y));
    Lab[2] = 200.0 * (f(Y) - f(Z));
}

static  void Lab2xyz(float* Lab, float* xyz)
{
    float L = Lab[0];
    float a = Lab[1];
    float b = Lab[2];

    const float div_116 = 1.0 / 116.0;
    xyz[0] = XYZn[0] * f_invert(div_116 * (L + 16.0) + a / 500.0);
    xyz[1] = XYZn[1] * f_invert(div_116 * (L + 16.0));
    xyz[2] = XYZn[2] * f_invert(div_116 * (L + 16.0) - b / 200.0);
}


static  void rgb2xyz(float* rgb, float* xyz, const float *coeffs)
{
    mul32f_3x3(coeffs, rgb, xyz);
}

static  void xyz2rgb(float* xyz, float* rgb, const float* coeffs)
{
    mul32f_3x3(coeffs, xyz, rgb);
}

void rgbe2Lab(float* src, float* dst, FUNC_GAMMA func_gamma)
{
    float rgb[3];
    float xyz[3];
    for (int i = 0; i != 3; ++i) {
        rgb[i] = func_gamma(src[i]);
    }
    rgb[0] *= 100;
    rgb[1] *= 100;
    rgb[2] *= 100;
    rgb2xyz(rgb, xyz, rgb2xyz_709);
    xyz2Lab(xyz, dst);
}

void Lab2rgbe(float* src, float* dst, FUNC_GAMMA func_gamma)
{
    float rgb[3];
    float xyz[3];

    Lab2xyz(src, xyz);
    xyz2rgb(xyz, rgb, xyz2rgb_709);
    rgb[0] /= 100;
    rgb[1] /= 100;
    rgb[2] /= 100;

    for (int i = 0; i != 3; ++i) {
        dst[i] = func_gamma(rgb[i]);
    }
}

//For test

int main(int argc , char ** argv)
{
    float rgb[3] = { 1,0,0 };
    float lab[3] = {};
    float dstrgb[3] = {};
    rgbe2Lab(rgb, lab, rec_709_inverse_oetf);
    Lab2rgbe(lab, dstrgb, rec_709_oetf);
    getchar();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容