0.2.0 map2colour

This commit is contained in:
Rob Tillaart 2023-04-26 09:26:03 +02:00
parent 3cdd0e5a43
commit c2badab145
12 changed files with 619 additions and 123 deletions

View File

@ -6,13 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.2.0] - 2023-04-24
- add dynamic size in constructor (minimum 7 for backwards)
- add destructor.
- add **uint8_t size()**
- add **m2c_colours.h** for colour constants
- add **M2C_GRAY** constants
- array of values now may be non-decreasing (iso increasing)
- update readme.md
- minor edits
----
## [0.1.6] - 2023-02-21
- update readme.md
- update GitHub actions
- update license 2023
- minor edits
## [0.1.5] - 2022-10-19
- redo **begin()** of map2colourFast to always create divFactors.
- add compare example to compare map2colour and map2colourFast.

View File

@ -8,45 +8,57 @@
# map2colour
Arduino library for mapping a float to colour spectrum.
Arduino library for mapping a float to a colour spectrum.
## Description
The map2colour library is used to make map a reading from a sensor, e.g. temperature or pressure,
to a colour in the RGB spectrum. This can be used to colour an element on a graphical display, drive an RGB LED, or even a LED string etc.
The map2colour library is used to map a float value to a colour in the RGB spectrum.
The float value can be the result of a calculation or read from a sensor,
e.g. temperature, humidity, light, distance, direction or pressure.
The initial release uses 7 floats values that describe the range being mapped.
These are passed to the library with **begin()**.
These 7 floats must be in ascending order and are mapped default on the following colour array.
This function can be used to colour an element on a graphical display,
drive an RGB LED, or a LED string etc to indicate some sort of state visually.
The first releases used a fixed number of 7 floats values that describe the range being mapped.
With version 0.2.0 one can define the size as a parameter of the constructor.
There is no limit (except RAM) in theory, but in practice 16 or 32 entries is a lot.
A lookup array of float values is passed to the library with **begin()**.
These floats must be in **non-decreasing** order and are mapped default on the following colour array.
```cpp
uint32_t colours[] =
{
// BLACK RED YELLOW GREEN AQUA BLUE WHITE
// M2C_BLACK M2C_RED M2C_YELLOW M2C_LIME M2C_AQUA M2C_BLUE M2C_WHITE
0x00000000, 0x00FF0000, 0x00FFFF00, 0x0000FF00, 0x0000FFFF, 0x000000FF, 0x00FFFFFF
}
```
New values will be linear interpolated between two points when needed.
Assume you initialize a float array
Assume you initialize a float value array indicating temperature Celsius levels.
```cpp
float tempArray[] = { -20, -10, 5, 15, 30, 60, 125 };
```
A temperature of 0°C will be mapped between the 2nd and 3rd element so
between RED and YELLOW.
A temperature between 60°C and 125°C will be mapped between BLUE and WHITE.
**begin()** also allows one to overrule the colours array with a colour array of your choice.
A temperature of 0°C will be between the 2nd and 3rd value so it will be mapped
between the 2nd and 3rd element colour so between M2C_RED and M2C_YELLOW.
Similarly any temperature between 60°C and 125°C will be mapped between M2C_BLUE and M2C_WHITE.
**begin()** allows one to overrule the values and the colours array with arrays of your choice.
Adjusting the colour array allows one to use a "full spectrum" like the default or only
interpolate between two colours. Note the library has several colours predefined as constant
to make the colour table (and the code) more readable. If colours are missing please make a
PullRequest (preferred) or file an issue.
interpolate between two colours.
Note the library has several colours predefined in **m2c_colours.h** as constants to make the
colour table and therefore the code more readable.
If colours are missing please make a PullRequest (preferred) or file an issue.
**begin()** returns false if the array of values is not in increasing order, true otherwise.
**begin()** returns true if the array of values is in non-decreasing order, false otherwise.
If returned false the code might behave in unexpected ways.
Please note that the colourMap can have duplicate entries even side by side.
## Interface
@ -56,19 +68,23 @@ If returned false the code might behave in unexpected ways.
#### Functions
- **map2colour()** constructor.
- **map2colourFast()** constructor, (larger code base, more RAM and faster)
- **bool begin(float \* values, uint32_t \* colourMap = NULL)** load the array with **7**
boundary values and the associated array of **7** colours packed in uint32_t **0x00RRGGBB**.
- **map2colour(uint8_t size = 7)** constructor, default size 7 to be backwards compatible.
- **~map2colour()** destructor.
- **map2colourFast(uint8_t size = 7)** constructor, (larger code base, more RAM and faster)
- **~map2colourFast()** destructor.
- **uint8_t size()** returns the size of the arrays needed (== parameter of constructor).
- **bool begin(float \* values, uint32_t \* colourMap = NULL)** load the array with **size**
boundary values and the associated array of **size** colours packed in uint32_t **0x00RRGGBB**.
If the colour array is not given the last given (or the default) colour array is used.
**begin()** can be called multiple times to change the mapping.
The function returns false if the array of values is not in increasing order.
The function returns false if the array of values is not in non-decreasing order.
- **uint32_t map2RGB(float value)** returns RGB colour packed in an uint32_t **0x00RRGGBB**.
If the value is out of range of the original values array, the value is always mapped upon the first colour.
If the value is out of range of the original values array, the value is always mapped upon the
first or last colour.
- **uint16_t map2_565(float value)** often used 16 bit colour format.
Currently a wrapper around **map2RGB**.
Note: the arrays passed to **begin()** should both have at least 7 elements!
Note: the arrays passed to **begin()** should both have **size** elements!
The colour array can be filled with decimal or HEX values or predefined colours can be used.
See below.
@ -76,7 +92,9 @@ See below.
## Predefined colours
Colours are represented as 24 bit RGB values and have the pattern **0x00RRGGBB**.
Colours are represented as 32 bit .RGB values and have the pattern **0x00RRGGBB**.
In the file **m2c_colours.h** a number of colours are predefined.
| define | value | define | value |
@ -91,45 +109,72 @@ Colours are represented as 24 bit RGB values and have the pattern **0x00RRGGBB**
| M2C_FUCHSIA | 0x00FF00FF | M2C_AQUA | 0x0000FFFF |
Besides these colours, the file contains also GRAY-scale VALUES M2C_GRAY_0 .. M2C_GRAY_16.
More colour definitions can be found on the internet
e.g. https://www.w3.org/wiki/CSS/Properties/color/keywords
Note that only 3 bytes of 4 of the 32 bit colour patterns are used.
The 4th byte might be used in the future.
## Operation
See examples.
By changing the colour map one can get different effects.
The minimum to implement is an intensity effect going from black towards a colour at max intensity.
More complex colour schemes are possible, up to 7 different colours.
This number 7 is hardcoded (for now) and that might change in the future.
The minimum to implement is an intensity effect going e.g. from black towards a colour at max intensity.
For this effect only two values are significant, however one must provide full size arrays.
```cpp
float values[7] = { -200, 200, 200, 200, 200, 200, 200, };
uint32_t colours[7] = { M2C_BLACK, M2C_RED, 0, 0, 0, 0, 0};
```
Note that the above colour scheme maps all colokrs above 200 to BLACK (0).
Another interesting colour scheme could be a symmetric one.
This could indicate 25 as an optimal value (GREEN).
```cpp
float values[5] = { -50, -25, 0, 25, 50, 75, 100};
uint32_t colours[5] = { M2C_BLACK, M2C_RED, M2C_YELLOW, M2C_GREEN, M2C_YELLOW, M2C_RED, M2C_BLACK};
```
More complex colour schemes are possible, up to **size** different colours.
#### Experimental in 0.1.5
#### Non-decreasing array
(was planned for 0.2.0)
(experimental in 0.1.5)
If you create a non-decreasing array of values one can create a break in the colour gradient.
See example.
```cpp
float values[7] = { -200, -90, 0, 45, 45, 150, 180 };
float values[7] = { -200, -90, 0, 45, 45, 150, 180 };
uint32_t colours[7] = { M2C_BLUE, M2C_AQUA, M2C_LIME, M2C_YELLOW, M2C_RED, M2C_YELLOW, M2C_BLUE};
```
With the double 45 in the values array there would be no gradient between the **M2C_YELLOW** and **M2C_RED**
effectively having 2 continuous gradients.
With **45** occurring twice in the values array above there would be no interpolation or colour gradient
between the **M2C_YELLOW** and **M2C_RED** effectively resulting in 2 continuous gradients.
Note: **begin()** will report such array as false.
A slightly less hard edge could be made by changing the second 45 to 46 or 47,
so there is a small area with a very steep gradient.
Note: Since 0.2.0 **begin()** will accept a non-decreasing value array and return true.
This was false in 0.1.5.
## Performance
Indicative performance figures measured with performance example.
Indicative performance figures measured with the performance example.
Performance depends on colours chosen, platform etc.
Note: time in microseconds
Note: UNO at 16 MHz, ESP32 at 240 MHz
#### version 0.1.2
| function call | time UNO | time ESP32 |
@ -152,6 +197,8 @@ Note: UNO at 16 MHz, ESP32 at 240 MHz
#### version 0.1.4
map2colourFast.
| function call | time UNO | time ESP32 | notes |
|:-------------------------|------------:|-------------:|:------------------------|
| begin(values) | 284 | 15 | unexpected peak ESP32 |
@ -164,15 +211,29 @@ Note: UNO at 16 MHz, ESP32 at 240 MHz
One performance optimization (trade memory for speed) is replacing the float division
in map2RGB by a multiplication.
This requires 24 bytes RAM to hold the 6 factors and ~100 bytes of PROGMEM for the
calculation of the dividers in begin().
This optimization is implemented as a derived class **map2colourFast** in version 0.1.4.
This requires (size x 4) bytes RAM to hold the \[size] factors and some ~100 bytes
of PROGMEM for the calculation of the dividers in **begin()**.
The **map2RGB()** call is about 40 % faster compared to the original 0.1.2.
Although the **begin()** call is ~300 us longer, it only takes a dozen **map2RGB()** calls to break even.
Note: the gain for the ESP32 is less pronounced, but can still be interesting.
#### version 0.2.0
map2colourFast, slightly slower compared to 0.1.4.
Note that the larger the size the more time it takes to find the correct interval for the value.
| function call | time UNO | time ESP32 |
|:-------------------------|------------:|-------------:|
| begin(values) | 316 | 22 |
| begin(values, colours) | 332 | 7 |
| map2RGB(value) | 48 - 116 | 1 - 2 |
| map2_565(value) | 52 - 120 | 1 - 2 |
## Future
#### Must
@ -181,24 +242,18 @@ Note: the gain for the ESP32 is less pronounced, but can still be interesting.
#### Should
- redo **begin()** of map2colour to allow all values. (0.2.0)
- non-decreasing array (already experimental in 0.1.5, will still return false! )
- any array of numbers. (return value will always be true then)
- look for optimizations.
- cache last value?
#### Could
- make size configurable ?
- at least smaller than 7 (speeds up)
- ...
- **void adjustColour(uint8_t index, uint32_t RGB)**
- single colour adjust
- faster than calling begin() again
- divfactors need to be calculated again.
- map2RGB variant that gives a colour to the delta with previous value
- user can do that fairly easy => example
- add **reset()** for default array? (RAM)
- create a memory efficient version
- keep a pointer to the colour array.
- split RGB channels for every mapping.
- is this useful? only for smallest RAM devices.
- remove default array and break backwards compatibility.
#### Wont
@ -206,10 +261,28 @@ Note: the gain for the ESP32 is less pronounced, but can still be interesting.
- PROGMEM for default array? ==> slower, AVR specific.
- move up the test for non-increase in **begin()** ==> fail fast.
- conflicts with begin of fast version.
- should a 4th (alpha) channel be enabled?
- user responsibility.
- could a 4th (alpha) channel be enabled?
- not needed yet, would need new constants
- faster 16 bit 565 version?
- only on request as a separate class map2colour565.
- map2HSL() as extra colour space.
- not seen much HSL displays in "arduino" world
- not seen much HSL displays in "Arduino" world
- separate converter solves this.
- add **reset()** for default array?
- takes too much RAM.
- improve the constructor
- add **splitColorMap()**
- only done once so too little gain.
- map2RGB variant that gives a colour as the delta with the previous value.
- user can do that fairly easy => example
- add 3rd param size to **begin()** to allow smaller arrays?
- suppose you allocate size = 20 and want to use only 5 entries.
- create a new object.
- **bool adjustColour(uint8_t index, uint32_t RGB)**
- single colour adjustment
- returns false if index out of range.
- faster than calling **begin()**.
- divfactors need to be calculated again?
- see no real use case.

View File

@ -0,0 +1,57 @@
//
// FILE: map2colour_dynamic.ino
// AUTHOR: Rob Tillaart
// PURPOSE: map2colour demo
// URL: https://github.com/RobTillaart/map2colour
#include "Arduino.h"
#include "map2colour.h"
map2colour mc(12);
// must be in increasing order
float values[12] = { 0, 33, 66, 100, 150, 200, 250, 300, 400, 600, 800, 1024 };
// arbitrary colors
uint32_t colmap[12] =
{
M2C_BLACK, M2C_SILVER, M2C_GRAY,
M2C_WHITE, M2C_MAROON, M2C_RED,
M2C_PURPLE, M2C_FUCHSIA, M2C_GREEN,
M2C_LIME, M2C_OLIVE, M2C_YELLOW
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAP2COLOUR_LIB_VERSION: ");
Serial.println(MAP2COLOUR_LIB_VERSION);
Serial.println();
// load the values array
mc.begin(values, colmap);
// show the interpolating
for (float i = 0; i < 1024; i += 10)
{
uint32_t rgb = mc.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,225 @@
map2colour_performance.ino - map2colourFast
MAP2COLOUR_LIB_VERSION: 0.2.0
begin()
316
332
map2RGB()
16 0.00 FF0000
52 10.00 FF0000
48 20.00 FF0000
52 30.00 FF0000
76 40.00 FF3F00
76 50.00 FF8F00
80 60.00 FFDF00
116 70.00 E8FD00
112 80.00 C3FB00
108 90.00 9DF800
112 100.00 78F600
112 110.00 52F400
116 120.00 2DF100
112 130.00 12F000
108 140.00 25F100
112 150.00 38F200
112 160.00 4BF300
108 170.00 5DF400
112 180.00 70F600
112 190.00 83F700
108 200.00 96F800
112 210.00 A8F900
116 220.00 BBFA00
112 230.00 CEFB00
116 240.00 E1FD00
112 250.00 F3FE00
88 260.00 FFFB00
96 270.00 FFF100
88 280.00 FFE700
92 290.00 FFDD00
88 300.00 FFD300
92 310.00 FFC900
88 320.00 FFBF00
88 330.00 FFB500
92 340.00 FFAB00
92 350.00 FFA100
88 360.00 FF9700
92 370.00 FF8D00
92 380.00 FF8300
88 390.00 FF7900
88 400.00 FF6F00
88 410.00 FF6500
92 420.00 FF5B00
88 430.00 FF5100
92 440.00 FF4700
92 450.00 FF3D00
92 460.00 FF3300
88 470.00 FF2900
96 480.00 FF1F00
92 490.00 FF1500
92 500.00 FF0B00
96 510.00 FF0100
72 520.00 FF0000
72 530.00 FF0000
72 540.00 FF0000
72 550.00 FF0000
72 560.00 FF0000
76 570.00 FF0000
72 580.00 FF0000
72 590.00 FF0000
72 600.00 FF0000
76 610.00 FF0000
72 620.00 FF0000
72 630.00 FF0000
72 640.00 FF0000
76 650.00 FF0000
72 660.00 FF0000
76 670.00 FF0000
72 680.00 FF0000
72 690.00 FF0000
72 700.00 FF0000
72 710.00 FF0000
72 720.00 FF0000
76 730.00 FF0000
72 740.00 FF0000
72 750.00 FF0000
72 760.00 FF0000
72 770.00 FF0000
72 780.00 FF0000
76 790.00 FF0000
76 800.00 FF0000
76 810.00 FF0000
72 820.00 FF0000
72 830.00 FF0000
72 840.00 FF0000
72 850.00 FF0000
76 860.00 FF0000
76 870.00 FF0000
76 880.00 FF0000
76 890.00 FF0000
72 900.00 FF0000
72 910.00 FF0000
76 920.00 FF0000
72 930.00 FF0000
76 940.00 FF0000
76 950.00 FF0000
72 960.00 FF0000
76 970.00 FF0000
72 980.00 FF0000
76 990.00 FF0000
72 1000.00 FF0000
76 1010.00 FF0000
76 1020.00 FF0000
TOTAL: 8636
AVG: 83.84
map2_565()
20 0.00 F800
56 10.00 F800
52 20.00 F800
56 30.00 F800
80 40.00 F9E0
80 50.00 FC60
80 60.00 FEE0
120 70.00 EFE0
112 80.00 C7C0
112 90.00 9FC0
116 100.00 7FA0
112 110.00 57A0
116 120.00 2F80
112 130.00 1780
112 140.00 2780
116 150.00 3F80
112 160.00 4F80
112 170.00 5FA0
112 180.00 77A0
116 190.00 87A0
116 200.00 97C0
112 210.00 AFC0
112 220.00 BFC0
116 230.00 CFC0
120 240.00 E7E0
116 250.00 F7E0
92 260.00 FFC0
92 270.00 FF80
92 280.00 FF20
96 290.00 FEE0
92 300.00 FE80
92 310.00 FE40
96 320.00 FDE0
100 330.00 FDA0
96 340.00 FD40
96 350.00 FD00
100 360.00 FCA0
92 370.00 FC60
96 380.00 FC00
100 390.00 FBC0
96 400.00 FB60
92 410.00 FB20
100 420.00 FAC0
92 430.00 FA80
96 440.00 FA20
100 450.00 F9E0
92 460.00 F980
96 470.00 F940
96 480.00 F8E0
96 490.00 F8A0
96 500.00 F840
108 510.00 F800
76 520.00 F800
76 530.00 F800
84 540.00 F800
76 550.00 F800
76 560.00 F800
76 570.00 F800
80 580.00 F800
80 590.00 F800
76 600.00 F800
76 610.00 F800
84 620.00 F800
76 630.00 F800
76 640.00 F800
76 650.00 F800
76 660.00 F800
76 670.00 F800
76 680.00 F800
76 690.00 F800
76 700.00 F800
76 710.00 F800
76 720.00 F800
84 730.00 F800
80 740.00 F800
76 750.00 F800
80 760.00 F800
80 770.00 F800
80 780.00 F800
76 790.00 F800
80 800.00 F800
84 810.00 F800
76 820.00 F800
80 830.00 F800
80 840.00 F800
80 850.00 F800
80 860.00 F800
76 870.00 F800
76 880.00 F800
76 890.00 F800
76 900.00 F800
80 910.00 F800
80 920.00 F800
76 930.00 F800
76 940.00 F800
80 950.00 F800
76 960.00 F800
76 970.00 F800
76 980.00 F800
76 990.00 F800
80 1000.00 F800
80 1010.00 F800
80 1020.00 F800
TOTAL: 9064
AVG: 88.00
done...

View File

@ -0,0 +1,48 @@
//
// FILE: map2colour_windys_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/map2colour
// https://github.com/RobTillaart/map2colour/issues/9
#include "Arduino.h"
#include "map2colour.h"
map2colour mc(13);
// float windys_values[] = { -70, -55, -40, -25, -15, -8.33, -3.89, 0, 1, 10, 21, 30, 45}; // Celsius
float windys_values[13] = { -94,-67,-40,-13,5,17,25,32,34,50,70,86,116}; // Fahrenheit.
uint32_t windys_colour[13] =
{
0x734669, 0xcaacc3, 0xa24691, 0x8f59a9, 0x9ddbd9, 0x6abfb5, 0x64a6bd,
0x5d85c6, 0x447d63, 0x809318, 0xf3b704, 0xe85319, 0x470e00
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAP2COLOUR_LIB_VERSION: ");
Serial.println(MAP2COLOUR_LIB_VERSION);
Serial.println();
// load the windys arrays
mc.begin(windys_values, windys_colour);
// show the interpolating
for (float i = -100; i < 125; i += 5)
{
uint32_t rgb = mc.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -7,6 +7,8 @@ map2colourFast KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
size KEYWORD2
map2RGB KEYWORD2
map2_565 KEYWORD2

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/map2colour.git"
},
"version": "0.1.6",
"version": "0.2.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=map2colour
version=0.1.6
version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for mapping a float to colour spectrum

View File

@ -0,0 +1,48 @@
#pragma once
//
// FILE: m2c_colours.h
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
// https://www.w3.org/wiki/CSS/Properties/color/keywords
#define M2C_BLACK 0x00000000
#define M2C_SILVER 0x00C0C0C0
#define M2C_GRAY 0x00808080
#define M2C_WHITE 0x00FFFFFF
#define M2C_MAROON 0x00800000
#define M2C_RED 0x00FF0000
#define M2C_PURPLE 0x00800080
#define M2C_FUCHSIA 0x00FF00FF
#define M2C_GREEN 0x00008000
#define M2C_LIME 0x000FF000
#define M2C_OLIVE 0x00808000
#define M2C_YELLOW 0x00FFFF00
#define M2C_NAVY 0x00000080
#define M2C_BLUE 0x000000FF
#define M2C_TEAL 0x00008080
#define M2C_AQUA 0x0000FFFF
#define M2C_GRAY_0 0x00000000
#define M2C_GRAY_1 0x00101010
#define M2C_GRAY_2 0x00202020
#define M2C_GRAY_3 0x00303030
#define M2C_GRAY_4 0x00404040
#define M2C_GRAY_5 0x00505050
#define M2C_GRAY_6 0x00606060
#define M2C_GRAY_7 0x00707070
#define M2C_GRAY_8 0x00808080
#define M2C_GRAY_9 0x00909090
#define M2C_GRAY_10 0x00A0A0A0
#define M2C_GRAY_11 0x00B0B0B0
#define M2C_GRAY_12 0x00C0C0C0
#define M2C_GRAY_13 0x00D0D0D0
#define M2C_GRAY_14 0x00E0E0E0
#define M2C_GRAY_15 0x00F0F0F0
#define M2C_GRAY_16 0x00FFFFFF
// -- END OF FILE --

View File

@ -1,25 +1,54 @@
//
// FILE: map2colour.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.6
// VERSION: 0.2.0
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
#include "map2colour.h"
#define M2C_MIN_SIZE 7
map2colour::map2colour()
map2colour::map2colour(uint8_t size)
{
_size = size;
if (_size < M2C_MIN_SIZE) _size = M2C_MIN_SIZE;
_Red = (uint8_t *)malloc(_size);
_Green = (uint8_t *)malloc(_size);
_Blue = (uint8_t *)malloc(_size);
// for backwards compatibility
uint8_t r[7] = { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF };
uint8_t g[7] = { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF };
uint8_t b[7] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
memcpy(_Red, r, 7);
memcpy(_Green, g, 7);
memcpy(_Blue, b, 7);
}
map2colour::~map2colour()
{
if (_Red) free(_Red);
if (_Green) free(_Green);
if (_Blue) free(_Blue);
}
bool map2colour::begin(float * values, uint32_t * colourMap)
{
if ((_Red == NULL) || (_Green == NULL) || (_Blue == NULL))
{
// need error codes?
return false;
}
// split colour map in channels to allow interpolation per channel
if (colourMap != NULL)
{
for (int i = 0; i < 7; i++)
for (int i = 0; i < _size; i++)
{
uint32_t val = colourMap[i];
_Blue[i] = val & 0xFF;
@ -30,16 +59,21 @@ bool map2colour::begin(float * values, uint32_t * colourMap)
}
}
_values = values;
for (int index = 1; index < 7; index++)
for (int index = 1; index < _size; index++)
{
// catch non increasing values.
float den = _values[index] - _values[index - 1];
if (den <= 0.0) return false;
if (den < 0.0) return false;
}
return true;
}
uint8_t map2colour::size()
{
return _size;
}
uint32_t map2colour::map2RGB(float value)
{
uint8_t index = 1;
@ -50,7 +84,7 @@ uint32_t map2colour::map2RGB(float value)
if (_values[0] < value)
{
if (value < _values[6] )
if (value < _values[_size-1] )
{
// search the interval
while (_values[index] < value) index++;
@ -77,9 +111,9 @@ uint32_t map2colour::map2RGB(float value)
else
{
// out of upper range
R = _Red[6];
G = _Green[6];
B = _Blue[6];
R = _Red[_size-1];
G = _Green[_size-1];
B = _Blue[_size-1];
}
}
uint32_t colour = R;
@ -109,17 +143,25 @@ uint16_t map2colour::map2_565(float value)
//
// DERIVED CLASS
//
map2colourFast::map2colourFast() : map2colour()
map2colourFast::map2colourFast(uint8_t size) : map2colour(size)
{
divFactor = (float *) malloc(size * sizeof(float));
}
map2colourFast::~map2colourFast()
{
if (divFactor) free(divFactor);
}
bool map2colourFast::begin(float * values, uint32_t * colourMap)
{
// load the colour-map and check non-decreasing order.
bool OK = map2colour::begin(values, colourMap);
// pre-calculate dividers
for (int index = 1; index < 7; index++)
for (int index = 1; index < _size; index++)
{
float divider = _values[index] - _values[index - 1];
if (divider > 0)
@ -145,7 +187,7 @@ uint32_t map2colourFast::map2RGB(float value)
if (_values[0] < value)
{
if (value < _values[6] )
if (value < _values[_size-1] )
{
// search the interval
while (_values[index] < value) index++;
@ -170,9 +212,9 @@ uint32_t map2colourFast::map2RGB(float value)
else
{
// out of upper range
R = _Red[6];
G = _Green[6];
B = _Blue[6];
R = _Red[_size-1];
G = _Green[_size-1];
B = _Blue[_size-1];
}
}
uint32_t colour = R;

View File

@ -2,71 +2,37 @@
//
// FILE: map2colour.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.6
// VERSION: 0.2.0
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
#include "Arduino.h"
#define MAP2COLOUR_LIB_VERSION (F("0.1.6"))
#include "m2c_colours.h"
// https://www.w3.org/wiki/CSS/Properties/color/keywords
#define M2C_BLACK 0x00000000
#define M2C_SILVER 0x00C0C0C0
#define M2C_GRAY 0x00808080
#define M2C_WHITE 0x00FFFFFF
#define M2C_MAROON 0x00800000
#define M2C_RED 0x00FF0000
#define M2C_PURPLE 0x00800080
#define M2C_FUCHSIA 0x00FF00FF
#define M2C_GREEN 0x00008000
#define M2C_LIME 0x000FF000
#define M2C_OLIVE 0x00808000
#define M2C_YELLOW 0x00FFFF00
#define M2C_NAVY 0x00000080
#define M2C_BLUE 0x000000FF
#define M2C_TEAL 0x00008080
#define M2C_AQUA 0x0000FFFF
// needed?
// #define M2C_GRAY_1 0x00101010
// #define M2C_GRAY_2 0x00202020
// #define M2C_GRAY_3 0x00303030
// #define M2C_GRAY_4 0x00404040
// #define M2C_GRAY_5 0x00505050
// #define M2C_GRAY_6 0x00606060
// #define M2C_GRAY_7 0x00707070
// #define M2C_GRAY_8 0x00808080
// #define M2C_GRAY_9 0x00909090
// #define M2C_GRAY_10 0x00A0A0A0
// #define M2C_GRAY_11 0x00B0B0B0
// #define M2C_GRAY_12 0x00C0C0C0
// #define M2C_GRAY_13 0x00D0D0D0
// #define M2C_GRAY_14 0x00E0E0E0
#define MAP2COLOUR_LIB_VERSION (F("0.2.0"))
class map2colour
{
public:
map2colour();
map2colour(uint8_t size = 7);
~map2colour();
// values is an array of 7 values in ascending order
bool begin(float * values, uint32_t * colourMap = NULL);
// values is an array of size values in ascending order
bool begin(float * values, uint32_t * colourMap = NULL);
uint8_t size();
uint32_t map2RGB(float value);
uint16_t map2_565(float value);
protected:
uint8_t _size = 7;
uint8_t _size;
float * _values;
// default colours, split up per channel for performance.
uint8_t _Red[7] = { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF };
uint8_t _Green[7] = { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF };
uint8_t _Blue[7] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
// uint8_t _Alpha[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t * _Red;
uint8_t * _Green;
uint8_t * _Blue;
};
@ -79,14 +45,16 @@ class map2colour
class map2colourFast : public map2colour
{
public:
map2colourFast();
// values is an array of 7 values in ascending order
map2colourFast(uint8_t size = 7);
~map2colourFast();
// values is an array of size values in ascending order
bool begin(float * values, uint32_t * colourMap = NULL);
uint32_t map2RGB(float value);
uint16_t map2_565(float value);
private:
float divFactor[6];
float * divFactor;
};

View File

@ -59,7 +59,7 @@ unittest(test_constructor_II)
map2colour mc;
float values[7] = { 1, 2, 3, 4, 5, 6, 7 };
uint32_t colours[7] =
uint32_t colours[7] =
{
M2C_WHITE, M2C_BLACK, M2C_FUCHSIA, M2C_OLIVE, M2C_NAVY, M2C_GREEN, M2C_YELLOW
};
@ -75,7 +75,7 @@ unittest(test_constructor_II)
}
unittest(test_constants)
unittest(test_constants_I)
{
assertEqual(M2C_BLACK ,0x00000000);
assertEqual(M2C_SILVER ,0x00C0C0C0);
@ -96,6 +96,28 @@ unittest(test_constants)
}
unittest(test_constants_II)
{
assertEqual(M2C_GRAY_0 ,0x00000000);
assertEqual(M2C_GRAY_1 ,0x00101010);
assertEqual(M2C_GRAY_2 ,0x00202020);
assertEqual(M2C_GRAY_3 ,0x00303030);
assertEqual(M2C_GRAY_4 ,0x00404040);
assertEqual(M2C_GRAY_5 ,0x00505050);
assertEqual(M2C_GRAY_6 ,0x00606060);
assertEqual(M2C_GRAY_7 ,0x00707070);
assertEqual(M2C_GRAY_8 ,0x00808080);
assertEqual(M2C_GRAY_9 ,0x00909090);
assertEqual(M2C_GRAY_10 ,0x00A0A0A0);
assertEqual(M2C_GRAY_11 ,0x00B0B0B0);
assertEqual(M2C_GRAY_12 ,0x00C0C0C0);
assertEqual(M2C_GRAY_13 ,0x00D0D0D0);
assertEqual(M2C_GRAY_14 ,0x00E0E0E0);
assertEqual(M2C_GRAY_15 ,0x00F0F0F0);
assertEqual(M2C_GRAY_16 ,0x00FFFFFF);
}
unittest(test_compare_RGB)
{
map2colour mc;
@ -105,7 +127,7 @@ unittest(test_compare_RGB)
mc.begin(values);
mcf.begin(values);
int fails = 0;
for (float i = 0; i <= 1024; i++)
{
@ -131,7 +153,7 @@ unittest(test_compare_RGB565)
mc.begin(values);
mcf.begin(values);
int fails = 0;
for (float i = 0; i <= 1024; i++)
{