# Problem when importing color in hexadecimal format from an ini file

In my game I can import a color correctly when it is in the "engine format".

Example ("color.ini"):

[color]
color1="c_black"
color2="c_green"
color3="c_navy"


These colors were seen in this link:

https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/drawing/colour/index.html

It turns out that I can't import the color when I use its hexadecimal code (only the colors from the previous link don't supply me).

Example ("color.ini"):

[color]
color1="#FA8072"
color2="#FAEBD7"
color3="#E0FFFF"


• I tried lowercase variations, with \$ instead of # and nothing worked.

• It is not even a case of seeing the wrong color, but of changing nothing (it always turns white).

• I am using the function (asset_get_index) to apply the color.

Link where I looked for a solution before coming here:

Code in my game (works in all colors that don't come as hexadecimal):

color[i]=ini_read_string("color","color"+string(i),"");


Draw:

draw_sprite_ext(spr_Barra,0,290,97+25*(i-1),1,1,0,asset_get_index(color[i]),1);


Code I tried, based on one of the comments, from the question:

result=0;

zero=ord("0");
nine=ord("9");
a=ord("A");
f=ord("F");

for(var i=1;i<=string_length(color1);i++){
c=ord(string_char_at(string_upper(color1),i));
result=result<<4;

if (c>=zero && c<=nine){
result=result+(c-zero);
}else if(c>=A && c<=f){
result=result+(c-a+10);
}
}


I used the function (show_debug_message) to see the result of the code and got nonsense results:

• 1024, 2048

Link to see the code base I tried:

• Did you try parsing your hexadecimal code string to a number first, before assigning it to your color array, as described here? – DMGregory Aug 22 '20 at 12:33
• @DMGregory I looked at what you sent, but I still haven't been able to apply it. – Boneco Sinforoso Aug 26 '20 at 0:01
• What did you try? – DMGregory Aug 26 '20 at 0:40
• I copied and adapted the code. The results were numbers. – Boneco Sinforoso Aug 26 '20 at 23:15
• It already was a hexadecimal string — that was the problem. Now you've converted it to a number that the engine can understand natively. Just because it prints as 1024 to display to you, the human, doesn't mean its bits are anything other than 0000 0000 0000 0000 0000 0100 0000 0000 in the computer's memory. – DMGregory Aug 31 '20 at 17:06

I read this article to jog my memory about HEX colour indexing, which is basically a base-16 that can be converted easily to decimal values, used in GMS to create colour values with the make_colour_rgb(r, g, b) function.

The paragraph "Converting Hex to RGB Color Codes" was my main guide through the implementation, as it explains crystal clear how to convert values from hexadecimal to decimal values, grouping them for red, green, and blue values:

• Take the first digit, D, and convert it into decimal. The result is 13.
• Multiply 13 by 16. 13 (16) = 208. This is the partial value.
• Take the second digit, A, and convert it into decimal. The result is 10.
• Add the partial value to the second digit. 208 + 10 = 218.

And so on for all the remaining values. Then I came up with quite a simple implementation:

// Converts a HEX colour value in an RGB map
// INPUT:   string
// OUTPUT:  ds_map["red", "green", "blue"] OR noone
var hex_code = string_upper(string_lettersdigits(argument0));
var rgb_map = ds_map_create();
16 * hex_to_dec(string_char_at(hex_code, 1)) +
hex_to_dec(string_char_at(hex_code, 2)) );
16 * hex_to_dec(string_char_at(hex_code, 3)) +
hex_to_dec(string_char_at(hex_code, 4)) );
16 * hex_to_dec(string_char_at(hex_code, 5)) +
hex_to_dec(string_char_at(hex_code, 6)) );
return rgb_map;


This function takes a string in the format #000000 (including the hash character) and converts it to RGB values stored in a ds_map, and accepts both uppercase and lowercase letters.

The support function hex_to_dec() is used to convert individual HEX values into their decimal counterparts by checking against their ASCII values:

// Converts a HEX value in a decimal number
// INPUT:   string
// OUTPUT:  real
if ( ord(argument0) >= 48 && ord(argument0) <= 57 ) return real(argument0);
if ( ord(argument0) >= 65 && ord(argument0) <= 90 ) return ((ord(argument0) - 65) mod 6) + 10;


This function takes a 1-char string and returns its value in the decimal system, it does the same for letters A-F and loops back (thanks to mod) for other letters (which is a nicer alternative to throwing an exception, in my opinion, despite harder debugging).

There's so much to do to improve this code, but it works fine as a starting point. It's up to you to deal with wrong or missing input, according to your needs.