THis is the standalone javascript file for extracting H@G@ marked Application Extension Blocks - gifFile.html ![]()
It is one of the experimental components for writing snimated gif metadata
https://david.codefish.club/assets/animated-gif-metadata/gifFile.html HEIGHT 50 gifFile.html
animated-gif-metadata
<input type="file" id="gifFile" accept=".gif" /> <pre id="out"></pre> <script> document.getElementById('gifFile').addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const buf = await file.arrayBuffer(); const result = parseH2G2AppExtension(new Uint8Array(buf)); document.getElementById('out').textContent = result ? `Found H2G2 App Extension:\n${result.dataText}` : 'No H2G2 App Extension found'; }); function parseH2G2AppExtension(bytes) { let p = 0; function read(n){ const s = bytes.subarray(p, p+n); p += n; return s; } function readByte(){ return bytes[p++]; } function readSubBlocks() { const chunks = []; while (true) { const size = readByte(); if (size === 0) break; chunks.push(read(size)); } return Uint8Array.from(chunks.flat()); } function ascii(arr) { return String.fromCharCode(...arr); } function tryDecode(u8) { try { return new TextDecoder().decode(u8); } catch { return ascii(u8); } } // Header const header = ascii(read(6)); if (!/^GIF8[79]a$/.test(header)) throw new Error('Not a GIF'); // Logical Screen Descriptor const lsd = read(7); if (lsd[4] & 0x80) { // GCT present p += 3 * (1 << ((lsd[4] & 0x07) + 1)); } while (p < bytes.length) { const introducer = readByte(); if (introducer === 0x3B) break; // Trailer if (introducer === 0x2C) { // Image Descriptor const id = read(10); if (id[9] & 0x80) p += 3 * (1 << ((id[9] & 0x07) + 1)); readByte(); readSubBlocks(); } else if (introducer === 0x21) { const label = readByte(); if (label === 0xFF) { // Application Extension const blockSize = readByte(); if (blockSize === 11) { const appId = ascii(read(8)); const authCode = ascii(read(3)); const data = readSubBlocks(); if (appId === 'H2G2') { return { appId, authCode, data, dataText: tryDecode(data) }; } } else { p += blockSize; readSubBlocks(); } } else if (label === 0xF9) { // Graphic Control Ext p += readByte(); readByte(); } else { readSubBlocks(); } } else { break; } } return null; } </script>