I'll do my best to be as clear as possible about what I'm trying to do. In short, I'd like to know if a switch statement can check multiple variables simultaneously (I have a feeling it can't, but I'd like to confirm).

If it can't, can someone recommend a way around doing this without doing a million if statements?

I wrote a "Color" class that does all sorts of conversions, and one of the conversions it does is between the HTML standard color words and their corresponding RGB values. I wrote a huge if/else series (since switch statements can't process strings, I believe) that checks the word and if it's one of the HTML words it'll return a map with the RGB values at RGB, RGB, and RGB

Now, I'd like a way to do the opposite...given 3 doubles - R, G, and B...the computer will be able to give the respective word if it exists, otherwise the default would be to 'cout << "The values you gave does not correspond with a color word" << endl;'

I'm hoping for something that would act similar to this:

string Color::RGB2WORD(double R , double G, double B)
{
   switch(R,G,B)
   {
      case 255, 250, 245:
      return "someword";
      ...etc...etc...
   }
}

I feel this *would* be easier to code if it was possible or if there was some similar way to do it, than to write a long series of if statements as the respective if statements would be:

if(R==255 && G==250 && B==245)
   return "someword";
else if(.........................)
....

I feel it'd be easier to work with, and I'm also curious what other suggestions I may get regarding this. I know it's an unusual request to have a switch compare multiple variables, and would be very rarely used, but I like trying something different and seeing what alternatives there are.

If it really comes down to it, I can write the if/else statements. But there are 183 different words to return and if I can simplify it for copy/paste or otherwise just a little bit, it'd be awesome

I guess I *could* write a script that could attempt to automate it though if needed. But it'd be somewhat of a one-time deal and about an hour or so of copy/paste/edit otherwise


PS: Sorry for the rambling above...kind of got off track on some alternatives of my own lol

Cliffs: Looking for (ideally) a switch statement that can compare multiple variables or an alternative (preferably not if/else, as I know it's a viable alternative...but am curious what else may exist, or other ways to?)

Thanks in advance!
-Josh

switches with multiple variables is no supported, just as you thought it might not be. But ... if you convert the rgb values into COLORREF value then you could use that in the switch statement.

switches with multiple variables is no supported, just as you thought it might not be. But ... if you convert the rgb values into COLORREF value then you could use that in the switch statement.

Hmm this seems like it might be able to work. How would I use it in the 'case's though?

And, looking online, it looks like its for Visual C++. Could this work from within linux? If so, what library do I need to include?
(trying now but coming up with "'COLORREF' was not declared in this scope"

Really cool idea though..hadn't heard of this until now.

The class I'm writing converts the following:
RGB
XYZ
Yxy
HunterLab
CIELab
CIELCH
CIELuv
CMY
CMYK
...HEX
...and words

from one to the other, with the exception of HSL or HSV to the others and, so far, with the exception of the others back to words.

I started this somewhat as a self-test, and it's turned into about 2300 lines of code...the longest c++ code i'd written yet

nested switch?

This could work, but with the amount of extra code needed, it'd probably be best to use an if/else than. Good suggestion though

Do you have to deal with each value from 0 to 255 for each color?

I'm using the values of RGB all from 0-255, yes

This helps me convert between the types I listed above.

Currently, the class I'm writing is able to convert, for example. from words to CMYK by going from words to RGB to CMYK and saving the values of CMYK in a map at CMYK, CMYK, CMYK, CMYK. The function, though, would simply be like so:
map<char,double> CMYK = WORD2CMYK("arctic blue");

It also converts all strings/words that are inputted, to lower case and removes all spaces...to help give the user flexibility when inputing the words

It's been fun writing it, though I doubt I'll really use it much (right now, I don't see myself using it). But I feel it's accomplished a bit and I learned a lot about classes. Actually, I wrote it as a namespace (first time using namespaces), so I'd be able to add "using namespace Color;" in a program and wouldn't have to call Color:: many times throughout :)


EDIT: I'll attempt to write an automated script for writing this as a long if/else loop. Doesn't sound too bad and I can use what I've written and copy it to a blank text file, then write it all to another blank text file and continue editing the script until it looks how I want :)

Thanks again everyone!
-Josh

Edited 6 Years Ago by josolanes: n/a

Since you're on Linux, perhaps a Bit Field would work (a bitset probably would too, but I don't know how to use those). Set up 3 unsigned 8-bit fields, then use one field for each color. They would be more portable than a Windows library.

//an example bit field:
union colorNumber {
  unsigned int colorSum;  //provide an integer backbone (generally 32-bits)
  struct {
    unsigned value1  :  8;  //a color value (8 unsigned bits gives 0-255)
    unsigned value2  :  8;  //a color value (8 unsigned bits gives 0-255)
    unsigned value3  :  8;  //a color value (8 unsigned bits gives 0-255)
    //the remaining 8 bits are un-named because they are not used
  };  //close the bit field definitition
};  //close the union

You would use the union just like a class.

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
  //non-pointer example:
  colorNumber myColor;
  myColor.colorSum = 0;  //initialize the color to (0,0,0)/black
  cout << hex << "The current color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;
  cout << "Setting Red to 255..." << endl;
  myColor.value3 = 255;  //set R to 255
  cout << hex << "The new color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;
  cout << "Setting Blue to 255..." << endl;
  myColor.value1 = 255;  //set R to 255
  cout << hex << "The new color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;

  cin.get();
  return 0;
}

You could then set up a switch based on colorNumber::colorSum that uses the Hex values as the case constants.

If you're not familiar w/ bit fields, a quick Google should turn up something.

Edited 6 Years Ago by Fbody: n/a

Since you're on Linux, perhaps a Bit Field would work (a bitset probably would too, but I don't know how to use those). Set up 3 unsigned 8-bit fields, then use one field for each color. They would be more portable than a Windows library.

//an example bit field:
union colorNumber {
  unsigned int colorSum;  //provide an integer backbone (generally 32-bits)
  struct {
    unsigned value1  :  8;  //a color value (8 unsigned bits gives 0-255)
    unsigned value2  :  8;  //a color value (8 unsigned bits gives 0-255)
    unsigned value3  :  8;  //a color value (8 unsigned bits gives 0-255)
    //the remaining 8 bits are un-named because they are not used
  };  //close the bit field definitition
};  //close the union

You would use the union just like a class.

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
  //non-pointer example:
  colorNumber myColor;
  myColor.colorSum = 0;  //initialize the color to (0,0,0)/black
  cout << hex << "The current color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;
  cout << "Setting Red to 255..." << endl;
  myColor.value3 = 255;  //set R to 255
  cout << hex << "The new color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;
  cout << "Setting Blue to 255..." << endl;
  myColor.value1 = 255;  //set R to 255
  cout << hex << "The new color sum is: " << myColor.colorSum << endl;
  cout << dec << "The current RGB is: RGB(" << myColor.value3 << "," << myColor.value2 << "," << myColor.value1 << ")" << endl;

  cin.get();
  return 0;
}

You could then set up a switch based on colorNumber::colorSum that uses the Hex values as the case constants.

If you're not familiar w/ bit fields, a quick Google should turn up something.

That's a pretty cool technique. I'd never used bit fields or similar before. I'll give it a try like this, too. To test myself and see if I can get it to work how I'd like

----------------------------------------------------------------------

Though I, literally, JUST finished writing a parsing script for this. I copy/pasted the original if/else statements into a text file. Then used the script to parse the file and output it to another file as another if/else that works backwards from the first.

Here's the script I wrote:

#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

void parse()
{
    vector<string> WORD;
    vector<int> R,G,B;
    ifstream in("/home/josh/in", ios::binary);
    if(in.is_open())
    {
        for(int count=0; count < 140; count++)
        {
            int r,g,b;
            string word;
            string end;
            in.ignore(40, '\"');
            in >> word;
            for(int i=0; i<word.length(); ++i)
            {
                if(word[i] == ')')
                    word.erase(word.begin()+i);
            }
            for(int i=0; i<word.length(); ++i)
            {
                if(word[i] == '\"')
                    word.erase(word.begin()+i);
            }
            WORD.push_back(word);
            in.ignore(40, '=');
            in >> r;
            R.push_back(r);
            in.ignore(40, '=');
            in >> g;
            G.push_back(g);
            in.ignore(40,'=');
            in >> b;
            B.push_back(b);
            in.ignore(40, ' ');
        }
    }
    in.close();
    cout << WORD.size() << endl;
    ofstream out("/home/josh/out");
    for(int x=0; x<WORD.size(); x++)
    {
        if(x==0)
        {
            out << "if(R==" << R[x] << " && G==" << G[x] << " && B==" << B[x] << ")" << endl;
        }
        else
        {
            out << "else if(R==" << R[x] << " && G==" << G[x] << " && B==" << B[x] << ")" << endl;
        }
        out << "    return \"" << WORD[x] << "\";" << endl;
    }
    cout << "DONE!!" << endl;
    out.close();
}

int main(int argc, char** argv) 
{
    parse();
    return (EXIT_SUCCESS);
}

and a (very small) sample of my original if/else:

map<char,double> Color::WORD2RGB(string word)
{
    map<char,double> RGB;
    if(fixStr(word) == "aliceblue")
    {
        RGB['R'] = 240;
        RGB['G'] = 248;
        RGB['B'] = 255;
    }
    else if(fixStr(word) == "antiquewhite")
    {
        RGB['R'] = 250;
        RGB['G'] = 235;
        RGB['B'] = 215;
    }
    else if(fixStr(word) == "aqua")
    {
        RGB['R'] = 0;
        RGB['G'] = 255;
        RGB['B'] = 255;
    }
    else if(fixStr(word) == "aquamarine")
    {
        RGB['R'] = 127;
        RGB['G'] = 255;
        RGB['B'] = 212;
    }
    //... A LOT MORE else if's...
    else
        cout << "The color you entered does not exist!" << endl;
    return RGB;
}

A small bit of the output after my parse script is run:

if(R==240 && G==248 && B==255)
        return "aliceblue";
    else if(R==250 && G==235 && B==215)
        return "antiquewhite";
    else if(R==0 && G==255 && B==255)
        return "aqua";
    else if(R==127 && G==255 && B==212)
        return "aquamarine";
    //... A LOT MORE else if's...
    else
        return "Color does not exist!";

This is in the class:

string Color::RGB2WORD(int R, int G, int B)

I'll give your way a try to as I'm curious to try it and see how it works

Wait - to Fbody - I just realized that your way may work, without a lot of extra coding on my part...as I already have a function that returns a HEX value from RGB...

However, I have the HEX value returned as a string by the function, and I think I've read that switches can't use strings. Can a HEX be stored as another variable type?

(EDIT: hmm...never used the technique at all that you showed, Fbody. Going to give this a try. May end up being a much nicer way of converting to HEX as well)

Thanks everyone for your help! And Fbody, you kind of got me thinking further here now :)
-Josh


PS: what's the more efficient way of doing this?

i may do some testing (say, tell it to run RGB2WORD function 1000x in the if/else way i have set up vs as HEX in a switch to see which runs quicker. time it using linux's "time" command.

The HEX one would, initially, have a small bit more calculating (converting RGB to HEX), but the switch would then just do a basic comparison. I'm not familiar enough with efficiency to know if and if/else is more or less efficient than a switch...

Edited 6 Years Ago by josolanes: n/a

It should work, here is an example switch based on my previous example:

switch (myColor.colorSum) {
	  case 0xff00ff:  //(255,0,255) in a single hexadecimal
		  cout << "Color RGB(255,0,255) detected in switch..." << endl;
		  break;
	  default:
		  cout << "Color not recognized" << endl;
  }

[edit]
oops.... we overlapped...

I'm not sure which is more efficient. I do know that the way I demonstrated would use fewer resources (i.e. RAM), but I'm not sure about computing time. It uses fewer resources because it's storing the information in only 4-bytes (the size of a single int) as opposed to 6+ bytes (one byte for each char in the string plus overhead). If you have the ability, perhaps you can somehow incorporate it into your class as a member var.

class Color {
  private:  //usually implied, stated for clarity...
    colorNumber myNumber;
    string myName;
  public:
    /*etc......*/
};

Edited 6 Years Ago by Fbody: n/a

Comments
Thanks for all your help! You've helped a lot with different ideas and ways of doing this. Really appreciate it!

Wait - to Fbody - I just realized that your way may work, without a lot of extra coding on my part...as I already have a function that returns a HEX value from RGB...

However, I have the HEX value returned as a string by the function, and I think I've read that switches can't use strings. Can a HEX be stored as another variable type?

(EDIT: hmm...never used the technique at all that you showed, Fbody. Going to give this a try. May end up being a much nicer way of converting to HEX as well)

Thanks everyone for your help! And Fbody, you kind of got me thinking further here now :)
-Josh


PS: what's the more efficient way of doing this?

i may do some testing (say, tell it to run RGB2WORD function 1000x in the if/else way i have set up vs as HEX in a switch to see which runs quicker. time it using linux's "time" command.

The HEX one would, initially, have a small bit more calculating (converting RGB to HEX), but the switch would then just do a basic comparison. I'm not familiar enough with efficiency to know if and if/else is more or less efficient than a switch...

So...regarding if/else and switch efficiency. With a VERY basic test (a simple if/else loop with 11 if's, and a switch with 11 case's)...both with the same integers (0-10) and trying to find a variable "x" with value 10.

I ran them in a for loop up to 100000000 from 0 and the if/else would take 13.4 seconds, on average after 3 runs. And the switch would take 11.9 seconds, on average after 3 runs

That makes some sense, only 1 comparison per situation is required to determine truth as opposed to 4 (1 for each comparison, plus 1 for the if itself).

Edited 6 Years Ago by Fbody: n/a

It should work, here is an example switch based on my previous example:

switch (myColor.colorSum) {
	  case 0xff00ff:  //(255,0,255) in a single hexadecimal
		  cout << "Color RGB(255,0,255) detected in switch..." << endl;
		  break;
	  default:
		  cout << "Color not recognized" << endl;
  }

[edit]
oops.... we overlapped...

I'm not sure which is more efficient. I do know that the way I demonstrated would use fewer resources (i.e. RAM), but I'm not sure about computing time. It uses fewer resources because it's storing the information in only 4-bytes (the size of a single int) as opposed to 6+ bytes (one byte for each char in the string plus overhead). If you have the ability, perhaps you can somehow incorporate it into your class as a member var.

class Color {
  private:  //usually implied, stated for clarity...
    colorNumber myNumber;
    string myName;
  public:
    /*etc......*/
};

Working on switching to your way now :)

My class is starting to take more than the blink of an eye to compile and i've never written something so long that I can actually wait (even a second or two) to compile so I'm going to try and make this more efficient now. Your way seems like it'll be more efficient in a few ways...both in RAM and (in theory) computing time

I realize I'm a little late in this thread. RGB() in windows.h is just a #define and as such you do not need to use any of windows libraries. Just put this in your program. #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) A COLORREF is nothing more than typedef unsigned long COLORREF; So, you could do something like

switch(RGB(20,30,40) )
{
    case RGB(20,30,40):
}

Edited 6 Years Ago by Ancient Dragon: n/a

Comments
I appreciate all your help!! Will try it with COLORREF

It should work, here is an example switch based on my previous example:

switch (myColor.colorSum) {
	  case 0xff00ff:  //(255,0,255) in a single hexadecimal
		  cout << "Color RGB(255,0,255) detected in switch..." << endl;
		  break;
	  default:
		  cout << "Color not recognized" << endl;
  }

[edit]
oops.... we overlapped...

I'm not sure which is more efficient. I do know that the way I demonstrated would use fewer resources (i.e. RAM), but I'm not sure about computing time. It uses fewer resources because it's storing the information in only 4-bytes (the size of a single int) as opposed to 6+ bytes (one byte for each char in the string plus overhead). If you have the ability, perhaps you can somehow incorporate it into your class as a member var.

class Color {
  private:  //usually implied, stated for clarity...
    colorNumber myNumber;
    string myName;
  public:
    /*etc......*/
};

Fbody, I've been trying to learn unions and structs now since your post and I'm starting to grasp the idea, but am having trouble working it into my Class as I'd like. I'll post the relevant code below...

the union, within my namespace Color (sorry, I keep using the words namespace and class interchangeably...):

union colorNumber
    {
        unsigned int hex;
        struct
        {
            unsigned  value1:8;
            unsigned value2:8;
            unsigned value3:8;
        };
    };

The working code for RGB2HEX:

unsigned int Color::RGB2HEX(int R, int G, int B)
{
    colorNumber RGB;
    /*int rgbNum = ((R & 0xff) << 16)
        | ((G & 0xff) << 8)
        | (B & 0xff);
    static string hexDigits = "0123456789ABCDEF";
    string rgb;
    for (int i=(3*2) - 1; i>=0; i--) {
            rgb += hexDigits[((rgbNum >> i*4) & 0xF)];
    }*/
    RGB.value1 = R;
    RGB.value2 = G;
    RGB.value3 = B;
    return RGB.hex;
}

my main.cpp:

#include <stdlib.h>
#include "Color.h"
#include <iostream>

using namespace Color;
using namespace std;

int main(int argc, char** argv) 
{
    colorNumber myColor;
    myColor.hex = 0;
    myColor.value1 = 255;
    myColor.value2 = 0;
    myColor.value3 = 255;
    cout << RGB2HEX(255,0,255) << endl;
    switch(RGB2HEX(255,0,255))
    {
        case 0xff00ff:
            cout << "YES!!" << endl;
            break;
        default:
            cout << "NO!!" << endl;
            break;
    }
    cout << myColor.hex << endl;
    switch(myColor.hex)
    {
        case 0xff00ff:
            cout << "YES!!" << endl;
            break;
        default:
            cout << "NO!!" << endl;
            break;
    }
}

(edit...copied the wrong code above...it's now been corrected!!)
The output is:

2197750015
NO!!
16711935
YES!!

The first number, before "NO!!" changes every time. I'm pretty certain it's because it's a temporary instance of colorNumber that is created within my function RGB2HEX

My question is, is there any way to have it output the hex value like the other one, but so that it can be called without a class instance (since this is a namespace and I prefer not needing an instance)

Thanks in advance. Unions are very different from anything I'd seen before...it was fun playing with that and seeing about them.

I'd still like to use the union/struct example for creating the HEX value if possible as it really helped cut down on my code quite a bit! :)

I realize I'm a little late in this thread. RGB() in windows.h is just a #define and as such you do not need to use any of windows libraries. Just put this in your program. #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) A COLORREF is nothing more than typedef unsigned long COLORREF; So, you could do something like

switch(RGB(20,30,40) )
{
    case RGB(20,30,40):
}

Ah...I was searching for info on it on Google but couldn't come up with that it was a typedef like you described. I'll likely use this in my switch statement as it's really short and simple.

But the HEX conversion still interests me to help streamline some of my code in a separate part of the namespace/class

Thanks for all your help Ancient Dragon and Fbody!!

Edited 6 Years Ago by josolanes: n/a

Can you try to re-post your main()? You re-posted the RGB2HEX code instead of the main(). It may be a good idea to post the relevant portions of the Color class declaration as well...

Edited 6 Years Ago by Fbody: n/a

Can you try to re-post your main()? You re-posted the RGB2HEX code instead of the main()

Oh sorry about that...must have highlighted and skipped the CTRL+C

Here's the main():

#include <stdlib.h>
#include "Color.h"
#include <iostream>

using namespace Color;
using namespace std;

int main(int argc, char** argv) 
{
    colorNumber myColor;
    myColor.hex = 0;
    myColor.value1 = 255;
    myColor.value2 = 0;
    myColor.value3 = 255;
    cout << RGB2HEX(255,0,255) << endl;
    switch(RGB2HEX(255,0,255))
    {
        case 0xff00ff:
            cout << "YES!!" << endl;
            break;
        default:
            cout << "NO!!" << endl;
            break;
    }
    cout << myColor.hex << endl;
    switch(myColor.hex)
    {
        case 0xff00ff:
            cout << "YES!!" << endl;
            break;
        default:
            cout << "NO!!" << endl;
            break;
    }
}

And I think I've got all the really relevant code posted up there now. Really focusing on the RGB2HEX conversion right now. And it relies on the union like you brought up

The RGB2HEX function, otherwise, doesn't rely on anything else from the namespace/class

If there are any parts that aren't clear, though, please let me know and I'll explain or post more code if you think you need it :)

Otherwise, if you'd like to see the code for the whole namespace/class, just let me know and I can offer to send it to you as a zip or separately

doh!! Figured it out. Didn't initialize RGB.hex in the RGB2HEX function

added RGB.hex = 0; after colorNumber RGB; and it works as expected now!

[edit] doh..... LOL, overlapped again... a little more info for you[/edit]

Technically RGB2HEX isn't needed. All you need to do is output the "hex" part of your union directly. A union stores more than 1 variable in the same physical memory location. The unsigned int hex creates a 32-bit "backbone" that the bit field is built on top of. The individual values represent sub-groups of (in this case) 8-bits that are all different parts of the unsigned int. When you store a value for a color, (i.e. R=128) the hex gets updated automatically based on the change, there is no other step required. All you need to do is tell the output stream to show the value as a hexadecimal integer rather than a decimal integer.

/* how a union works */
/*
|               hex                 |	<---union member unsigned int hex
|           bit field struct        |	<---union member, anonymous struct, the bitfield
| unused | value3 | value2 | value1 |       <---structure members, the color values
 00000000 00000000 00000000 00000000	<---the individual bits
*/

You appear to have the correct concept. But I believe you missed a subtlety that I was afraid you would (I thought about it after the fact). On most modern computers, the bit field sections are arranged from right-to-left, not left-to-right.

As a result, value3 is red, value2 is green, and value1 is blue. Change your assignment statements based on that information.

Edited 6 Years Ago by Fbody: n/a

doh!! Figured it out. Didn't initialize RGB.hex in the RGB2HEX function

added RGB.hex = 0; after colorNumber RGB; and it works as expected now!

And I figured out how to cout a number as hex

cout << hex << num << endl;

the above will output the hex equivalent of num

So in my main above I added "hex << " to "cout << hex << RGB2HEX(255,0,255) << endl;" and it did output "ff00ff"

Comments
great, you've been a wonderful "student" to work with, glad I could help

[edit] doh..... LOL, overlapped again... a little more info for you[/edit]

Technically RGB2HEX isn't needed. All you need to do is output the "hex" part of your union directly. A union stores more than 1 variable in the same physical memory location. The unsigned int hex creates a 32-bit "backbone" that the bit field is built on top of. The individual values represent groups of (in this case) 8-bits that are part of the unsigned int. When you store a value for a color, (i.e. R=128) the hex gets updated automatically based on the change, there is no other step required. All you need to do is tell the output stream to show the value as a hexadecimal integer rather than a decimal integer.

/* how a union works */
/*
|               hex                 |	<---union member unsigned int hex
|           bit field struct        |	<---union member, anonymous struct, the bitfield
| unused | value3 | value2 | value1 |       <---structure members, the color values
 00000000 00000000 00000000 00000000	<---the individual bits
*/

You appear to have the correct concept. But I believe you missed a subtlety that I was afraid you would (I thought about it after the fact). On most modern computers, the bit field sections are arranged from right-to-left, not left-to-right.

As a result, value3 is red, value2 is green, and value1 is blue. Change your assignment statements based on that information.

Thanks for the heads up about value3 and value1 being reversed. I didn't realize they were stored from right-to-left as you explained

I've reversed value3 and value1 in my assignments and tested it using an online HEX to RGB calculator and got the correct results now

And I know using RGB2HEX is a little redundant and unnecessary. I'm trying to make it simple to work with in a working program as a simple RGB2HEX(int R, int G, int B) so the user wouldn't need to know what's going on within the class itself

I also use that function within other functions to convert, for example, CMYK to HEX:

unsigned int Color::CMYK2HEX(double C, double M, double Y, double K)
{
    map<char,double> RGB = CMYK2RGB(C,M,Y,K);
    return RGB2HEX(RGB['R'], RGB['G'], RGB['B']);
}

I haven't tested the above code just yet, but I *think* it'll work. Going to test it right now to be sure

Great, glad you figured it out :)

Thank you very much for all of your help. I understand quite a bit more now than I had. I've been learning a lot about c++ in the last few weeks and really like figuring out something that looked alien to me before :)

Coming in late you have colours that you want to convert to different types and formats:

This would normally be a single set of formulae for each conversion and would not require a convert

but if you are pairing names with values and vice versa

couldn't you just use maps
one with key of string and colour value
one with key of the colour you want and string value.


otherwise a single pointer full look up could be implemented if speed is critical

edit: > hmm lots of posts came inbetween when I started and finished this

Edited 6 Years Ago by tetron: that happened fast

Comments
Thanks for the ideas! :)

Coming in late you have colours that you want to convert to different types and formats:

This would normally be a single set of formulae for each conversion and would not require a convert

but if you are pairing names with values and vice versa

couldn't you just use maps
one with key of string and colour value
one with key of the colour you want and string value.


otherwise a single pointer full look up could be implemented if speed is critical

edit: > hmm lots of posts came inbetween when I started and finished this

As far as formulas for converting directly...I was unable to find the formulas for them and found that the converting seems to work fairly well. The most thorough site I found with the conversions was here: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
And it only lists a couple formulas for converting each. However, with these formulas, it's possible to convert to any using another conversion. Not the most efficient, I know for sure, but the values come out accurately in the end and it works pretty quickly. I may, with time, determine a formula for each to convert them directly

As for the maps with the strings and values....that's a really good idea. Simple, and very efficient/fast. I'll change my if/else statements to use this instead. Can't belive i didn't think of this, especially with the heavy usage of maps throughout the rest of the namespace (doh!)

This, paired with the COLORREF typedef and it'll be a quick, simple conversion for much of the namespace. And it'd allow it to work much more efficiently. Very nice idea

This question has already been answered. Start a new discussion instead.