cied2000 | ciede2000 | try ciede2000 | Search

This code provides functions for color space conversions, including RGBtoXYZ, XYZtoLab, and rgb2lab, which transform RGB values into Lab* color space according to CIE XYZ and Lab specifications. The code uses C programming language and assumes RGB values are in the range [0, 255] and XYZ values are in the range [0, 1].

Run example

npm run import -- "rgb 2 lab"

rgb 2 lab

#include <math.h>

double F(double input) // function f(...), which is used for defining L, a and b changes within [4/29,1]
{
  if (input > 0.008856)
    return (pow(input, 0.333333333)); // maximum 1
  else
    return ((841/108)*input + 4/29);  //841/108 = 29*29/36*16
}


void XYZtoLab(double X, double Y, double Z, double *L, double *a, double *b)
{
  // TODO: make sure these are correct
  const double Xo = 244.66128; // reference white
  const double Yo = 255.0;
  const double Zo = 277.63227;
  *L = 116 * F(Y / Yo) - 16; // maximum L = 100
  *a = 500 * (F(X / Xo) - F(Y / Yo)); // maximum 
  *b = 200 * (F(Y / Yo) - F(Z / Zo));
}


// source http://www.easyrgb.com/en/math.php
void RGBtoXYZ(double R, double G, double B, double *X, double *Y, double *Z) {
  // Assume RGB has the type invariance satisfied, i.e., channels \in [0,255]
  float var_R = R / 255.0;
  float var_G = G / 255.0;
  float var_B = B / 255.0;

  var_R = (var_R > 0.04045) ? pow((var_R + 0.055) / 1.055, 2.4)
                            : var_R / 12.92;
  var_G = (var_G > 0.04045) ? pow((var_G + 0.055) / 1.055, 2.4)
                            : var_G / 12.92;
  var_B = (var_B > 0.04045) ? pow((var_B + 0.055) / 1.055, 2.4)
                            : var_B / 12.92;

  var_R *= 100;
  var_G *= 100;
  var_B *= 100;

  *X = var_R * 0.4124 + var_G * 0.3576 +
       var_B * 0.1805;
  *Y = var_R * 0.2126 + var_G * 0.7152 +
       var_B * 0.0722;
  *Z = var_R * 0.0193 + var_G * 0.1192 +
       var_B * 0.9505;
}


double *rgb2lab(int R, int G, int B){
  static double Lab[3] = {0, 0, 0};
  double X, Y, Z;
  RGBtoXYZ(R, G, B, &X, &Y, &Z);
  XYZtoLab(X, Y, Z, &Lab[0], &Lab[1], &Lab[2]);
  return Lab;
}


What the code could have been:

c
#include <math.h>

// Function to calculate F(x) according to the given formula
double F(double input) {
  // Ensure input is in the valid range [4/29, 1]
  if (input < 4 / 29.0) {
    // If input is out of range, clamp it to the minimum value
    input = 4 / 29.0;
  } else if (input > 1) {
    // If input is out of range, clamp it to the maximum value
    input = 1;
  }

  if (input <= 0.008856) {
    // For inputs less than or equal to 0.008856, use the linear formula
    return (841.0 / 108.0) * input + 4 / 29.0;
  } else {
    // For inputs greater than 0.008856, use the cubic root formula
    return pow(input, 1.0 / 3.0);
  }
}

// Function to convert XYZ to Lab color space
void XYZtoLab(double X, double Y, double Z, double *L, double *a, double *b) {
  const double Xo = 95.047;  // Reference white in CIE XYZ
  const double Yo = 100.0;   // Reference white in CIE XYZ
  const double Zo = 108.883; // Reference white in CIE XYZ

  // Calculate L, a, and b values
  *L = 116.0 * F(Y / Yo) - 16.0;
  *a = 500.0 * (F(X / Xo) - F(Y / Yo));
  *b = 200.0 * (F(Y / Yo) - F(Z / Zo));
}

// Function to convert RGB to XYZ color space
void RGBtoXYZ(double R, double G, double B) {
  // Assume RGB values are in the range [0, 1]
  double var_R = (R > 0.04045)? pow((R + 0.055) / 1.055, 2.4) : R / 12.92;
  double var_G = (G > 0.04045)? pow((G + 0.055) / 1.055, 2.4) : G / 12.92;
  double var_B = (B > 0.04045)? pow((B + 0.055) / 1.055, 2.4) : B / 12.92;

  // Scale XYZ values
  var_R *= 100.0;
  var_G *= 100.0;
  var_B *= 100.0;

  // Return XYZ values
  return var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805,
         var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722,
         var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
}

// Function to convert RGB to Lab color space
double *rgb2lab(int R, int G, int B) {
  static double Lab[3] = {0, 0, 0};
  double X, Y, Z;
  double xyz_values[3];
  xyz_values = RGBtoXYZ(R / 255.0, G / 255.0, B / 255.0);

  XYZtoLab(xyz_values[0], xyz_values[1], xyz_values[2],
           &Lab[0], &Lab[1], &Lab[2]);
  return Lab;
}

Code Breakdown

Function F

Function XYZtoLab

Function RGBtoXYZ

Function rgb2lab

Note