File: cielab.c

package info (click to toggle)
fitspng 1.4-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 1,804 kB
  • sloc: sh: 1,232; ansic: 860; makefile: 14
file content (78 lines) | stat: -rw-r--r-- 1,812 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*

  CIELAB implementation for FITSPNG     FITS to PNG converter
  Copyright (C) 2018  Filip Hroch, Masaryk University, Brno, CZ

  Fitspng is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Fitspng is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Fitspng.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "fitspng.h"
#include <math.h>

#include <assert.h>

// https://en.wikipedia.org/wiki/CIELAB_color_space

/* CIE Lab, D65 white point */
const float Xn = 95.047;
const float Yn = 100.0;
const float Zn = 108.883;

/* CIE Lab parameters */
const float d = 6.0 / 29.0;
const float a = 0.2068965;  /* = 3 * (6/29)**2 */
const float b = 4.0 / 29.0;

float Lab_fun(float I, float In)
{
  const float d3 = d*d*d;
  float r;

  r = I / In;
  return r > d3 ? cbrtf(r) : r / a + b;
}

float Lab_invfun(float f, float In)
{
  return In * (f > d ? f*f*f : a*(f - b));
}


void XYZ_Lab(float X, float Y, float Z, float *L, float *a, float *b)
{
  float fx, fy, fz;

  fx = Lab_fun(X,Xn);
  fy = Lab_fun(Y,Yn);
  fz = Lab_fun(Z,Zn);

  *L = 116.0f*fy - 16.0f;
  *a = 500.0f*(fx - fy);
  *b = 200.0f*(fy - fz);
}


void Lab_XYZ(float L, float a, float b, float *X, float *Y, float *Z)
{
  float Lx, ax, bx;

  Lx = (L + 16.0f) / 116.0f;
  ax = Lx + a / 500.0f;
  bx = Lx - b / 200.0f;

  *X = Lab_invfun(ax,Xn);
  *Y = Lab_invfun(Lx,Yn);
  *Z = Lab_invfun(bx,Zn);
}