Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: va!n on March 06, 2015

Title: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n on March 06, 2015
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.

Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: hellfire on March 09, 2015
So I typed "rgbtohsv.c integer" into Google (http://www.google.com) for you :)
This is what I got:
Convert RGB to HSV and back with a micro controller (http://www.ruinelli.ch/rgb-to-hsv)
You're welcome!
What are you working on?
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: Rbz 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
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n 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.

(http://www.jentronics.com/NewColor/hsv.jpg)

(http://www.normankoren.com/HSVcolors.jpg)

(http://krazatchu.ca/wp-content/uploads/2012/01/hsv-rgb.jpg)
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: hellfire 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.
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n 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.

Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n 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
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: hellfire 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...
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n 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.
Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: hellfire 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);

Title: Re: Looking for fast RGBtoHSV() and HSVtoRGB()
Post by: va!n 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.