M5Unit-COLOR 0.2.0 git rev:d6fe6e1
Loading...
Searching...
No Matches
unit_color_utility.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_HPP
11#define M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_HPP
12
14#include <algorithm>
15#include <cmath>
16#include <tuple>
17#include <cassert>
18#include <type_traits>
19
20namespace m5 {
21namespace unit {
22namespace tcs3472x {
23
26// GA = 1.08 when the sensor is placed behind clear glass (pass it via dgf)
27constexpr float GA{1.0f};
28constexpr float DF{310.f};
29constexpr float DGF{GA * DF};
30constexpr float R_Coef{0.136f};
31constexpr float G_Coef{1.0f};
32constexpr float B_Coef{-0.444f};
33constexpr float CT_Coef{3810.f};
34constexpr float CT_Offset{1391.f};
36
39constexpr float AT_NORMAL_FACTOR{2.4f};
41constexpr float AT_NORMAL_MAX{256 * AT_NORMAL_FACTOR};
44constexpr float WT_NORMAL_MAX{256 * WT_NORMAL_FACTOR};
45constexpr float WT_LONG_FACTOR{2.4f * 12.f};
46constexpr float WT_LONG_MIN{WT_LONG_FACTOR};
47constexpr float WT_LONG_MAX{256 * WT_LONG_FACTOR};
49
64 Calibration(const uint16_t br, const uint16_t wr, const uint16_t bg, const uint16_t wg, const uint16_t bb,
65 const uint16_t wb)
66 : blackR{br}, whiteR{wr}, blackG{bg}, whiteG{wg}, blackB{bb}, whiteB{wb}
67 {
68 assert(wr > br && "White must be greater than black");
69 assert(wg > bg && "White must be greater than black");
70 assert(wb > bb && "White must be greater than black");
71 }
72
73 uint16_t blackR{};
74 uint16_t whiteR{};
75 uint16_t blackG{};
76 uint16_t whiteG{};
77 uint16_t blackB{};
78 uint16_t whiteB{};
79
81 inline uint8_t R8(const Data& d) const
82 {
83 return linear(d.RnoIR16(), blackR, whiteR);
84 }
86 inline uint8_t G8(const Data& d) const
87 {
88 return linear(d.GnoIR16(), blackG, whiteG);
89 }
91 inline uint8_t B8(const Data& d) const
92 {
93 return linear(d.BnoIR16(), blackB, whiteB);
94 }
95
103 inline static uint8_t linear(const uint16_t raw, const uint16_t low, const uint16_t high)
104 {
105 if (raw <= low) {
106 return 0U;
107 }
108 if (raw >= high) {
109 return 255U;
110 }
111 return static_cast<uint8_t>(
112 std::round((static_cast<float>(raw) - static_cast<float>(low)) / (static_cast<float>(high - low)) * 255.f));
113 }
114};
115
121inline float atime_to_ms(const uint8_t a)
122{
123 return 2.4f * (256 - a);
124}
125
132inline float wtime_to_ms(const uint8_t w, const bool wlong)
133{
134 return atime_to_ms(w) * (wlong ? 12 : 1);
135}
136
142inline uint8_t ms_to_atime(const float ms)
143{
144 int tmp = 256 - std::round(ms / 2.4f);
145 return static_cast<uint8_t>(std::max(std::min(tmp, 0xFF), 0x00));
146}
147
153std::tuple<uint8_t, bool> ms_to_wtime(const float ms);
154
169float calculateLux(const uint16_t rawR, const uint16_t rawG, const uint16_t rawB, const uint16_t rawC,
170 const float atime_ms, const Gain gc, const float dgf = DGF, const float coefR = R_Coef,
171 const float coefG = G_Coef, const float coefB = B_Coef);
172
183float calculateColorTemperature(const uint16_t rawR, const uint16_t rawG, const uint16_t rawB, const uint16_t rawC,
184 const float coefCT = CT_Coef, const float offsetCT = CT_Offset);
185
192uint16_t calculateSaturation(const uint8_t atime);
193
200inline uint16_t calculateSaturation(const float atime_ms)
201{
202 return calculateSaturation(ms_to_atime(atime_ms));
203}
204
210template <typename T, typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, uint8_t>::value,
211 std::nullptr_t>::type = nullptr>
212inline uint16_t calculateSaturation(const T atime)
213{
214 return calculateSaturation(static_cast<uint8_t>(atime));
215}
216
231float calculateCRATIO(const uint16_t rawR, const uint16_t rawG, const uint16_t rawB, const uint16_t rawC);
232
240float calculateCPL(const float atime_ms, const Gain gc, const float dgf = DGF);
241
249inline float calculateMaxLux(const float atime_ms, const Gain gc, const float dgf = DGF)
250{
251 return 65535.0f / (3.0f * calculateCPL(atime_ms, gc, dgf));
252}
253
255template <typename T, T... Ints>
256struct integer_sequence {
257 typedef T value_type;
258 static constexpr std::size_t size()
259 {
260 return sizeof...(Ints);
261 }
262};
263
264// Porting C++14 features to C++11
265// clang-format off
266template <size_t... Ints>
267using index_sequence = integer_sequence<size_t, Ints...>;
268
269template <typename T, size_t N, T... Is>
270struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Is...> {};
271
272template <typename T, T... Is>
273struct make_integer_sequence<T, 0, Is...> : integer_sequence<T, Is...> {};
274
275template <size_t N>
276using make_index_sequence = make_integer_sequence<size_t, N>;
277// clang-format on
278
279// constexpr version of std::pow is GCC4.6.1 or higher
280#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))
281#define M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CAN_CONSTEXPR_MAKE_GAMMA_TABLE
282#define M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR constexpr
283#else
284#define M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR
285#endif
286
287inline M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR uint8_t calculate_gamma(const float x, const float gamma)
288{
289 return static_cast<uint8_t>(std::pow(x, gamma) * 255 + 0.5f); // Rounded
290}
291
292template <size_t... Indices>
293M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR std::array<uint8_t, sizeof...(Indices)> make_gamma_table_impl(
294 const float gamma, index_sequence<Indices...>)
295{
296 return {calculate_gamma(static_cast<float>(Indices) / 255.0f, gamma)...};
297}
299
309template <size_t Size = 256>
310M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR std::array<uint8_t, Size> make_gamma_table(const float gamma = 2.2f)
311{
312 return make_gamma_table_impl(gamma, make_index_sequence<Size>{});
313}
314
315} // namespace tcs3472x
316} // namespace unit
317} // namespace m5
318#endif
Top level namespace of M5Stack.
For TCS3472x.
Unit-related namespace.
Raw value to determine black and white.
Definition unit_color_utility.hpp:54
uint16_t blackG
Black reference value for green.
Definition unit_color_utility.hpp:75
uint8_t G8(const Data &d) const
Get the green value with calibration.
Definition unit_color_utility.hpp:86
static uint8_t linear(const uint16_t raw, const uint16_t low, const uint16_t high)
Linear interpolation in a specified range.
Definition unit_color_utility.hpp:103
uint16_t whiteB
White reference value for blue.
Definition unit_color_utility.hpp:78
uint8_t B8(const Data &d) const
Get the blue value with calibration.
Definition unit_color_utility.hpp:91
uint16_t blackR
Black reference value for red.
Definition unit_color_utility.hpp:73
Calibration(const uint16_t br, const uint16_t wr, const uint16_t bg, const uint16_t wg, const uint16_t bb, const uint16_t wb)
Constructor.
Definition unit_color_utility.hpp:64
uint16_t blackB
Black reference value for blue.
Definition unit_color_utility.hpp:77
uint8_t R8(const Data &d) const
Get the red value with calibration.
Definition unit_color_utility.hpp:81
uint16_t whiteR
White reference value for red.
Definition unit_color_utility.hpp:74
uint16_t whiteG
White reference value for green.
Definition unit_color_utility.hpp:76
Measurement data group.
Definition unit_TCS3472x_data.hpp:66
uint16_t RnoIR16() const
Gets the raw red value without IR component.
Definition unit_TCS3472x_data.hpp:92
uint16_t BnoIR16() const
Gets the raw blue value without IR component.
Definition unit_TCS3472x_data.hpp:102
uint16_t GnoIR16() const
Gets the raw green value without IR component.
Definition unit_TCS3472x_data.hpp:97
Data types for TCS3472x.
Gain
RGBC Gain Control.
Definition unit_TCS3472x_data.hpp:55
uint16_t calculateSaturation(const uint8_t raw)
Calculate Saturation.
Definition unit_color_utility.cpp:71
float calculateCPL(const float atime_ms, const Gain gc, const float dgf)
Calculate Counts per Lux (CPL)
Definition unit_color_utility.cpp:90
constexpr float WT_NORMAL_MIN
Minimum WTIME (2.4 ms)
Definition unit_color_utility.hpp:43
uint8_t ms_to_atime(const float ms)
ms to ATIME
Definition unit_color_utility.hpp:142
constexpr float WT_LONG_MAX
Maximum WTIME with WLONG (7372.8 ms)
Definition unit_color_utility.hpp:47
constexpr float B_Coef
Lux coefficient for the blue channel.
Definition unit_color_utility.hpp:32
constexpr float WT_LONG_MIN
Minimum WTIME with WLONG (28.8 ms)
Definition unit_color_utility.hpp:46
constexpr float CT_Offset
Color temperature offset.
Definition unit_color_utility.hpp:34
constexpr float WT_NORMAL_MAX
Maximum WTIME without WLONG (614.4 ms)
Definition unit_color_utility.hpp:44
constexpr float DF
Device factor.
Definition unit_color_utility.hpp:28
float atime_to_ms(const uint8_t a)
ATIME to ms.
Definition unit_color_utility.hpp:121
M5_UNIT_COLOR_UTILITY_UNIT_COLOR_UTILITY_CONSTEXPR std::array< uint8_t, Size > make_gamma_table(const float gamma=2.2f)
Make gamma table.
Definition unit_color_utility.hpp:310
constexpr float WT_LONG_FACTOR
WTIME step with WLONG (ms)
Definition unit_color_utility.hpp:45
constexpr float DGF
Device and glass factor.
Definition unit_color_utility.hpp:29
constexpr float CT_Coef
Color temperature coefficient.
Definition unit_color_utility.hpp:33
float wtime_to_ms(const uint8_t w, const bool wlong)
WTIME and WLONG to ms.
Definition unit_color_utility.hpp:132
constexpr float R_Coef
Lux coefficient for the red channel.
Definition unit_color_utility.hpp:30
float calculateMaxLux(const float atime_ms, const Gain gc, const float dgf=DGF)
Calculate maximum Lux.
Definition unit_color_utility.hpp:249
constexpr float G_Coef
Lux coefficient for the green channel.
Definition unit_color_utility.hpp:31
constexpr float AT_NORMAL_FACTOR
ATIME step (ms)
Definition unit_color_utility.hpp:39
constexpr float WT_NORMAL_FACTOR
WTIME step (ms)
Definition unit_color_utility.hpp:42
constexpr float GA
Glass attenuation factor (open air)
Definition unit_color_utility.hpp:27
constexpr float AT_NORMAL_MAX
Maximum ATIME (614.4 ms)
Definition unit_color_utility.hpp:41
constexpr float AT_NORMAL_MIN
Minimum ATIME (2.4 ms)
Definition unit_color_utility.hpp:40