Author Topic: Looking for fast RGBtoHSV() and HSVtoRGB()  (Read 8872 times)

0 Members and 1 Guest are viewing this topic.

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Where can i find a fast C++ functions for RGBtoHSV() and HSVtoRGB(),
where r,g,b and h,s,v are used as integer?

What is the best and fastest C/C++ way to do this conversion in realtime
without using to many muls and divs? Is it possible to speed things
up, by using a precalculated table? Thanks in advance.

- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #1 on: March 09, 2015 »
So I typed "rgbtohsv.c integer" into Google for you :)
This is what I got:
Convert RGB to HSV and back with a micro controller
You're welcome!
What are you working on?
Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #2 on: March 09, 2015 »
Hi,

There's a freebasic example made by Jim on this forum, it uses float but it is easy to scale to integer (255*).

http://www.dbfinteractive.com/forum/index.php?topic=3472.0
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #3 on: March 14, 2015 »
Thanks for the fast feedback and the links, i will take a closer look.

@hellfire:
Thanks for the welcoming.
I am trying to work on some very simple and basic image processing stuff.


@all:
I will try to generate and draw at runtime HSV ColorMaps as ColorBox, ColorWheel, ColorCube as shown in following images, i found on the web:




I know that i have to work with values from 0 to 360 (or with % operator, 0 to 1024). Atm i am not sure to use INT or FLOATS for a fast and best result.
I have to find out, how to draw this and other ColorMap images.





- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #4 on: March 17, 2015 »
Ok, that's actually a lot simpler.
You can keep a table which holds the rgb values of all hues (at full saturation and default brightness).
From there you can go darker, brighter and desaturate (blend to grey).

Actually you don't really need a table as the hue palette is just a linear interpolation between six values:
Code: [Select]
    0  ...  60 ...  120 ...  180 ...  240 ...  300 ...  360/0
(1,0,0), (1,1,0), (0,1,0), (0,1,1), (0,0,1), (1,0,1), (1,0,0)

Since it's 2015 I would generally consider using more than 8bit per color channel.
I doubt that float has any advantage over integer, though.
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #5 on: March 18, 2015 »
@Hellfire:
Thanks for the info and the view of the table and its values.
Just for testing i come up with  following in basic:

Code: [Select]
If CreateImage(0, 380, 255)

    StartDrawing(ImageOutput(0))
   
    r = 255
    g = 0
    b = 0
         
    step1.f =   255 / 60
   
   
    For i=0 To 360
     
      Select i         
         
        Case 0 To 60
          g = g + Int(step1.f)
         
        Case 61 To 120
          r = r - Int(step1.f)
         
        Case 121 To 180
          b = b + Int(step1.f)

        Case 181 To 240
          g = g - Int(step1.f)
         ; b = b + Int(step1.f)
         
        Case 241 To 300
          r = r + Int(step1.f)
         
        Case 301 To 360
          b = b - Int(step1.f)
      EndSelect
     
      Box(i,0,1,255,RGB(r,g,b));
     
    Next
   
   
    StopDrawing() ;

This generates this image (attachement). Atm i am not sure if there is a more efficient way to create this image.

- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #6 on: March 18, 2015 »
Here are my versions, with lighting gradient to black... (i am not sure, if the results compares 1:1 to real hsv colors...

// 320 x 256 Version
Code: [Select]
  If CreateImage(0, 360, 256)
   
    StartDrawing(ImageOutput(0))
   
    r = 255
    g = 0
    b = 0
   
    step1.f =   255 / 60
   
   
    For y = 0 To 255
     
      shade = 255 - y
     
      r = 255
      g = 0
      b = 0
     
      For x=0 To 360-1
       
        Select x         
           
          Case 0 To 60
            g = g + Int(step1.f)
           
          Case 61 To 120
            r = r - Int(step1.f)
           
          Case 121 To 180
            b = b + Int(step1.f)
           
          Case 181 To 240
            g = g - Int(step1.f)
           
          Case 241 To 300
            r = r + Int(step1.f)
           
          Case 301 To 360
            b = b - Int(step1.f)
        EndSelect
       
             
        xr = Int(r) - shade;
        xg = Int(g) - shade;
        xb = Int(b) - shade;
       
        If xr < 0 : xr = 0 : EndIf
        If xg < 0 : xg = 0:  EndIf
        If xb < 0 : xb = 0 : EndIf
         
        Plot (x,255-y, RGB(xr,xg,xb))
       
      Next
     
    Next
   
   
    StopDrawing() ;
   
  EndIf

// 256 x 256 Version

Code: [Select]
If CreateImage(0, 256, 256)
   
    StartDrawing(ImageOutput(0))
   
    r = 255
    g = 0
    b = 0
   
    step1.f =   255 / (256/6)
   
   
    For y = 0 To 255
     
      shade = 255 - y
     
      r = 255
      g = 0
      b = 0
     
      For x=0 To 256-1
       
        Select x         
           
          Case 0 To (256/6)
            g = g + Int(step1.f)
           
          Case (256/6) To (256/6)*2
            r = r - Int(step1.f)
           
          Case (256/6)*2 To (256/6)*3
            b = b + Int(step1.f)
           
          Case (256/6)*3 To (256/6)*4
            g = g - Int(step1.f)
           
          Case (256/6)*4 To (256/6)*5
            r = r + Int(step1.f)
           
          Case (256/6)*5 To (256/6)*6
            b = b - Int(step1.f)
        EndSelect
       
             
        xr = Int(r) - shade;
        xg = Int(g) - shade;
        xb = Int(b) - shade;
       
        If xr < 0 : xr = 0 : EndIf
        If xg < 0 : xg = 0:  EndIf
        If xb < 0 : xb = 0 : EndIf
         
        Plot (x,255-y, RGB(xr,xg,xb))
       
      Next
     
    Next
   
   
    StopDrawing() ;
   
  EndIf
« Last Edit: March 18, 2015 by va!n »
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #7 on: March 18, 2015 »
Atm i am not sure if there is a more efficient way to create this image.
There always is a more efficient way. I doubt that's really necessary here.
I would create the hue gradient only once, so you don't have to re-create it for every scanline.
Afterwards there's little left to optimize...
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #8 on: March 18, 2015 »
@hellfire:
This is my speed optimized working C/C++ version ;-)

Code: [Select]
// Generate HSV ColorTable

r = 255;
g = 0;
b = 0;

for (int i = 0; i < 256; i++)
{
// Calculate HSV colors
if ((i >= 0) && (i <= 41))
g += 6;

if ((i >= 42) && (i <= 84))
r -= 6;

if ((i >= 85) && (i <= 126))
b += 6;

if ((i >= 127) && (i <= 169))
g -= 6;

if ((i >= 170) && (i <= 210))
r += 6;

if ((i >= 211) && (i <= 255))
b -= 6;

// Store color in array
hsvR[i] = r;
hsvG[i] = g;
hsvB[i] = b;
}


// Draw HSV color rect
for (int y = 0; y < 255; y++)
{
for (int x = 0; x < 255; x++)
{
r = hsvR[x] - y;
g = hsvG[x] - y;
b = hsvB[x] - y;

r = (r < 0) ? 0 : r;
g = (g < 0) ? 0 : g;
b = (b < 0) ? 0 : b;

SetPixel(hdc2, 14 + x, 10 + y, RGB( r,g,b) );
}
}

Btw, using hsvR[], hsvG[] and hsvB[] isn't nice, i know! But i dont get it work to use a INT with a RGBA stucture to store any color channel diretly in a 4 byte RGBA pixel.
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #9 on: March 19, 2015 »
You're now using integer steps of 6, this way some parts are 42 and some are 43 entries wide.
And some r,g,b don't reach 255/0.
You can use a simple linear filter with some amount of fixed-point accuracy to solve this:

Code: [Select]
// linear interpolation between the two colors "c1" & "c2" with weight factor "alpha"
// colors are 32bit argb (8 bit per color component, a is unused)
// alpha is 0..256
// alpha=0:    100% c1,   0% c2
// alpha=128:   50% c1,  50% c2
// alpha= 256:   0% c1, 100% c2
inline unsigned int colorLinear(unsigned int c1, unsigned int c2, int alpha)
{
   const int r1= c1 >> 16 & 255;
   const int g1= c1 >> 8 & 255;
   const int b1= c1 & 255;

   const int r2= c2 >> 16 & 255;
   const int g2= c2 >> 8 & 255;
   const int b2= c2 & 255;

   int r= r1 + ((r2-r1)*alpha >> 8);
   int g= g1 + ((g2-g1)*alpha >> 8);
   int b= b1 + ((b2-b1)*alpha >> 8);

   return (r<<16)|(g<<8)|b;
}

void createHueGradient(unsigned int* gradient)
{
   const unsigned int pal[7]= {
      0xff0000,  // red     hue= 0
      0xffff00,  // yellow  hue= 256
      0x00ff00,  // green   hue= 512
      0x00ffff,  // cyan    hue= 768
      0x0000ff,  // blue    hue= 1024
      0xff00ff,  // magenta hue= 1280
      0xff0000   // red     hue= 1536/0
   };

   // interpolate through the above hue gradient with a step size of 6
   // this results in 256 colors

   for (int hue=0; hue<256*6; hue+=6)
   {
     int alpha= hue & 255;
     int index= (hue >> 8);

     *gradient++= colorLinear(pal[index], pal[index+1], alpha);
   }
}

Usage:
Code: [Select]
unsigned int gradient[256];
createHueGradient(gradient);

« Last Edit: March 26, 2015 by hellfire »
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: Looking for fast RGBtoHSV() and HSVtoRGB()
« Reply #10 on: March 24, 2015 »
@hellfire:
Thanks a lot for your fast help, the source and how to use itl
I will take a closer look, to understand it in any part and try to implent your version.
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won: