Simple Color3 -> String, String -> Color3

Whether you’re trying to store colors in your data stores efficiently,

ColorStore:SetAsync("0, 0, 255")

or using RichText to color parts of your text,

'<font color="rgb(127, 0, 255)">GFink: </font>Hello world!'

you find yourself needing to convert a Color3 value to an RGB string value.

You’re trying to do this: Color3.new(0.5, 0, 1)"127, 0, 255"

Conversely, if you’re loading that RGB string value from a data store, or trying to extract the Color3 value out of a RichText string with colored text, you will need to convert that string value into an Color3 value.

That’s just the inverse operation: "127, 0, 255"Color3.new(0.5, 0, 1)

If you look around for an easy way to do these operations, you stumble upon help threads with solutions that look like this:

That’s all well and good as long as they work, but to me it just looks a bit wordy/repetitive. You gotta repeat yourself three times for the three RGB channels.

Here is a Color3RGB string function which does the same thing as the verbose functions, but doesn’t repeat itself:

local function Color3toRGBstring(color3)
	return string.gsub("R,G,B", "%u", function(channel)
		return tostring(math.round(color3[channel] * 255))
	end)
end

Sidenote: coincidentally, %u would also be appropriate here if this operation was done using the triple string.format substitutions — string.format("%u, %u, %u", tostring(math.round(etc * 255)), etc..) where %u here signifies positive integers

Here is a single-line RGB stringColor3 function which also doesn’t repeat itself:

local function RGBstringToColor3(RGBstring)
	return Color3.fromRGB(unpack(string.split(RGBstring)))
end

Luckily, the messy "255 ", "127 " strings with spaces automatically get converted to numbers during the fromRGB operation

That second function is courtesy of @D0RYU:

Roblox uses split.string with the comma as a separator by default, so we can make ours even shorter :^)


If you have a way of simplifying these functions even further, that would be very cool to see, so please respond!
7 Likes

I’ll also add that it’s more efficient still to convert your Color3 values to hexadecimal rather than comma-separated RGB values, just in terms of having the lowest possible number of characters in a data store. You can use hexadecimal for RichText colors as well.

Here are the functions done with hex values:

local function Color3toRGBhex(color3, includePrefix: boolean?)
	return (includePrefix and "#" or "") .. string.gsub("RGB", "%u", function(channel)
		return string.format("%02X", math.round(color3[channel] * 255))
	end)
end

local function RGBhexToColor3(RGBhex)
	local RGBdec = {}
	for hex in string.gmatch(RGBhex, "%x%x") do
		table.insert(RGBdec, tonumber(hex, 16))
	end
	return Color3.fromRGB(unpack(RGBdec))
end

Here’s what the includePrefix parameter does:

Color3toRGBhex(Color3.fromRGB(255, 0, 127), true)"#FF007F"

Without it, there’s no hashtag/pound sign prefix:

Color3toRGBhex(Color3.fromRGB(255, 0, 127))"FF007F"

ChatGPT helped with the string patterns.

I wish RGBhexToColor3 could be a little more compact.

3 Likes

I will add that Color3 has builtin hex support:

local red = Color3.new(1, 0, 0)

local red_in_hex = red:ToHex()
local new_red_color = Color3.fromHex(red_in_hex)

Color3.ToHex
Color3.fromHex

6 Likes

I actually didn’t know this :sweat_smile: almost defeats the purpose of this whole thread since hex can be used basically anywhere that the regular RGB values can, but I will keep it up since it can serve as a central place for people to read and discuss this conversion stuff

Here’s an example of color encoding with RichText using Color3 vs. Hex:

Color3:

<font color="rgb(127, 0, 255)">GFink: </font>Hello world!

Hex:

<font color="#7F00FF">GFink: </font>Hello world!

Both look like this:

3 Likes