2026-09-27 11:37
PNG encoding.
I wanted to encode arbitrary files into png and back, useful for uploading to file hosts that only allow images. My first script was quite simple, embed the file data as a 1xn black and blue image (since I didn't to handle varying filesize). I capped it at 9kb, because I've seen 12000x9000 as the largest image dimensions on a phone's pic.
Once that was coded, I wanted to use all the colours in PNG. When encoding, I used $data[$i]??0 to handle files that aren't a multiple of 3 bytes, and used the image's width to encode the offset to strip on decoding. This took a bit more time, as I had to use imagegd's colour functions on decode, and ensure that the data was decoded in the right order.
I extended the allowed size to 90kb, before dropping it to 60kb (partly to change the filesize in my code, as it was coincidentally a multiple of 3. This helped me find and fix some bug).
Later, I wanted to have the script fully use the both dimensions of the image. I used rounded square roots, with clearance for extra code. I then encountered trickier problems, like the code skipping pixels. ensuring the loop's offset is a multiple of 3 fixed that. However, the decoder would give corrupt data, so thru trial and error, I made fixes and eventually got it working. Once working, I saw a lot of "0" bytes. my script removes them with substr, and the offset is encoded into the bottom right pixel.
I relaxed the filesize restriction, fixing random size changes by reading the green (and later red) values of that bottom right pixel. I coded a public interface (storing the filename in a metadata file), so anyone can encode/decode files with it, without needing a local copy of php. After seeing the encoder link posted in the chat, where many people could've clicked on it, I realised I need to add caching, so my server doesn't re-encode the same file on each load. The cache used to auto purge if 1 hour had passed (tho that was removed coz I access it randomly).
Audio encoding
After finishing PNGFileSwap, I wanted to do audio. For a while, I was stumped (php doesn't have audio encoding libraries), however, I discovered that ffmpeg can handle pcm (raw data). I searched online, and after trying a bit (initially it errored, then gave corrupt data on decode), got it to encode and decode signed 8 bit pcm.
Checking the encoded file in a terminal, I found it looks too much like the original, and 16bit encoding made ffmpeg realise that a byte is missing.
After eventually getting it to work on the site (I had to troubleshoot, change filenames, etc), I discovered that it doubled the filesize somehow, while 16 bit encoding hardly changed the size. To avoid ffmpeg dropping a byte on encoding, I had to put an extra byte in.
When decoding, I'll need to remove the extra byte if it existed... so I needed to embed a bit of metadata in the file. I couldn't easily find a way to decode comments in ffmpeg (*encoding* looked easy), so embedded 'busbarqQ' or 'barbusqQ' into the end of the encoded file, so my script can decode it. As a bonus, it can avoid working with files it didn't encode (unless someone crafts the string manually).
The decoder then broke, and I discovered my script needs to always check how many bytes to remove, regardless of cache status, fixed that and I think it's done.