-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6b31cc8
commit 9fc53ca
Showing
10 changed files
with
487 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// FILE: Kelvin2RGB.cpp | ||
// AUTHOR: Rob Tillaart | ||
// VERSION: 0.1.0 | ||
// DATE: 2018-01-31 | ||
// PURPOSE: Arduino library for converting temperature to RGB values | ||
// URL: https://github.com/RobTillaart/Kelvin2RGB | ||
|
||
#include "Kelvin2RGB.h" | ||
|
||
#define DIVIDE_255 0.0039215686274509803921568627451 | ||
|
||
Kelvin2RGB::Kelvin2RGB() | ||
{ | ||
_temperature = 0; | ||
_brightness = 0; | ||
_red = 0; | ||
_green = 0; | ||
_blue = 0; | ||
} | ||
|
||
void Kelvin2RGB::begin() | ||
{ | ||
} | ||
|
||
|
||
// Tanner Helland formulas | ||
void Kelvin2RGB::convert_TH(float temperature, float brightness) | ||
{ | ||
_temperature = constrain(temperature, 0, 65500); | ||
_brightness = constrain(brightness, 0, 100); | ||
|
||
_red = _green = _blue = 0; | ||
float t = _temperature * 0.01; | ||
|
||
if (t <= 66) | ||
{ | ||
_red = 255; | ||
_green = (99.4708025861 * log(t)) - 161.1195681661; | ||
if (t > 19) | ||
{ | ||
_blue = (138.5177312231 * log(t - 10)) - 305.0447927307; | ||
} | ||
else _blue = 0; | ||
} | ||
else | ||
{ | ||
_red = 329.698727466 * pow(t - 60, -0.1332047592); | ||
_green = 288.1221695283 * pow(t - 60, -0.0755148492); | ||
_blue = 255; | ||
} | ||
float f = 0.01 * _brightness; | ||
_red = f * constrain(_red, 0, 255); | ||
_green = f * constrain(_green, 0, 255); | ||
_blue = f * constrain(_blue, 0, 255); | ||
_rgb = round(_red) * 65536UL + round(_green) * 256UL + round(_blue); | ||
|
||
// divide by 255 to get factors between 0..1 | ||
_red *= DIVIDE_255; | ||
_green *= DIVIDE_255; | ||
_blue *= DIVIDE_255; | ||
} | ||
|
||
|
||
// Neil Bartlett formulas | ||
void Kelvin2RGB::convert_NB(float temperature, float brightness) | ||
{ | ||
_temperature = constrain(temperature, 0, 65500); | ||
_brightness = constrain(brightness, 0, 100); | ||
|
||
_red = _green = _blue = 0; | ||
float t = _temperature * 0.01; | ||
|
||
if (t <= 66) | ||
{ | ||
_red = 255; | ||
_green = t - 2; | ||
_green = -155.25485562709179 - 0.44596950469579133 * _green + 104.49216199393888 * log(_green); | ||
_blue = 0; | ||
if (t > 20) | ||
{ | ||
_blue = t - 10; | ||
_blue = -254.76935184120902 + 0.8274096064007395 * _blue + 115.67994401066147 * log(_blue); | ||
} | ||
} | ||
else | ||
{ | ||
_red = t - 55.0; | ||
_red = 351.97690566805693 + 0.114206453784165 * _red - 40.25366309332127 * log(_red); | ||
_green = t - 50.0; | ||
_green = 325.4494125711974 + 0.07943456536662342 * _green - 28.0852963507957 * log(_green); | ||
_blue = 255; | ||
} | ||
|
||
float f = 0.01 * _brightness; | ||
_red = f * constrain(_red, 0, 255); | ||
_green = f * constrain(_green, 0, 255); | ||
_blue = f * constrain(_blue, 0, 255); | ||
_rgb = round(_red) * 65536UL + round(_green) * 256UL + round(_blue); | ||
|
||
// divide by 255 to get factors between 0..1 | ||
_red *= DIVIDE_255; | ||
_green *= DIVIDE_255; | ||
_blue *= DIVIDE_255; | ||
} | ||
|
||
// -- END OF FILE -- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#pragma once | ||
// | ||
// FILE: Kelvin2RGB.h | ||
// AUTHOR: Rob Tillaart | ||
// VERSION: 0.1.0 | ||
// DATE: 2018-01-31 | ||
// PURPOSE: Arduino library for converting temperature to RGB values | ||
// URL: https://github.com/RobTillaart/Kelvin2RGB | ||
// | ||
// Based upon article Tanner Helland and Neil Bartlett | ||
// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ | ||
// http://www.zombieprototypes.com/?p=210 | ||
// https://en.wikipedia.org/wiki/Color_temperature#Categorizing_different_lighting | ||
|
||
#define KELVIN2RGB_LIB_VERSION "0.1.0" | ||
|
||
#include "Arduino.h" | ||
|
||
// based on https://en.wikipedia.org/wiki/Color_temperature#Categorizing_different_lighting | ||
// TODO a memory efficient storage -> uint8_t 17 .. 255 (factor 100) | ||
// how? hash function? parameter settings convert(dayLightSetting) | ||
/* | ||
NAME TEMPERATURE | ||
============================= | ||
match = 1700; | ||
sodiumLamp = 1700; | ||
candleFlame = 1850; | ||
sunrise = 1850; | ||
sunset = 1850; | ||
bulb = 2400; | ||
bulbSoftWhite = 2550; | ||
LEDlamp = 2700; | ||
warmWhite = 3000; | ||
studioLight = 3200; | ||
studioCPlight = 3350; | ||
daylightHorizon = 5000; | ||
flashLight = 5700; | ||
xenonLight = 6200; | ||
dayLightBright = 6500; | ||
normal = 6500; | ||
screenlow = 6500; | ||
screenMed = 8000; | ||
screenHigh = 9500; | ||
polewardSky0 = 15000; | ||
polewardSky1 = 19000; | ||
polewardSky2 = 23000; | ||
polewardSky3 = 27000; | ||
*/ | ||
|
||
|
||
class Kelvin2RGB | ||
{ | ||
public: | ||
Kelvin2RGB(); | ||
void begin(); | ||
|
||
// temp = 0..65500 brightness = 0.0 .. 100.0% | ||
void convert_TH(float temperature, float brightness = 100); | ||
void convert_NB(float temperature, float brightness = 100); | ||
|
||
float temperature() { return _temperature; }; | ||
float brightness() { return _brightness; }; | ||
inline float red() { return _red; }; | ||
inline float green() { return _green; }; | ||
inline float blue() { return _blue; }; | ||
uint32_t RGB() { return _rgb; } | ||
|
||
|
||
private: | ||
float _temperature; | ||
float _brightness; | ||
float _red; | ||
float _green; | ||
float _blue; | ||
uint32_t _rgb; | ||
}; | ||
|
||
// -- END OF FILE -- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,82 @@ | ||
# Kelvin2RGB | ||
|
||
Arduino library for converting temperature to RGB values | ||
|
||
## Credentials | ||
|
||
This library is based upon an article of Tanner Helland | ||
and a related story by Neil Bartlett | ||
http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ | ||
http://www.zombieprototypes.com/?p=210 | ||
https://en.wikipedia.org/wiki/Color_temperature#Categorizing_different_lighting | ||
|
||
There are more approximation formulas, some claim to be better, | ||
however these are not investigated. | ||
|
||
## Description | ||
|
||
The library converts a temperature in Kelvin and an brightness (0..100%) | ||
to 3 numbers red, green and blue. | ||
These numbers are weights can be used to correct a colorimage for virtual white temperature. | ||
|
||
There are 2 convert functions where the **convert_NB()** is claimed to be the | ||
more accurate one. | ||
|
||
With the numbers R,G,B calculated one can convert images so they will look more like | ||
taken with candle light, sunrise or sunset etc. | ||
|
||
**pseudo code** | ||
```cpp | ||
Kelvin2RGB KRGB; | ||
|
||
KRGB.convert(1850, 100); // sunrise light factors | ||
|
||
for each pixel in image | ||
{ | ||
red *= KRGB.red(); | ||
green *= KRGB.green(); | ||
blue *= KRGB.blue(); | ||
drawPixel(); | ||
} | ||
``` | ||
|
||
The numbers can also be used to reduce the blue channel so it has less effect | ||
on "getting sleepy". | ||
|
||
The library uses floats for the R,G and B weights to keep values as accurate as possible. | ||
Especially with images with more than 8 bits per channel this is preferred. | ||
That said it is also possible to use this on a 565 image or to adjust color lookup tables. | ||
|
||
|
||
## Interface | ||
|
||
The interface is pretty straightforward. | ||
|
||
- **Kelvin2RGB()** constructor | ||
- **begin()** for now an empty function. | ||
- **convert_TH(float temperature, float brightness = 100)** | ||
temperature = 0..65500 temperature below 1000 is not well defined. | ||
brightness = 0..100%, | ||
- **convert_NB(float temperature, float brightness = 100)** | ||
temperature = 0..65500 temperature below 1000 is not well defined. | ||
brightness = 0..100%, | ||
Is a bit more accurate and slightly slower (few %). Read link above for more information. | ||
- **float temperature()** returns temperature, to check the value used. | ||
- **float brightness()** returns brightness, to check the value used. | ||
- **float red()** returns red channel weight 0.0 .. 1.0 | ||
note this is different from Helland / Bartlett who both use an integer value 0 .. 255 | ||
- **float green()** returns green channel weight 0.0 .. 1.0 | ||
- **float blue()** returns blue channel weight 0.0 .. 1.0 | ||
- **uint32_t RGB()** retuns a 24 bit RGB value, | ||
more efficient than 3 floats for communication. | ||
|
||
## future | ||
|
||
- separate brightness per color channel to mimic "artificial illumination" | ||
- define constants like candleLight as parameter. | ||
|
||
|
||
## Operations | ||
|
||
See examples | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// FILE: Kelvin2RGB_difference.ino | ||
// AUTHOR: Rob Tillaart | ||
// VERSION: 0.1.0 | ||
// PURPOSE: demo - shows difference between 2 convert functions. | ||
// DATE: 2020-07-29 | ||
// URL: https://github.com/RobTillaart/Kelvin2RGB | ||
// | ||
|
||
// shows difference between the two calculations | ||
// best viewed in plotter. | ||
|
||
#include "Kelvin2RGB.h" | ||
|
||
Kelvin2RGB KRGB; | ||
Kelvin2RGB KRGB2; | ||
|
||
void setup() | ||
{ | ||
Serial.begin(115200); | ||
Serial.println(__FILE__); | ||
|
||
KRGB.begin(); | ||
KRGB2.begin(); | ||
|
||
test_difference(); | ||
} | ||
|
||
void loop() | ||
{ | ||
} | ||
|
||
void test_difference() | ||
{ | ||
float bright = 100.0; | ||
for (uint32_t temp = 0; temp < 70000; temp += 200) | ||
{ | ||
KRGB.convert_TH(temp, bright); | ||
KRGB2.convert_NB(temp, bright); | ||
Serial.print(KRGB.blue() - KRGB2.blue()); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.red() - KRGB2.red()); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.green() - KRGB2.green()); | ||
Serial.print("\n"); | ||
} | ||
} | ||
|
||
// -- END OF FILE -- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// | ||
// FILE: Kelvin2RGB_table.ino | ||
// AUTHOR: Rob Tillaart | ||
// VERSION: 0.1.0 | ||
// PURPOSE: generate table of values | ||
// DATE: 2020-07-29 | ||
// URL: https://github.com/RobTillaart/Kelvin2RGB | ||
// | ||
|
||
#include "Kelvin2RGB.h" | ||
|
||
Kelvin2RGB KRGB; | ||
|
||
void setup() | ||
{ | ||
Serial.begin(115200); | ||
Serial.println(__FILE__); | ||
|
||
KRGB.begin(); | ||
test(); | ||
} | ||
|
||
void loop() | ||
{ | ||
} | ||
|
||
void test() | ||
{ | ||
float bright = 100.0; // change to 0.0 | ||
while (bright <= 100.0) | ||
{ | ||
bright += 5; | ||
for (uint32_t temp = 0; temp < 70000; temp += 200) | ||
{ | ||
Serial.print(KRGB.temperature(), 0); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.brightness(), 0); | ||
Serial.print("\t"); | ||
|
||
KRGB.convert_TH(temp, bright); | ||
Serial.print(KRGB.red(), 4); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.green(), 4); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.blue(), 4); | ||
Serial.print("\t"); | ||
|
||
KRGB.convert_NB(temp, bright); | ||
Serial.print(KRGB.red(), 4); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.green(), 4); | ||
Serial.print("\t"); | ||
Serial.print(KRGB.blue(), 4); | ||
Serial.print("\n"); | ||
} | ||
} | ||
} | ||
|
||
// -- END OF FILE -- |
Oops, something went wrong.