Dark Bit Factory & Gravity
PROGRAMMING => C / C++ /C# => Topic started 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.
-
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?
-
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
-
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)
-
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:
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.
-
@Hellfire:
Thanks for the info and the view of the table and its values.
Just for testing i come up with following in basic:
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.
-
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
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
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
-
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...
-
@hellfire:
This is my speed optimized working C/C++ version ;-)
// 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.
-
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:
// 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:
unsigned int gradient[256];
createHueGradient(gradient);
-
@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.