DEV Community

loading...
Cover image for ๐Ÿ“pong๐Ÿ“ - fully playable, hidden inside a 24px by 24px image ๐Ÿ˜Ž [hiding text and code in images]

๐Ÿ“pong๐Ÿ“ - fully playable, hidden inside a 24px by 24px image ๐Ÿ˜Ž [hiding text and code in images]

InHuOfficial
Specialising in accessibility and website load speed / performance. If you have a question about [accessibility] or [page-speed-insights] ask away and I will help any way I can!
ใƒป3 min read

Sometimes you just have to set yourself silly challenges to help you learn. And this is one of those.

I wanted to see how tiny I could make an image and hide an entire game inside it!

So I set about writing my own (very rudimentary) steganography library.

If you aren't familiar with steganography it is the practice of hiding text, images or audio within an image or video.

This is normally done with clever bit flipping - but I am too smol brained for that!

Instead I realised I could use the alpha channel to encrypt data.

As the alpha channel on an image (the transparency) has 255 options that gives lots of ways to encrypt the data.

Demonstration

In the fiddle below there are 3 stages for encryption and a fourth for decryption.

Step 1 - grab the image we want to encode our data into

In the first step we simply load an image in.

I have already included the InHu logo (which is large enough to contain the whole of jQuery!) but you can choose your own image if you want.

You can also change the text you want encrypting by entering it in the textarea (by default it is a code-golfed version of pong!)

Step 2 - resize the image as small as possible.

In the second step you choose the "depth" we can encode.

This is essentially how visible the transparency is (how much information we store per pixel).

More simply it is a strange implementation of converting numbers to a given Base. So 2 is essentially binary (but using 1 and 2 for the bits) and 16 is essentially hexadecimal but using numbers 1-16 instead of numbers and letters.

A low number (e.g. 2) will require a larger image to encrypt the data but the transparency will be much lower.

A high number (e.g. 16) will require a smaller image but you may see the transparency,

So high numbers for smaller images but more likelihood of being noticed.

I recommend setting this to "8" as it is not noticeable on most images but still results in small image outputs.

There is also a checkbox for using the full ASCII table if you want to use special characters. I would leave this unchecked at first.

Once you have entered your preferences click "Calculate the smallest image size we can use".

This will then resize the original image to the minimum size possible to contain the information.

Step 3 - encode the data

Click the "Encode" button to generate the final image.

Here you can see if there are any visible differences between the two images. If there are then you can go back a step and lower the number a bit.

Step 4 - decode the image

If you click "Decode" you should see a fully playable version of pong appear below (assuming you haven't changed the text in the textarea! If you have then you should see your text repeated below)

Controls are Q and A for player 1 and P and L for player 2. Have fun!

Want to see the whole of paradise lost in an image?

I will warn you - the processing on this takes quite a while! You might not want to do this if you are on a mobile!

View the whole of paradise lost as part of a JS fiddle here (It takes a while to load so I didn't include it inline in the article)

Conclusion

A fun experiment indeed - there are loads of things we could do better - character maps instead of adding each character would reduce large files size significantly. Ironically though it made pong larger!

Obviously for those of you who know about steganography, this is normally done with bit flipping, but I though the opacity channel was an interesting alternative as instead of a max of 3 bits per pixel (red, green and blue) we get up to 255 bits of information per channel (obviously we can't use all 255 and maintain a reasonable image), but I decided 16 bits was the max!

It was fun trying to work out how to have a flexible base for encoding (it works for base2,3,4,5,6....14,15,16...etc.), there are probably much better ways to do it though!

Anyway, I hope you enjoyed this silly post!

p.s. the original Pong code was taken from this stack overflow answer

Discussion (6)

Collapse
theowlsden profile image
Shaquil Maria

Back again with the crazy experiments. At this point, you're a mad scientist๐Ÿ‘จโ€๐Ÿ”ฌ๐Ÿคฃ

Do you have a GitHub repo with these experiments?

Collapse
inhuofficial profile image
InHuOfficial Author

No but when the site goes live they will all be available for download. To be fair the entirety of the code is in the jsfiddle for this one so you can just grab that!

Collapse
theowlsden profile image
Shaquil Maria

Noted, will keep an eye open for that.

To be fair the entirety of the code is in the jsfiddle for this one so you can just grab that!

True enough, but I asked because I think that would be easier to access at a later point, but the site will do exactly that.

Thread Thread
inhuofficial profile image
InHuOfficial Author

Yeah that is probably true for a few of my random posts, I might squeeze some time out to at least make them gists.

I will see how I get on with the site as it is taking forever to build!

Collapse
inhuofficial profile image
InHuOfficial Author • Edited

I did contemplate fitting "war and peace" into an image, but my poor computer would set on fire with my crappy implementation, hence why I went for paradise lost instead ๐Ÿคฃ๐Ÿคฃ

With that being said, with maximum "compression" (16 on my scale) I worked out that war and peace could fit into an image 2400px by 1500px with room to spare!

Collapse
rishitkhandelwal profile image
Rishit Khandelwal

Fascinating!

Forem Open with the Forem app