FastLED: rgb2hsv_approximate returns completely wrong color

Hello,

it feels like I found a bug in rgb2hsv_approximate. For most colors it approximates correctly but for some it is completely wrong.

Sample code:

#include "FastLED.h"

void setup() {
  Serial.begin(115200);
  Serial.println("");
  
  CRGB color1 = CRGB(255,153,0);
  Serial.println("rgb: " + String(color1.red) + "," + String(color1.green) + "," + String(color1.blue));
  CHSV color2 = rgb2hsv_approximate(color1);
  Serial.println("hsv: " + String(color2.hue) + "," + String(color2.sat) + "," + String(color2.val));
}

void loop() {
}

Serial output:

rgb: 255,153,0
hsv: 122,255,255

unbenannt

Paint.net says rgb(255,153,0) results in hsv(36,100,100) for 360 degrees which would be hsv(26,255,255) for FastLED if I’m not mistaken. Instead rgb2hsv_approximate returns hsv(122,255,255) in FastLED which is not even closely orange-ish (it’s green).

The code runs on an ESP8266.

Bug or am I just missing something?

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Comments: 15 (4 by maintainers)

Most upvoted comments

This bug still exists:

uint32_t tmp = strtol(colorstring.c_str(), NULL, 16);

Serial.println(tmp);

CRGB tmpcol = CRGB(tmp);

Serial.print(tmpcol.r);   
Serial.print(" ");
Serial.print(tmpcol.g);
Serial.print(" ");
Serial.println(tmpcol.b);

//task-safe write operation to DotPixelXolor as accessing tasks run on different cores
xSemaphoreTake(EffektColorAccess, portMAX_DELAY);
DotPixelColor = rgb2hsv_approximate(tmpcol); //this approximation somehow does not always work! 
xSemaphoreGive(EffektColorAccess);

Serial.print(DotPixelColor.hue);
Serial.print(" ");
Serial.print(DotPixelColor.sat);
Serial.print(" ");
Serial.println(DotPixelColor.val);

Console Output:

Request Col_Set: |#ff8000
16744448
255 128 0
112 255 255

“Request Col_Set” comes from the calling function from before this code, this is printing purely the color string. this string is than converted into an actual number via strtol();

Color codes are OK until the rgb2hsv_approximate. This happens only in for those orange-ish colors. Also, colors close to Hue = 255 are a bit “very” approximated (it returns red all the time untill it suddenly jumps to a purple-ish color)

  • cad435

Edit; I implemented the “rgb2hsv_precise” from @5chmidti and can confirm this works how I expected it to work 😃 Thank you!

Edit2: Out of curiosity I did some measurements. First a FastLED “rgb2hsv_approximate” and than a “rgb2hsv_precise”. At least on the ESP32 the “precise” implementation seems to be 2 times faster than the approximate??

Request Col_Set: |#ffff00
approx: 89us
precise: 29us
Request Col_Set: |#ff0000
approx: 92us
precise: 21us
Request Col_Set: |#00ffff
approx: 65us
precise: 24us

I’ve been looking into this and while I haven’t ‘fixed’ any of the existing functions I’ve added more color accurate conversion functions in the pr linked above.

More info in the pr, but here are the conversions from this thread rerun with the new functions:

r       g       b               h       s       v               r       g       b
56      0       108             192     255     108             55      0       108
48      0       130             185     255     130             45      0       130
41      0       153             181     255     153             39      0       153
34      0       175             178     255     175             32      0       175
34      0       176             178     255     176             33      0       176
17      44      166             163     228     166             18      42      166
0       88      156             147     255     156             0       84      156
0       88      156             147     255     156             0       84      156
0       94      132             140     255     132             0       93      132
0       101     108             131     255     108             0       99      108
0       107     84              118     255     107             0       107     83
0       108     84              118     255     108             0       108     83
4       171     68              101     249     171             5       171     67
9       235     52              93      245     235             10      235     52 // these were problematic 
9       235     52              93      245     235             10      235     52 // but look quite alright here
56      1       108             191     252     108             54      2       108

and from the first post:

r      g      b        h       s       v
255    143    0        25      255     255