Converting a hexidecimal string to a floating point array

B

Bushido Hacks

Hey c.l.c++ and/or c.g.a.opengl posters,

How do I convert a hexidecimal string, traditionally used for defining
colors with HTML, into a floating point array?

In other words, how do I convert this:
char* hex = "#FF9933";

into this:

float fpa = { 1.0, 0.6, 0.2 };
 
V

Victor Bazarov

Bushido said:
Hey c.l.c++ and/or c.g.a.opengl posters,

How do I convert a hexidecimal string, traditionally used for defining
colors with HTML, into a floating point array?

In other words, how do I convert this:
char* hex = "#FF9933";

into this:

float fpa = { 1.0, 0.6, 0.2 };

Skip the #, extract the first two hex digits and convert it to
an integer from base-16 string using strtol, divide the integer
by 255. (double constant, don't forget the dot). Then repeat
for the other two pairs of hex digits. Wrap it up in a function
and you get yourself something you can use over and over. Or
you could do it without extracting digits. Just convert the
entire number into a long, then split it into three integers
using / and %, then do the division by 255. like before.

V
 
W

Wolfgang Draxinger

Victor said:
using / and %, then do the division by 255. like before.

division and module are expensive. Better is bitwise masking and
bitshifting. It's strange but I've seen a lot of programs using
division and module for operaions that would have been better
done with bitwise operations. Is there a certain reason other
than ignorance?

Wolfgang Draxinger
--
 
A

abecedarian

Wolfgang said:
division and module are expensive. Better is bitwise masking and
bitshifting. It's strange but I've seen a lot of programs using
division and module for operaions that would have been better
done with bitwise operations. Is there a certain reason other
than ignorance?

Hear, hear! A real expert speaking!
 
J

JB West

Victor Bazarov said:
Skip the #, extract the first two hex digits and convert it to
an integer from base-16 string using strtol, divide the integer
by 255. (double constant, don't forget the dot). Then repeat
for the other two pairs of hex digits. Wrap it up in a function
and you get yourself something you can use over and over. Or
you could do it without extracting digits. Just convert the
entire number into a long, then split it into three integers
using / and %, then do the division by 255. like before.

V

If you are using as a color argument, you may not need to convert to float.
Just parse & pass to OpenGL. void glColor3us( GLushort red, GLushort green,
GLushort blue )


-jbw
 
V

Victor Bazarov

Wolfgang said:
division and module are expensive. Better is bitwise masking and
bitshifting. It's strange but I've seen a lot of programs using
division and module for operaions that would have been better
done with bitwise operations. Is there a certain reason other
than ignorance?

For 255 (256) there probably isn't. For other values there may
not be a simple solution using bit shifts and masks.
 
P

Peter Koch Larsen

Wolfgang Draxinger said:
division and module are expensive. Better is bitwise masking and
bitshifting. It's strange but I've seen a lot of programs using
division and module for operaions that would have been better
done with bitwise operations. Is there a certain reason other
than ignorance?

Well, if you divide i by 128 what expression looks best?

i/128 -or- 1 >> 7 ?

The naïve programmer might prefer the first one, but any expert hacker would
naturally prefer option number 2.

The only problem is that the second option is non-portable whereas the first
is fine - and just as fast on any compiler i've encountered the last 15
years.
So take your poison. Are you a hacker or just a naïve programmer like me?

/Peter
 
B

Bushido Hacks

Gee people. Come'on! IT'S A SIMPLE QUESTION. Im not interested in
doing all this goofy crap right now. I just want to use a simple
straightforward method. I'm not trying to hack the Pentagon.

I want an answer that only uses char, int, double, or float. Not long.
Not short. Not string. And certainly nothing to do with C or Assembly,
or Visual whatever. Just regular ISO standard C++. That's all.

Man. You know what our problem is, we just take thing too literally.
Where as you guys take a ten page list of codes, I could probably
factor into about a page and a half.

And since when did division and mod become expensive operations? I
doubt any of that is true. If they are, why bother using +, -, *, !,
&&, ||, &, |, <, >, == , or even = ?

My only interest in this is to just make a simple OpenGL model using
C++.

I just want to break the string apart into characters. First character
divsible by FF (255) and the second character divsable by F (15) then
add the two digits and assign them to an array of size 3.

But my first road block is to break apart the string. Remember, I want
to use a STRING not an actual hexidecimal.
 
A

Alvin

Bushido said:
Gee people. Come'on! IT'S A SIMPLE QUESTION. Im not interested in
doing all this goofy crap right now. I just want to use a simple
straightforward method. I'm not trying to hack the Pentagon.

I want an answer that only uses char, int, double, or float. Not long.
Not short. Not string. And certainly nothing to do with C or Assembly,
or Visual whatever. Just regular ISO standard C++. That's all.

Man. You know what our problem is, we just take thing too literally.
Where as you guys take a ten page list of codes, I could probably
factor into about a page and a half.

And since when did division and mod become expensive operations? I
doubt any of that is true. If they are, why bother using +, -, *, !,
&&, ||, &, |, <, >, == , or even = ?

My only interest in this is to just make a simple OpenGL model using
C++.

I just want to break the string apart into characters. First character
divsible by FF (255) and the second character divsable by F (15) then
add the two digits and assign them to an array of size 3.

But my first road block is to break apart the string. Remember, I want
to use a STRING not an actual hexidecimal.

The answer has been given. Ignore the #. Read two chars from the string.
Convert those chars into a single number (in base-16...this is important).
Then divide that number by 255. Then convert the resulting number (it will
be a decimal number between 0 and 1) into it's string equivalent.

Alvin
 
P

Peter Koch Larsen

Bushido Hacks said:
Gee people. Come'on! IT'S A SIMPLE QUESTION. Im not interested in
doing all this goofy crap right now. I just want to use a simple
straightforward method. I'm not trying to hack the Pentagon.

I want an answer that only uses char, int, double, or float. Not long.
Not short. Not string. And certainly nothing to do with C or Assembly,
or Visual whatever. Just regular ISO standard C++. That's all.

Man. You know what our problem is, we just take thing too literally.
Where as you guys take a ten page list of codes, I could probably
factor into about a page and a half.

And since when did division and mod become expensive operations? I
doubt any of that is true. If they are, why bother using +, -, *, !,
&&, ||, &, |, <, >, == , or even = ?

My only interest in this is to just make a simple OpenGL model using
C++.

I just want to break the string apart into characters. First character
divsible by FF (255) and the second character divsable by F (15) then
add the two digits and assign them to an array of size 3.

But my first road block is to break apart the string. Remember, I want
to use a STRING not an actual hexidecimal.
That question was answered in Victor Bazarovs reply - so why this post?

/Peter
 
B

ben

The answer has been given. Ignore the #. Read two chars from the string.
Convert those chars into a single number (in base-16...this is important).
Then divide that number by 255. Then convert the resulting number (it will
be a decimal number between 0 and 1) into it's string equivalent.

or simpler: replace "#" with "0x", put it into a stringstream, and read an
int out of it.

ben
 
J

Jack Klein

division and module are expensive. Better is bitwise masking and
bitshifting. It's strange but I've seen a lot of programs using
division and module for operaions that would have been better
done with bitwise operations. Is there a certain reason other
than ignorance?

Wolfgang Draxinger

I would be quite surprised to find a compiler on the market today that
did not do the automatic strength reduction for division or modulus of
an integer type by a constant power of 2. Old 16-bit MS-DOS compilers
from Microsoft and Borland were doing this 15 years ago, for example.

The last one I had to use that would actually generate a division for
this became extinct at least five years ago.

But I admit that I will always verify that a new (to me) compiler does
so, and do the shifts and masks in the source in time critical code if
necessary.
 
M

Martin Steen

Bushido said:
Hey c.l.c++ and/or c.g.a.opengl posters,

How do I convert a hexidecimal string, traditionally used for defining
colors with HTML, into a floating point array?

In other words, how do I convert this:
char* hex = "#FF9933";

into this:

float fpa = { 1.0, 0.6, 0.2 };

Call the function HexColorToFloat like this:

float FloatColor[3];
HexColorToFloat("FF9933", FloatColor);


/**********************************************************************/

#include <iostream.h>

static int Getdec(char hexchar)
{
if ((hexchar >= '0') && (hexchar <= '9')) return hexchar - '0';
if ((hexchar >= 'A') && (hexchar <= 'F')) return hexchar - 'A' + 10;
if ((hexchar >= 'a') && (hexchar <= 'f')) return hexchar - 'a' + 10;

return -1; // Wrong character
}

static void HexColorToFloat(char* HexColor, float* FloatColor)
{
char* HexColorPtr = HexColor;

for (int i = 0; i < 3; i++)
{
int IntColor = (Getdec(HexColorPtr[0]) * 16) +
Getdec(HexColorPtr[1]);

FloatColor = (float) IntColor / 255.0;
HexColorPtr += 2;
}
}


int main(int argc, char* argv[])
{
float FloatColor[3];

HexColorToFloat("FF9933", FloatColor);

cout << "r=" << FloatColor[0] << endl;
cout << "g=" << FloatColor[1] << endl;
cout << "b=" << FloatColor[2] << endl;

return 0;
}
 
K

Karl Heinz Buchegger

Martin said:
static int Getdec(char hexchar)
{
if ((hexchar >= '0') && (hexchar <= '9')) return hexchar - '0';
if ((hexchar >= 'A') && (hexchar <= 'F')) return hexchar - 'A' + 10;
if ((hexchar >= 'a') && (hexchar <= 'f')) return hexchar - 'a' + 10;

Neither in C nor in C++ you have the guarantee that the characters
'A' through 'F' have consecutive code values.

But note: You have that guarantee for the characters '0' to '9'.
 
M

Martin Steen

Karl Heinz Buchegger wrote:

Neither in C nor in C++ you have the guarantee that the characters
'A' through 'F' have consecutive code values.

But note: You have that guarantee for the characters '0' to '9'.

For real?

As long as you use ASCII or Unicode, i suppose this code works. ;)

Best regards, Martin
 
L

Larry I Smith

Bushido said:
Hey c.l.c++ and/or c.g.a.opengl posters,

How do I convert a hexidecimal string, traditionally used for defining
colors with HTML, into a floating point array?

In other words, how do I convert this:
char* hex = "#FF9933";

into this:

float fpa = { 1.0, 0.6, 0.2 };

Here's a couple of example methods:

// hex2rgb.cpp - test some hex to RGB color conversion
// methods.
// compile: g++ -o hex2rgb hex2rgb.cpp
// execute: ./hex2rgb some_hex_string

#include <cstdlib> // for strtoul()
#include <iostream>

// convert a hex color string to three integer RGB values.
// returns zero on success, non-zero on error.
int
hex2rgb(const char * hex, int& red, int& green, int& blue)
{
unsigned long val;

if (NULL == hex)
{
red = green = blue = 0;
return 1;
}

// convert the hex string to an unsigned long int.
// val will be zero if 'hex' is invalid.
// Note: we should check 'errno' after this call
// to see if a conversion error occurred;
// see the docs for strtoul().
val = strtoul(hex, NULL, 16);
red = ((val & 0xff0000) >> 16);
green = ((val & 0xff00) >> 8);
blue = (val & 0xff);

return 0;
}

// convert a hex color string to three float RGB values.
// returns zero on success, non-zero on error.
// Note this is the same as the int version except we
// divide each derived RGB color by 255.0. this method
// could simply call the int version then divide those
// results by 255.0 before returning
int
hex2rgb(const char * hex, float& red, float& green, float& blue)
{
unsigned long val;

if (NULL == hex)
{
red = green = blue = 0.0;
return 1;
}

// convert the hex string to an unsigned long int.
// val will be zero if 'hex' is invalid.
// Note: we should check 'errno' after this call
// to see if a conversion error occurred;
// see the man page for strtoul(),
val = strtoul(hex, NULL, 16);

red = ((float)((val & 0xff0000) >> 16)) / 255.0;
green = ((float)((val & 0xff00) >> 8)) / 255.0;
blue = ((float)(val & 0xff)) / 255.0;

return 0;
}


int
main(int argc, char * argv[])
{
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " hex_value" << std::endl;
return 1;
}

int ir, ig, ib;
float fr, fg, fb;

// get the int RGB values into ir, ig, and ib
hex2rgb(argv[1], ir, ig, ib);

std::cout << argv[1] << ": red = " << ir << " green = " << ig
<< " blue = " << ib << std::endl;

// get the float RGB values into fr, fg, and fb
hex2rgb(argv[1], fr, fg, fb);

std::cout << argv[1] << ": red = " << fr << " green = " << fg
<< " blue = " << fb << std::endl;

return 0;
}


Regards,
Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top