How can I save a string containing 144 color3 to datastore?

I am working on an art / pixelart game which will let players save finished work. I have tried encoding the grid of 12x12 pixels into a string:

But am very confused how I would go about saving this, Should I go about creating binary code instead? then encoding and decoding when the player loads data?

Has anyone who has made games with drawing saving got any ideas?

The string is not in numerical order btw

Maybe you could save a table in the following format:

{
    {(int) R, (int) G, (int) B},
    {(int) R, (int) G, (int) B},
    {(int) R, (int) G, (int) B},
}

Well firstly I’d recommend putting it into numerical order and then serializing it to save it. If you don’t put it into numerical order then I guess you can arrange the dictionary by using some simple string splitting, all though that may prove difficult unless you use some sort of escape character like / to separate the string to something like such:

1 23,255,255 / 5 225, 255, 255 / 3 102, 33, 0 /

However, I believe it’d be easier to simply get it into numerical order and remove the number entirely so that way you’ve got a shorter string to be saved, something like such:

23,255,255,3,102,33,225,255,255

If you choose, you can still use the back slash to separate it however this will only help with visual clarity unless you make a function to find values based from slash to slash.

I wouldn’t recommend turning it into binary as you don’t have exact memory management in lua(u), plus the fact that if you did you’d just end up limiting the colour palate.

Well string.char supports numbers from 0-255. Maybe you could encode each number as a character? E.g.

local colors = {
    {256, 233, 100},
    {233, 99, 45}
}

local finalString = ""
for _, color in pairs(colors) do
    for _, component in pairs(color) do
        finalString ..= string.char(component)
    end
end

Color3:ToHex() and Color3.fromHex() can represent and decode a Color3 in just six hex characters, compared to the up to 11 that your r:g:b scheme encodes it in. The drawback is that it can’t represent the funny out-of-range colors :’(
Replace your color string format with ToHex to cut down on size massively without changing any other code.

In addition, you can turn the list into a string directly instead of letting JSONEncode turn your nice array into a mess.

local color3s = { -- pretend this has your 144 Color3s in it
	Color3.new(1, 0, 0),
	Color3.new(1, 1, 0),
	Color3.new(0, 1, 0),
	Color3.new(0, 1, 1),
}

local function Color3ArrayToString(tbl)
	local rope = {} -- pieces of string
	for _, color in ipairs(tbl) do
		table.insert(rope, color:ToHex()) -- hopefully guaranteed to return RRGGBB instead of RGB
	end
	return table.concat(rope) -- combine all of them into one string
end

local function StringToColor3Array(str)
	local tbl = {}
	for hex in string.gmatch(str, "......") do -- take 6-character pieces of the string
		table.insert(tbl, Color3.fromHex(hex))
	end
	return tbl
end

print(game.HttpService:JSONEncode(Color3ArrayToString(color3s)))
print(game.HttpService:JSONEncode(Color3ArrayToString(StringToColor3Array(Color3ArrayToString(color3s)))))

Be warned that you’re designing a file format. If you push just this (144 raw pixels) to the datastores, then you might risk invalidating older saves if you change the encoder or decoder. JSON is big and ugly, but at least it’s extensible - in the future, if you ever want a different canvas size, you can add a width and height value somewhere in the json and assume it’s 12 if it’s missing and all is good. But this is just a big blob of pixels that you have to be careful not to add anything else to.

(To anyone else reading this: no, you probably can’t compress this into 3 bytes instead of 6 because JSONEncode and possibly others refuse to encode it)

2 Likes

use tables.
make a 3d array

  • have 12 arrarys in an array (1 for each line)
  • have 12 arrays in each of those arrays (for each color3 value)
local Page = 
	{
		{{255,255,255},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}},
		{{},{},{},{},{},{},{},{},{},{},{},{}}
	}

store your values as shown and then save the whole thing to the data store.

alternatly you could use string handling taking the value of all 144 pixels and concatingating them with a “_” inbetween them perhaps and then saving that string to the datastore this means the picture will be saved in a big serial line that you can split apart and assign each pixel its colour when they want it

if this doesnt make sense feel free to ask questions because i just threw this answer together.

1 Like

Thank you everyone who replied, I will be trying all your suggested methods :slight_smile: