MeVisLab Toolbox Reference
mlCIELabToRGBTools.h
Go to the documentation of this file.
1 // Copyright (c) Fraunhofer MEVIS, Germany. All rights reserved.
2 // **InsertLicense** code
3 //----------------------------------------------------------------------------------
5 
10 //----------------------------------------------------------------------------------
11 
12 #pragma once
13 
14 #include "MLMLToDicomToolsSystem.h"
15 #include <mlTypeDefs.h>
16 #include <mlLinearAlgebra.h>
17 
18 ML_START_NAMESPACE
19 
25 inline Vector3 convertXYZToRGB(const Vector3& xyzIn, bool clampToStayInRGB=true) {
26  double var_X = xyzIn[0] / 100.0; // X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
27  double var_Y = xyzIn[1] / 100.0; // Y from 0 to 100.000
28  double var_Z = xyzIn[2] / 100.0; // Z from 0 to 108.883
29 
30  double var_R = var_X * 3.240479 + var_Y * -1.537150 + var_Z * -0.498535;
31  double var_G = var_X * -0.969256 + var_Y * 1.875992 + var_Z * 0.041556;
32  double var_B = var_X * 0.055648 + var_Y * -0.204043 + var_Z * 1.057311;
33 
34  if ( var_R > 0.0031308 ){ var_R = 1.055 * ( pow(var_R , ( 1.0 / 2.4 )) ) - 0.055; }
35  else { var_R = 12.92 * var_R; }
36  if ( var_G > 0.0031308 ){ var_G = 1.055 * ( pow(var_G , ( 1.0 / 2.4 )) ) - 0.055; }
37  else { var_G = 12.92 * var_G; }
38  if ( var_B > 0.0031308 ){ var_B = 1.055 * ( pow(var_B , ( 1.0 / 2.4 )) ) - 0.055; }
39  else { var_B = 12.92 * var_B; }
40 
41  if (clampToStayInRGB){
42  if (var_R < 0.){ var_R = 0.; } else if (var_R > 1.){ var_R = 1.; }
43  if (var_G < 0.){ var_G = 0.; } else if (var_G > 1.){ var_G = 1.; }
44  if (var_B < 0.){ var_B = 0.; } else if (var_B > 1.){ var_B = 1.; }
45  }
46 
47  Vector3 rgbOut;
48  rgbOut[0] = var_R;
49  rgbOut[1] = var_G;
50  rgbOut[2] = var_B;
51  return rgbOut;
52 }
53 
57 inline Vector3 convertCIELabToXYZ(const Vector3& cieLabIn) {
58  double var_Y = ( cieLabIn[0] + 16.0 ) / 116.0;
59  double var_X = cieLabIn[1] / 500.0 + var_Y;
60  double var_Z = var_Y - cieLabIn[2] / 200.0;
61 
62  if ( pow(var_Y,3.0) > 0.008856 ){ var_Y = pow(var_Y,3.0); }
63  else { var_Y = ( var_Y - 16 / 116 ) / 7.787; }
64  if ( pow(var_X,3.0) > 0.008856 ){ var_X = pow(var_X,3.0); }
65  else { var_X = ( var_X - 16 / 116 ) / 7.787; }
66  if ( pow(var_Z,3.0) > 0.008856 ){ var_Z = pow(var_Z,3.0); }
67  else { var_Z = ( var_Z - 16 / 116 ) / 7.787; }
68 
69  const double ref_X = 95.047; // Observer= 2°, Illuminant= D65
70  const double ref_Y = 100.000;
71  const double ref_Z = 108.883;
72 
73  Vector3 xyzOut;
74  xyzOut[0] = ref_X * var_X; // ref_X = 95.047 Observer= 2°, Illuminant= D65
75  xyzOut[1] = ref_Y * var_Y; // ref_Y = 100.000
76  xyzOut[2] = ref_Z * var_Z; // ref_Z = 108.883
77  return xyzOut;
78 }
79 
84 inline Vector3 convertCIELabToRGB(const Vector3& cieLabIn, bool clampToStayInRGB=true) {
85  return convertXYZToRGB(convertCIELabToXYZ(cieLabIn), clampToStayInRGB);
86 }
87 
90 inline Vector3 convertRGBToXYZ(const Vector3& rgbIn, bool clampToObserver2IlluminantD65=false) {
91  double var_R = rgbIn[0];
92  double var_G = rgbIn[1];
93  double var_B = rgbIn[2];
94 
95  if ( var_R > 0.04045 ){ var_R = pow(( ( var_R + 0.055 ) / 1.055 ) , 2.4); }
96  else { var_R = var_R / 12.92; }
97  if ( var_G > 0.04045 ){ var_G = pow(( ( var_G + 0.055 ) / 1.055 ) , 2.4); }
98  else { var_G = var_G / 12.92; }
99  if ( var_B > 0.04045 ){ var_B = pow(( ( var_B + 0.055 ) / 1.055 ) , 2.4); }
100  else { var_B = var_B / 12.92; }
101 
102  var_R = var_R * 100.;
103  var_G = var_G * 100.;
104  var_B = var_B * 100.;
105 
106  // Observer. = 2°, Illuminant = D65
107  // Source for example https://de.wikipedia.org/wiki/CIE-Normvalenzsystem
108  // and for more precise values now used in matrix
109  // https://stackoverflow.com/questions/6629798/whats-wrong-with-this-rgb-to-xyz-color-space-conversion-algorithm
110  Vector3 xyzOut;
111  xyzOut[0] = var_R * 0.4124564 + var_G * 0.3575761 + var_B * 0.1804375;
112  xyzOut[1] = var_R * 0.2126729 + var_G * 0.7151522 + var_B * 0.0721750;
113  xyzOut[2] = var_R * 0.0193339 + var_G * 0.1191920 + var_B * 0.9503041;
114 
115  if (clampToObserver2IlluminantD65){
116  if (xyzOut[0] < 0.){ xyzOut[0] = 0.; } else if (xyzOut[0] > 95.047){ xyzOut[0] = 95.047; }
117  if (xyzOut[1] < 0.){ xyzOut[1] = 0.; } else if (xyzOut[1] > 100.000){ xyzOut[1] = 100.000; }
118  if (xyzOut[2] < 0.){ xyzOut[2] = 0.; } else if (xyzOut[2] > 108.883){ xyzOut[2] = 108.883; }
119  }
120  return xyzOut;
121 }
122 
125 inline Vector3 convertXYZToCIELab(const Vector3& xyzIn) {
126  const double ref_X = 95.047; // Observer= 2°, Illuminant= D65
127  const double ref_Y = 100.000;
128  const double ref_Z = 108.883;
129 
130  double var_X = xyzIn[0] / ref_X;
131  double var_Y = xyzIn[1] / ref_Y;
132  double var_Z = xyzIn[2] / ref_Z;
133 
134  if ( var_X > 0.008856 ){ var_X = pow(var_X, ( 1./3. )); }
135  else { var_X = ( 7.787 * var_X ) + ( 16. / 116. ); }
136  if ( var_Y > 0.008856 ){ var_Y = pow(var_Y, ( 1./3. )); }
137  else { var_Y = ( 7.787 * var_Y ) + ( 16. / 116. ); }
138  if ( var_Z > 0.008856 ){ var_Z = pow(var_Z, ( 1./3. )); }
139  else { var_Z = ( 7.787 * var_Z ) + ( 16. / 116. ); }
140 
141  Vector3 cieLabOut;
142  cieLabOut[0] = ( 116. * var_Y ) - 16.;
143  cieLabOut[1] = 500. * ( var_X - var_Y );
144  cieLabOut[2] = 200. * ( var_Y - var_Z );
145  return cieLabOut;
146 }
147 
150 inline Vector3 convertRGBToCIELab(const Vector3& rgbIn) {
151  return convertXYZToCIELab(convertRGBToXYZ(rgbIn));
152 }
153 
158  cieLabIn[0] *= 655.35; // Scale from [0,100] to [0,65535]
159  cieLabIn[1] = (cieLabIn[1] + 128.)*256.; // Scale from [-128,127] to [0,65535].
160  cieLabIn[2] = (cieLabIn[2] + 128.)*256.; // Scale from [-128,127] to [0,65535].
161  return cieLabIn;
162 }
163 
167 inline Vector3 unscaleCIELabTagValue(Vector3 cieLabScaledIn) {
168  cieLabScaledIn[0] /= 655.35; // Scale from [0,65535] to [0,100].
169  cieLabScaledIn[1] = cieLabScaledIn[1]/256. - 128.; // Scale from [0,65535] to [-128,127].
170  cieLabScaledIn[2] = cieLabScaledIn[2]/256. - 128.; // Scale from [0,65535] to [-128,127].
171  return cieLabScaledIn;
172 }
173 
174 ML_END_NAMESPACE
175 
Project global and OS specific declarations.
Vector3 convertCIELabToRGB(const Vector3 &cieLabIn, bool clampToStayInRGB=true)
Converts an CIELab value to RGB without regarding monitor or observation specific settings,...
Vector3 convertXYZToRGB(const Vector3 &xyzIn, bool clampToStayInRGB=true)
Small and bad converter from XYZ in range [0,0,0], [95.047, 100, 108.883] to RGB with r,...
Vector3 convertRGBToXYZ(const Vector3 &rgbIn, bool clampToObserver2IlluminantD65=false)
Small and bad converter from RGB to XYZ with r,g,b in [0,1], assuming observer = 2° and illuminant = ...
Vector3 convertCIELabToXYZ(const Vector3 &cieLabIn)
Small and bad converter from CIELab in range [0,-128,-128], [100, 128, 128] to XYZ in range [0,...
Vector3 scaleCIELabTo16BitUnsigned(Vector3 cieLabIn)
Scale a given cieLabIn value to 16 bit unsigned integer range as described in DICOM standard C....
Vector3 convertXYZToCIELab(const Vector3 &xyzIn)
Small and bad converter from XYZ to CIELab, assuming observer = 2° and illuminant = D65.
Vector3 convertRGBToCIELab(const Vector3 &rgbIn)
Converts an RGB value in [0,1] to CIELab without regarding monitor or observation specific settings,...
Vector3 unscaleCIELabTagValue(Vector3 cieLabScaledIn)
Unscale a given cieLabScalesIn value to [0,100], [-128,127], [-127,127] ranges as described in DICOM ...