Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

generateColorFuncs.js 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // @ts-nocheck
  2. 'use strict';
  3. // these algorithms are sourced from https://drafts.csswg.org/css-color/#color-conversion-code
  4. function lin_sRGB(RGB) {
  5. // convert an array of sRGB values in the range 0.0 - 1.0
  6. // to linear light (un-companded) form.
  7. // https://en.wikipedia.org/wiki/SRGB
  8. return RGB.map((val) => {
  9. if (val < 0.04045) {
  10. return val / 12.92;
  11. }
  12. return ((val + 0.055) / 1.055) ** 2.4;
  13. });
  14. }
  15. function matrixMultiple3d(matrix, vector) {
  16. return [
  17. matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],
  18. matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],
  19. matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2],
  20. ];
  21. }
  22. function srgb2xyz(srgb) {
  23. return matrixMultiple3d(
  24. [
  25. [0.4124564, 0.3575761, 0.1804375],
  26. [0.2126729, 0.7151522, 0.072175],
  27. [0.0193339, 0.119192, 0.9503041],
  28. ],
  29. srgb,
  30. );
  31. }
  32. function chromaticAdaptationD65_D50(xyz) {
  33. return matrixMultiple3d(
  34. [
  35. [1.0478112, 0.0228866, -0.050127],
  36. [0.0295424, 0.9904844, -0.0170491],
  37. [-0.0092345, 0.0150436, 0.7521316],
  38. ],
  39. xyz,
  40. );
  41. }
  42. function xyz2lab(xyzIn) {
  43. // Assuming XYZ is relative to D50, convert to CIE Lab
  44. // from CIE standard, which now defines these as a rational fraction
  45. const ε = 216 / 24389; // 6^3/29^3
  46. const κ = 24389 / 27; // 29^3/3^3
  47. const white = [0.9642, 1.0, 0.8249]; // D50 reference white
  48. // compute xyz, which is XYZ scaled relative to reference white
  49. const xyz = xyzIn.map((value, i) => value / white[i]);
  50. // now compute f
  51. const f = xyz.map((value) => {
  52. if (value > ε) {
  53. return Math.cbrt(value);
  54. }
  55. return (κ * value + 16) / 116;
  56. });
  57. return [
  58. 116 * f[1] - 16, // L
  59. 500 * (f[0] - f[1]), // a
  60. 200 * (f[1] - f[2]), // b
  61. ];
  62. }
  63. function rgb2hsl(r, g, b) {
  64. r /= 255;
  65. g /= 255;
  66. b /= 255;
  67. let h;
  68. let s;
  69. let l;
  70. const M = Math.max(r, g, b);
  71. const m = Math.min(r, g, b);
  72. const d = M - m;
  73. if (d === 0) {
  74. h = 0;
  75. } else if (M === r) {
  76. h = ((g - b) / d) % 6;
  77. } else if (M === g) {
  78. h = (b - r) / d + 2;
  79. } else {
  80. h = (r - g) / d + 4;
  81. }
  82. h *= 60;
  83. if (h < 0) {
  84. h += 360;
  85. }
  86. l = (M + m) / 2;
  87. s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
  88. s *= 100;
  89. l *= 100;
  90. return [Math.round(h), Math.round(s), Math.round(l)];
  91. }
  92. function rgb2hwb(rgb_r, rgb_g, rgb_b) {
  93. rgb_r /= 255;
  94. rgb_g /= 255;
  95. rgb_b /= 255;
  96. const w = Math.min(rgb_r, rgb_g, rgb_b);
  97. const v = Math.max(rgb_r, rgb_g, rgb_b);
  98. const b = 1 - v;
  99. if (v === w) {
  100. return [0, Math.round(w * 100), Math.round(b * 100)];
  101. }
  102. const f = rgb_r === w ? rgb_g - rgb_b : rgb_g === w ? rgb_b - rgb_r : rgb_r - rgb_g;
  103. const i = rgb_r === w ? 3 : rgb_g === w ? 5 : 1;
  104. return [
  105. Math.round(((i - f / (v - w)) / 6) * 360) % 360,
  106. Math.round(w * 100),
  107. Math.round(b * 100),
  108. ];
  109. }
  110. function perc255(value) {
  111. return `${Math.round((value * 100) / 255)}%`;
  112. }
  113. function generateColorFuncs(hexString) {
  114. if (hexString.length !== 7) {
  115. throw new Error(
  116. `Invalid hex string color definition (${hexString}) - expected 6 character hex string`,
  117. );
  118. }
  119. const rgb = [0, 0, 0];
  120. for (let i = 0; i < 3; i += 1) {
  121. rgb[i] = Number.parseInt(hexString.substr(2 * i + 1, 2), 16);
  122. }
  123. const hsl = rgb2hsl(rgb[0], rgb[1], rgb[2]);
  124. const hwb = rgb2hwb(rgb[0], rgb[1], rgb[2]);
  125. const func = [];
  126. const rgbStr = `${rgb[0]},${rgb[1]},${rgb[2]}`;
  127. const rgbPercStr = `${perc255(rgb[0])},${perc255(rgb[1])},${perc255(rgb[2])}`;
  128. const hslStr = `${hsl[0]},${hsl[1]}%,${hsl[2]}%`;
  129. const hwbStr = `${hwb[0]},${hwb[1]}%,${hwb[2]}%`;
  130. // *very* convoluted process, just to be able to establish if the color
  131. // is gray -- or not.
  132. const linRgb = lin_sRGB([rgb[0] / 255, rgb[1] / 255, rgb[2] / 255]);
  133. const xyz_d65 = srgb2xyz(linRgb);
  134. const xyz_d50 = chromaticAdaptationD65_D50(xyz_d65);
  135. const lab = xyz2lab(xyz_d50);
  136. func.push(`rgb(${rgbStr})`);
  137. func.push(`rgba(${rgbStr},1)`);
  138. func.push(`rgba(${rgbStr},100%)`);
  139. func.push(`rgb(${rgbPercStr})`);
  140. func.push(`rgba(${rgbPercStr},1)`);
  141. func.push(`rgba(${rgbPercStr},100%)`);
  142. func.push(`hsl(${hslStr})`);
  143. func.push(`hsla(${hslStr},1)`);
  144. func.push(`hsla(${hslStr},100%)`);
  145. func.push(`hwb(${hwbStr})`);
  146. func.push(`hwb(${hwbStr},1)`);
  147. func.push(`hwb(${hwbStr},100%)`);
  148. // technically, this should be 0 - but then #808080 wouldn't even be gray
  149. if (lab[1] * lab[1] < 0.01 && lab[2] * lab[2] < 0.01) {
  150. // yay! gray!
  151. const grayStr = Math.round(lab[0]);
  152. func.push(`gray(${grayStr})`);
  153. func.push(`gray(${grayStr},1)`);
  154. func.push(`gray(${grayStr},100%)`);
  155. func.push(`gray(${grayStr}%)`);
  156. func.push(`gray(${grayStr}%,1)`);
  157. func.push(`gray(${grayStr}%,100%)`);
  158. }
  159. return func;
  160. }
  161. module.exports = generateColorFuncs;