This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
H4X0RZ's profile picture

Storing 2 colors in one character

Started by H4X0RZ, 09 August 2015 - 02:36 PM
H4X0RZ #1
Posted 09 August 2015 - 04:36 PM
Hi,

KingofGamesYami said something intersting
FYI you can store two colors in a single character/byte, because there are 256 possible characters and 16 * 16 = 256. So, to store text and colors for said text, you'd need only two characters.

Maybe you want to try again using that?

and I wanted to try this out but after some minutes of testing I found a "problem" (I think I just don't have the needed knowledge): When I combine the numbers together there is no way to "reveal" the factors. When factorizing the "output" number, there are multiple results.

For example:

The two numbers are 5 and 6.
When multiplied it is 30.

All the factor pairs I found are:
1,30
2,15
3,10
5,6
6,5
10,3
15,2
30,1

Now, most of them are valid color pairs. How do I get back to my pair of 5 and 6?

I could assign every color pair a specific character, but that would make my code extremely huge.
Edited on 09 August 2015 - 02:38 PM
Lyqyd #2
Posted 09 August 2015 - 04:44 PM
You use four bits for the background and four bits for the foreground.
Lignum #3
Posted 09 August 2015 - 04:47 PM
You're going to need to use bit operations for this:

local colour1 = colours.green
local colour2 = colours.purple

local combined = bit.bor(colour1, bit.blshift(colour2, 16)) --# Shift by 16 because colours are 16 bits wide.

colour1 = bit.band(combined, 0x0000FFFF) --# Get the higher bits.
colour2 = bit.band(combined, 0xFFFF0000) --# Get the lower bits.

print(colour1) --# 8192 (green)
print(colour2) --# 1024 (purple)
Edited on 09 August 2015 - 02:48 PM
Lyqyd #4
Posted 09 August 2015 - 04:52 PM
That's not one character, though. It's awfully wasteful, space-wise. Throwing in a couple of these will get you a number 0-15, which takes up a mere four bits, and is all the information necessary for each color:


math.floor(math.log(clr) / math.log(2))
InDieTasten #5
Posted 09 August 2015 - 05:02 PM
when you assign the colors values of 0-15(using log on the standard colors api for example) you could do this fairly easily which is basically the same like the bit operations, but using "more direct" / faster method.


--#encode
local value = 16*color1 + color2
 
--#decode
local color1 = math.floor(value/16)
local color2 = value % 16 --# modulo evaluating the rest of an integral devision
KingofGamesYami #6
Posted 09 August 2015 - 05:04 PM
Link
Lignum #7
Posted 09 August 2015 - 05:05 PM
That's not one character, though. It's awfully wasteful, space-wise.

True, but everything in Lua is a double anyway, so no harm done. Heck, even the integers in Lua 5.3 would allow this. Unless we're talking about files, in which case, your solution is better.
H4X0RZ #8
Posted 09 August 2015 - 05:22 PM
You're going to need to use bit operations for this:

local colour1 = colours.green
local colour2 = colours.purple

local combined = bit.bor(colour1, bit.blshift(colour2, 16)) --# Shift by 16 because colours are 16 bits wide.

colour1 = bit.band(combined, 0x0000FFFF) --# Get the higher bits.
colour2 = bit.band(combined, 0xFFFF0000) --# Get the lower bits.

print(colour1) --# 8192 (green)
print(colour2) --# 1024 (purple)
That's not one character, though. It's awfully wasteful, space-wise. Throwing in a couple of these will get you a number 0-15, which takes up a mere four bits, and is all the information necessary for each color:


math.floor(math.log(clr) / math.log(2))

Thanks for the help :)/>

when you assign the colors values of 0-15(using log on the standard colors api for example) you could do this fairly easily which is basically the same like the bit operations, but using "more direct" / faster method.


--#encode
local value = 16*color1 + color2

--#decode
local color1 = math.floor(value/16)
local color2 = value % 16 --# modulo evaluating the rest of an integral devision
I think I did something wrong but this code doesn't work.
Bomb Bloke #9
Posted 09 August 2015 - 05:51 PM
I think I did something wrong but this code doesn't work.

I suspect you tried to use the values from the colours API directly, without converting them as you've been shown. The original values are all powers of two - they range from 1 to 32768, and require 16 bits to store. The idea is to first figure out the exponent for each of the colours (using logarithms), then store just those - these exponents range from 0 to 15, and so require 4 bits to store (hence why you can cram two into a byte).

For example, colours.purple is 1024, or 2 to the power of 10 - so rather than attempting to store 1024, you just store 10.

Once you have your two four-bit values, you bit-shift one of them to the right four times, then OR the result with the other value to get your combined figure. To extract the original values, you OR the byte twice - once with 0x0F, and once with 0xF0. The latter you bit-shift to the left four times, and hey presto, you've got your two exponents back - raising 2 to the power of those gives you your original colour values.

Multiplying / dividing by 16 has much the same effect as bit-shifting right / left four times (16 = 2 to the power of 4). InDieTasten's code snippet uses floor / modulo operations in place of OR operations (to trim the excess bits).
Edited on 09 August 2015 - 03:55 PM
H4X0RZ #10
Posted 11 August 2015 - 02:40 PM
It almost works, but there is still a small bug. Not sure if the problem lies in the main code or in the test code though.

Sometimes it draws the image like I expected it to do, but sometimes something like happens:


Anyone has an idea how to fix this?
Bomb Bloke #11
Posted 11 August 2015 - 03:36 PM
\n is character 10, which is equal to the "unified" byte-value of a white foreground with a purple background. So use a different method of storing the image dimensions - for example, writing them as the first two bytes of your file (which'll end up using less space anyway).

You'd also ideally have your save/load functions close their file handles when they're done with them.
H4X0RZ #12
Posted 11 August 2015 - 03:41 PM
\n is character 10, which is equal to the "unified" byte-value of a white foreground with a purple background. So use a different method of storing the image dimensions - for example, writing them as the first two bytes of your file (which'll end up using less space anyway).

You'd also ideally have your save/load functions close their file handles when they're done with them.
Oh, fail. I forgot about the file handles… Thanks for the help :)/>