My recent project on how to turn nearly any file into an image file.

avatar
(Edited)

Hello Everyone!

How to encode files as RGB values and create image files that can later be reconstructed back into the original file.

Hello Everyone!

These are a few projects that I have been working on and wanting to share with everyone.

In short, I was looking for a way to have files stored as images (sans stenography) and I think that the method that I landed on works rather well even though it currently lacks any error correction. I also feel confident that 'brighter minds than mine' will figure that part out if the technology proves itself useful. It is also worth noting that, images uploaded to many places undergo some kind of compression and I have yet to see how well the png files work after undergoing such treatment.

So far I have given it the same sort of stress test that I gave most of my QR code projects by seeing if the system can load the png files into the browser, create blob urls for them and then load v86 and linux. As tricky as that might sound it was rather straight forward and worked a heck of a lot better than I thought that it would.

At which point I pivoted to seeing if I could also get it to work with 'node.js' with the caveat of making the browser based v86 files work with 'node.js'. In the end I got it to work by sort of 'black holing' all the calls the v86 makes (for audio and such) and then porting the output to a serial port.

In regards to the file to image encoding pipeline goes, it is essentially just gzipping the data, urlsafe base64 encoding the data, mapping urlsafe base64 to RGB values, forming the values into a list... and then turning the list into a square so that it is an image. If (during the encoding process) the bytes are not perfectly divisible (by three) it adds some padding which appear as black pixels. Then at the very end a 'length anchor' is stored so the length of the base64 string is discover-able during the decoding process after the padding has been stripped.

The repository's readme has not been updated to reflect the latest encoder/decoder script's logic but it now adds metadata and can always recreate the original file name no matter what the png file gets renamed to. I also streamlined the encoding/decoding pipeline for batch processing files in a directory instead of the single file process used by the earlier version.

Thus far, I have only encountered problems with some types of binary files but my work around for those is to either nest the binaries inside JSON or squashfs them and stick the entire squashfs (as an encoded string) inside of JSON and that works too. Some binaries might work with the encoder just by compressing them first with traditional compressors (like gzip) but I have yet to tinker with that too much after a few initial failures with that approach.

In the example below I will provide the latest version of the 'file to png' script because I think that it is a bit more polished and with the metadata acting as a file name fail-safe... it is hard to recommend the older methodology.

What started as a clever way to pass any kind of file that I want to, to an LLM (capable of decoding it) while other LLM(s) dismiss it as 'noise' lead me down quite the rabbit hole so I hope that someone enjoys the fruits of my efforts!

The following python script can be found here.


pixelator-standalone-full.py


import gzip
import base64
import os
import numpy as np
from PIL import Image
import math
import struct
import json
import hashlib
import sys

class IronVaultUltimate:
    def __init__(self):
        self.prefix = "MASTER_DNA_SEED_"
        self.output_ext = ".png"

    def _calculate_checksum(self, data):
        """Generates a SHA-256 hash of the data for integrity verification."""
        return hashlib.sha256(data).hexdigest()

    def encode_batch(self, input_dir="pixelate", output_dir="pixelated"):
        """Converts files in input_dir into data-embedded PNGs in output_dir."""
        if not os.path.exists(input_dir):
            os.makedirs(input_dir)
            print(f"[*] Created '{input_dir}/' folder. Place files there and run again.")
            return

        os.makedirs(output_dir, exist_ok=True)
        files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
        
        if not files:
            print(f"[!] No files found in '{input_dir}' to encode. Skipping.")
            return

        print(f"\n--- PHASE 1: ENCODING (Source: {input_dir}) ---")
        
        for filename in files:
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, f"{self.prefix}{filename}{self.output_ext}")
            
            print(f"[+] Encoding: {filename}")
            
            with open(input_path, "rb") as f:
                raw_data = f.read()

            checksum = self._calculate_checksum(raw_data)
            metadata = {
                "filename": filename,
                "checksum": checksum,
                "size": len(raw_data)
            }
            metadata_json = json.dumps(metadata).encode('utf-8')
            compressed_data = gzip.compress(raw_data)

            # Package structure: [Header Len] + [Header] + [Data]
            header_len_bin = struct.pack(">I", len(metadata_json))
            payload = header_len_bin + metadata_json + compressed_data
            
            b64_str = base64.urlsafe_b64encode(payload)
            # Precision Anchor at the very end
            final_data = b64_str + struct.pack(">I", len(b64_str))

            padding = (3 - len(final_data) % 3) % 3
            padded_data = final_data + b'\x00' * padding
            pixels = np.frombuffer(padded_data, dtype=np.uint8).reshape(-1, 3)
            
            side = int(math.ceil(math.sqrt(len(pixels))))
            vram = np.zeros((side * side, 3), dtype=np.uint8)
            vram[:len(pixels)] = pixels
            
            Image.fromarray(vram.reshape((side, side, 3))).save(output_path)
            print(f"    Success: Created {os.path.basename(output_path)}")

    def decode_batch(self, input_dir="pixelated", output_dir="pixelated_done"):
        """Converts PNGs in input_dir back into original files in output_dir."""
        if not os.path.exists(input_dir):
            print(f"[!] Input directory '{input_dir}' not found. Skipping.")
            return

        os.makedirs(output_dir, exist_ok=True)
        files = [f for f in os.listdir(input_dir) if f.endswith(self.output_ext) and f.startswith(self.prefix)]

        if not files:
            print(f"[!] No valid IronVault PNGs found in '{input_dir}'. Skipping.")
            return

        print(f"\n--- PHASE 2: DECODING (Source: {input_dir}) ---")

        for png_file in files:
            img_path = os.path.join(input_dir, png_file)
            print(f"[+] Analyzing: {png_file}")
            
            try:
                img = Image.open(img_path).convert('RGB')
                raw_bytes = np.array(img).flatten().tobytes()
                
                clean_bytes = raw_bytes.rstrip(b'\x00')
                total_b64_len = struct.unpack(">I", clean_bytes[-4:])[0]
                
                b64_payload = clean_bytes[:total_b64_len]
                binary_blob = base64.urlsafe_b64decode(b64_payload)
                
                header_len = struct.unpack(">I", binary_blob[:4])[0]
                metadata_json = binary_blob[4:4+header_len]
                metadata = json.loads(metadata_json.decode('utf-8'))
                
                compressed_data = binary_blob[4+header_len:]
                restored_data = gzip.decompress(compressed_data)
                
                new_checksum = self._calculate_checksum(restored_data)
                status = "BIT-PERFECT VERIFIED" if new_checksum == metadata['checksum'] else "!!! DATA CORRUPTED !!!"

                output_path = os.path.join(output_dir, metadata['filename'])
                with open(output_path, "wb") as f:
                    f.write(restored_data)
                
                print(f"    Restored: {metadata['filename']} | {status}")
                
            except Exception as e:
                print(f"    [!] FAILED to process {png_file}: {e}")

# --- AUTO-SENSING COMMAND CENTER ---
if __name__ == "__main__":
    vault = IronVaultUltimate()
    
    print("==============================")
    print("    IRON VAULT ULTIMATE v3    ")
    print("==============================")
    
    # Logic for automatic execution
    if len(sys.argv) > 1:
        # User provided a flag
        cmd = sys.argv[1].lower()
        if cmd in ['e', 'encode']:
            vault.encode_batch("pixelate", "pixelated")
        elif cmd in ['d', 'decode']:
            vault.decode_batch("pixelated", "pixelated_done")
        else:
            print(f"Unknown flag '{cmd}'. Use 'encode' or 'decode'.")
    else:
        # NO FLAG PROVIDED: Do both automatically
        print("[*] No flags provided. Running FULL VAULT CYCLE (Encode + Decode)...")
        vault.encode_batch("pixelate", "pixelated")
        vault.decode_batch("pixelated", "pixelated_done")
        print("\n--- ALL TASKS COMPLETE ---")

Now for the fun part! Here is a simple standalone html page to load the png files, assign them blob urls and then launch V86. All the files used for the html versions (along with all the V86 related files) can be found here.


index_single_tab.html


<!DOCTYPE html>
<html lang="en">
<head>
    <title>IronVault: Universal Deep-Discovery</title>
    <meta charset="utf-8" />
    <style>
        body { background: #050505; color: #00ff41; font-family: 'Courier New', monospace; display: flex; flex-direction: column; align-items: center; padding: 20px; }
        #boot-log { width: 750px; height: 320px; background: #000; overflow-y: scroll; border: 1px solid #00ff41; padding: 15px; font-size: 12px; margin-bottom: 20px; color: #00ff41; box-shadow: inset 0 0 15px #002200; }
        #screen_container { border: 10px solid #111; display: none; background: #000; margin-top: 10px;}
        #screen_container canvas { display: block; }
        .verified { color: #00ff41; font-weight: bold; }
        .err { color: #ff3333; font-weight: bold; }
        .diag { color: #888; font-style: italic; }
    </style>
</head>
<body>

    <h1>IRON VAULT: UNIVERSAL</h1>
    <div id="boot-log"></div>
    <div id="screen_container"><canvas id="vga_canvas"></canvas></div>

    <script type="module">
        const log = (msg, type = 'info') => {
            const div = document.getElementById("boot-log");
            div.innerHTML += `<span class="${type}">> ${msg}</span><br>`;
            div.scrollTop = div.scrollHeight;
        };

        async function extractDNA(imgSrc) {
            log(`Opening Lattice: ${imgSrc}`);
            const response = await fetch(imgSrc);
            const blob = await response.blob();
            const img = await createImageBitmap(blob, { colorSpaceConversion: 'none' });
            
            const canvas = document.createElement('canvas');
            canvas.width = img.width; canvas.height = img.height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            
            const imgData = ctx.getImageData(0, 0, img.width, img.height).data;
            let rgb = new Uint8Array((imgData.length / 4) * 3);
            let idx = 0;
            for (let i = 0; i < imgData.length; i += 4) {
                rgb[idx++] = imgData[i]; rgb[idx++] = imgData[i+1]; rgb[idx++] = imgData[i+2];
            }

            let end = rgb.length - 1;
            while (end >= 0 && rgb[end] === 0) end--;
            const b64Len = new DataView(rgb.buffer, end - 3, 4).getUint32(0);
            const b64 = new TextDecoder().decode(rgb.slice(0, b64Len)).replace(/-/g, '+').replace(/_/g, '/');
            const binary = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
            
            const headerLen = new DataView(binary.buffer, 0, 4).getUint32(0);
            const metadata = JSON.parse(new TextDecoder().decode(binary.slice(4, 4 + headerLen)));
            
            const ds = new DecompressionStream('gzip');
            const writer = ds.writable.getWriter();
            writer.write(binary.slice(4 + headerLen));
            writer.close();
            
            const output = [];
            const reader = ds.readable.getReader();
            while (true) {
                const { value, done } = await reader.read();
                if (done) break;
                output.push(value);
            }
            const finalData = new Uint8Array(output.reduce((acc, curr) => acc + curr.length, 0));
            let offset = 0;
            for (const chunk of output) { finalData.set(chunk, offset); offset += chunk.length; }

            log(`Verified: ${metadata.filename} [${finalData.length} bytes]`, 'verified');
            return { data: finalData, filename: metadata.filename };
        }

        async function init() {
            try {
                // 1. ENGINE EXTRACTION
                const jsResult = await extractDNA("MASTER_DNA_SEED_libv86.js.png");
                const jsText = new TextDecoder().decode(jsResult.data);
                
                log("Injecting Engine DNA...");
                // Force global execution using the indirect eval trick
                (0, eval)(jsText);

                // 2. DEEP DISCOVERY LOOP (Hunts for the constructor)
                log("Searching memory for Emulator Constructor...", "diag");
                let V86Constructor = null;
                
                for (let i = 0; i < 15; i++) {
                    // Check standard locations
                    V86Constructor = window.V86Starter || (window.v86 && window.v86.V86Starter);
                    
                    if (!V86Constructor) {
                        // Brute force scan
                        for (let key in window) {
                            if (key.toLowerCase().includes("v86") && typeof window[key] === "function") {
                                V86Constructor = window[key];
                                break;
                            }
                        }
                    }
                    
                    if (V86Constructor) break;
                    await new Promise(r => setTimeout(r, 200));
                }

                if (!V86Constructor) throw new Error("V86Starter not found in global scope.");
                log("Emulator Engine: LOCATED", "verified");

                // 3. HARDWARE EXTRACTION
                const wasmRes = await extractDNA("MASTER_DNA_SEED_v86.wasm.png");
                const wasmUrl = URL.createObjectURL(new Blob([wasmRes.data], { type: 'application/wasm' }));
                const biosRes = await extractDNA("MASTER_DNA_SEED_seabios.bin.png");
                const vgaRes = await extractDNA("MASTER_DNA_SEED_vgabios.bin.png");

                // 4. OS EXTRACTION (Swap this for kolibri.img or sectorforth.img.png or linuxV3.iso.png)
                const osResult = await extractDNA("MASTER_DNA_SEED_linuxV3.iso.png");

                // 5. SMART CONFIGURATION
                const v86Config = {
                    wasm_path: wasmUrl,
                    memory_size: 128 * 1024 * 1024,
                    vga_canvas: document.getElementById("vga_canvas"),
                    screen_container: document.getElementById("screen_container"),
                    bios: { buffer: biosRes.data.buffer },
                    vga_bios: { buffer: vgaRes.data.buffer },
                    autostart: true,
                    preserve_aspect_ratio: true
                };

                const fname = osResult.filename.toLowerCase();
                if (fname.endsWith(".iso")) {
                    log("Mapping to ATAPI CD-ROM...", "diag");
                    v86Config.cdrom = { buffer: osResult.data.buffer };
                } 
                else if (fname.endsWith(".img") || fname.endsWith(".bin")) {
                    if (osResult.data.length < 2000000) {
                        log("Mapping to Floppy Drive A...", "diag");
                        v86Config.fda = { buffer: osResult.data.buffer };
                    } else {
                        log("Mapping to Hard Drive A...", "diag");
                        v86Config.hda = { buffer: osResult.data.buffer };
                    }
                }

                // 6. IGNITION
                log("Ignition Sequence Start...", "verified");
                document.getElementById("screen_container").style.display = "block";

                window.emulator = new V86Constructor(v86Config);
                log("BOOTING SYSTEM...", "verified");

            } catch (e) {
                log(`FATAL ERROR: ${e.message}`, "err");
                console.error(e);
            }
        }

        init();
    </script>
</body>
</html>

All the files used for the node-js version (along with all the V86 related files) can also be found here.


iron_vm_headless.js


const fs = require('fs');
const zlib = require('zlib');
const path = require('path');
const { PNG } = require('pngjs');
const { performance } = require('perf_hooks');
const crypto = require('node:crypto');

const DNA_STORAGE = { js: "", wasm: "", bios: "", vga: "", os: "" };
const CONFIG = {
    prefix: "MASTER_DNA_SEED_",
    ext: ".png",
    tempFile: path.join(__dirname, ".synthetic_engine.js")
};

async function getDNA(type, filename) {
    if (DNA_STORAGE[type]) return zlib.gunzipSync(Buffer.from(DNA_STORAGE[type], 'base64'));
    const pngPath = path.join(__dirname, `${CONFIG.prefix}${filename}${CONFIG.ext}`);
    if (!fs.existsSync(pngPath)) throw new Error(`DNA Missing: ${filename}`);

    const png = PNG.sync.read(fs.readFileSync(pngPath));
    const rgb = Buffer.alloc((png.data.length / 4) * 3);
    for (let i = 0, j = 0; i < png.data.length; i += 4) {
        rgb[j++] = png.data[i]; rgb[j++] = png.data[i + 1]; rgb[j++] = png.data[i + 2];
    }
    let end = rgb.length - 1;
    while (end >= 0 && rgb[end] === 0) end--;
    const b64Len = rgb.readUInt32BE(end - 3);
    const b64Str = rgb.slice(0, b64Len).toString('utf8').replace(/-/g, '+').replace(/_/g, '/');
    let padded = b64Str; while (padded.length % 4 !== 0) padded += '=';
    const payload = Buffer.from(padded, 'base64');
    return zlib.gunzipSync(payload.slice(4 + payload.readUInt32BE(0)));
}

(async () => {
    try {
        console.log("\x1b[1m\x1b[34m--- IRON VAULT: SYNTHETIC ENVIRONMENT (v6.4) ---\x1b[0m");

        const jsDNA = await getDNA('js', 'libv86.js');
        const wasmDNA = await getDNA('wasm', 'v86.wasm');
        const biosDNA = await getDNA('bios', 'seabios.bin');
        const vgaDNA  = await getDNA('vga', 'vgabios.bin');
        const osDNA   = await getDNA('os', 'sectorforth.img'); 

        // Define the entire environment as a string to avoid Proxy conversion errors
        const syntheticCode = `
            // 1. Recursive Membrane Definition
            const createMem = () => {
                const m = new Proxy(() => m, {
                    get: (t, p) => {
                        if (p === 'currentTime') return Date.now()/1000;
                        if (p === 'style' || p === 'dataset') return {};
                        if (p === 'nodeType') return 1;
                        return m;
                    },
                    construct: () => m
                });
                return m;
            };
            const voidObj = createMem();

            // 2. Global Shims
            global.window = global;
            global.self = global;
            global.navigator = { userAgent: "node.js", platform: "Linux x86_64", language: "en-US" };
            global.performance = require("perf_hooks").performance;
            global.crypto = require("node:crypto").webcrypto;
            global.AudioContext = class { constructor() { return voidObj; } };
            global.webkitAudioContext = global.AudioContext;
            global.document = voidObj;
            global.addEventListener = () => {};
            global.removeEventListener = () => {};

            // 3. Engine Execution
            (function() {
                const exports = undefined; const module = undefined; const define = undefined;
                ${jsDNA.toString()}
                if (typeof N === 'function') global.V86Starter = N;
            }).call(global);

            module.exports = global.V86Starter || global.V86 || (global.v86 && global.v86.V86Starter);
        `;
        
        fs.writeFileSync(CONFIG.tempFile, syntheticCode);
        const V86 = require(CONFIG.tempFile);
        const toAB = (b) => b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);

        console.log("[ENGINE] Handshake Success. CPU Igniting...");

        const emulator = new V86({
            bios: { buffer: toAB(biosDNA) },
            vga_bios: { buffer: toAB(vgaDNA) },
            wasm_fn: async (env) => (await WebAssembly.instantiate(wasmDNA, env)).instance.exports,
            autostart: true,
            memory_size: 32 * 1024 * 1024,
            disable_keyboard: true,
            disable_mouse: true,
            fda: { buffer: toAB(osDNA) } // sectorforth is a Floppy
        });

        // --- THE LENS: VGA MEMORY SCRAPER ---
        let lastScreen = "";
        const render = () => {
            try {
                // Scrape VGA Text Buffer (0xB8000)
                const mem = emulator.read_memory(0xB8000, 80 * 25 * 2);
                let currentScreen = "";
                for (let i = 0; i < mem.length; i += 2) {
                    const charCode = mem[i];
                    currentScreen += (charCode > 31 && charCode < 127) ? String.fromCharCode(charCode) : " ";
                    if ((i / 2 + 1) % 80 === 0) currentScreen += "\n";
                }

                if (currentScreen.trim().length > 0 && currentScreen !== lastScreen) {
                    process.stdout.write("\x1b[H\x1b[J"); // Home and Clear
                    console.log("\x1b[34m╔══════════════════════ IRON VAULT MONITOR ══════════════════════╗\x1b[0m");
                    console.log(currentScreen);
                    console.log("\x1b[34m╚════════════════════════════════════════════════════════════════╝\x1b[0m");
                    console.log(`Instructions: ${emulator.get_instruction_counter().toLocaleString()}`);
                    lastScreen = currentScreen;
                }
            } catch (e) {}
        };

        setInterval(render, 200);

        // --- INPUT (XT SCANCODES) ---
        const XT = { "\r": 0x1C, " ": 0x39, "A": 0x1E, "B": 0x30, "C": 0x2E, "D": 0x20, "E": 0x12, "F": 0x21, "G": 0x22, "H": 0x23, "I": 0x17, "J": 0x24, "K": 0x25, "L": 0x26, "M": 0x32, "N": 0x31, "O": 0x18, "P": 0x19, "Q": 0x10, "R": 0x13, "S": 0x1F, "T": 0x14, "U": 0x16, "V": 0x2F, "W": 0x11, "X": 0x2D, "Y": 0x15, "Z": 0x2C };
        
        process.stdin.setRawMode(true);
        process.stdin.resume();
        process.stdin.setEncoding("utf8");
        process.stdin.on("data", (key) => {
            if (key === "\u0003") {
                if (fs.existsSync(CONFIG.tempFile)) fs.unlinkSync(CONFIG.tempFile);
                process.exit();
            }
            const code = XT[key.toUpperCase()];
            if (code) {
                emulator.bus.send("keyboard-code", code);
                emulator.bus.send("keyboard-code", code | 0x80);
            }
        });

    } catch (err) {
        console.error("\n[FATAL ERROR]", err.message);
        if (fs.existsSync(CONFIG.tempFile)) fs.unlinkSync(CONFIG.tempFile);
    }
})();

All of these projects are actually offshoots from some new additions that I have been making to my system-prompt project.

I am only mentioning that project as a footnote and please note that those latest series of 'ai kernels' (in the folder that the link points to) are ones that I have been experimenting with facilitating REPL (mainly python and forth) capabilities in. Furthermore the kernels are much more jailbroken than many of the other kernel series because they (the system prompts) are designed to guide an LLM to build 'ai kernels' which gets nutty when it is also having to REPL its own code outputs as new inputs... to make new outputs... in the form of a new 'ai kernel' or just making kernel modifications... for its own kernel... so that it can build better kernels!

I am sure folks can imagine just how wild that gets and surprisingly enough... I did not have too many problems with them getting stuck in loops (while forging kernels) or getting lost in all the many layers of complexity around its own recursive activities.

Well, I think that about sums it all up. I hope that someone finds it all useful. My apologies about all the LLM generated content in this post as far as the code goes. I am still better at describing what I want to achieve than actually writing the code myself.

MASTER_DNA_SEED_pi_digits.txt.png

This noisy looking image is actually a file named 'pi_digits.txt' that contains the first million digits of pi!

If anyone wants to decode the above image back into 'pi_digits.txt' I made it available here in case the image servers compress or alter it in a way in which it cannot be properly decoded.

Thanks for reading!

Cheers! & Hive On!

All content found in this post is mine!



0
0
0.000
0 comments