Last active
August 19, 2020 14:38
-
-
Save tscholl2/bb7a03f71a7e22d2686e1039f285d9a7 to your computer and use it in GitHub Desktop.
Revisions
-
tscholl2 revised this gist
Aug 19, 2020 . 2 changed files with 23 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,18 +1,29 @@ /** * Encode takes a string as input, encodes it as UTF8 * then embeds it into a PNG which has builtin compression. * @param {string} input * @returns {Promise<string>} */ async function encode(input) { const bytes = new TextEncoder("utf-8").encode(input); const canvas = document.createElement("canvas"); canvas.width = Math.ceil(Math.sqrt(bytes.length / 3 + 2)); canvas.height = canvas.width; const ctx = canvas.getContext('2d'); const imgData = ctx.createImageData(canvas.width, canvas.height); for (let i = 0, j = 0; j < 4; i++) imgData.data[i] = i % 4 == 3 ? 255 : (bytes.length >> (8 * j++)) & 0xff; for (let i = 5, j = 0; i < 4 * canvas.width * canvas.height; i++) imgData.data[i] = i % 4 == 3 ? 255 : bytes[j++] || 0; ctx.putImageData(imgData, 0, 0); return canvas.toDataURL('image/png', 0); } /** * Reverse of encode. * @param {string} input * @returns {Promise<string>} */ async function decode(input) { const image = new Image(); image.src = input; @@ -24,10 +35,10 @@ async function decode(input) { ctx.drawImage(image, 0, 0); const imgData = ctx.getImageData(0, 0, image.width, image.height); let length = 0; for (let i = 0, j = 0; j < 4; i++) length |= i % 4 == 3 ? 0 : (imgData.data[i] << (8 * j++)); const output = imgData.data .filter((_, i) => i > 4 && i % 4 != 3) .slice(0, length) return new TextDecoder("utf-8").decode(output); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1 @@ (()=>{return{encode:async function(t){const e=new TextEncoder("utf-8").encode(t),a=document.createElement("canvas");a.width=Math.ceil(e.length/3+2),a.height=1;const n=a.getContext("2d"),c=n.createImageData(a.width,1);for(let t=0,a=0;a<4;t++)c.data[t]=t%4==3?255:e.length>>8*a++&255;for(let t=5,n=0;t<4*a.width;t++)c.data[t]=t%4==3?255:e[n++]||0;return n.putImageData(c,0,0),a.toDataURL("image/png",0)},decode:async function(t){const e=new Image;e.src=t,await new Promise(t=>e.onload=t);const a=document.createElement("canvas");a.width=e.width,a.height=1;const n=a.getContext("2d");n.drawImage(e,0,0);const c=n.getImageData(0,0,e.width,1);let o=0;for(let t=0,e=0;e<4;t++)o|=t%4==3?0:c.data[t]<<8*e++;const d=c.data.filter((t,e)=>e>4&&e%4!=3).slice(0,o);return new TextDecoder("utf-8").decode(d)}}})(); -
tscholl2 revised this gist
Aug 19, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1 @@ (()=>{const t=String.fromCodePoint,e="length";return{compress:(o)=>{const r=[],n=new Map;for(let e=0;e<256;e++)n.set(t(e),e);let s="",c="",l="";for(let e of o)l=s+(c=t(e)),n.has(l)?s=l:(r.push(n.set(l,n.size).get(s)),s=c);return r.push(n.get(s)),(t=>{const o=t.reduce((t=0,e)=>e>t?e:t),r=1+Math.floor(Math.log2(o)),n=new Uint8Array(5+Math.ceil(t[e]*r/8));n[0]=r;for(let o=0;o<4;o++)n[1+o]=t[e]>>8*o&255;for(let o=0;o<t[e];o++)for(let e=0;e<r;e++){const s=40+(o*r+e);n[s>>3]|=(1<<s%8)*(t[o]>>e&1)}return n})(r)},decompress:(o)=>{const r=(t=>{const o=t[0],r=t.slice(1,5).reverse().reduce((t,e)=>t<<8|e,0),n=new Uint32Array(r);for(let r=0;r<t[e];r++)for(let e=0;e<o;e++){const s=40+(r*o+e);n[r]|=(1<<e)*(t[s>>3]>>s%8&1)}return n})(o),n=[];for(let e=0;e<256;e++)n.push(t(e));let s=n[r[0]],c="";const l=[s];for(let t of r.slice(1))l.push(c=t<n[e]?n[t]:s+s[0]),n.push(s+c[0]),s=c;const f=[];for(let t of l.join(""))f.push(t.codePointAt(0));return new Uint8Array(f)}}})(); -
tscholl2 revised this gist
Aug 10, 2020 . 4 changed files with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ (() => { const fcp = String.fromCodePoint; const L = "length"; /** This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1 @@ (()=>{const t=String.fromCodePoint,e="length";return{compress:function(o){const r=[],n=new Map;for(let e=0;e<256;e++)n.set(t(e),e);let s="",c="",l="";for(let e of o)l=s+(c=t(e)),n.has(l)?s=l:(r.push(n.set(l,n.size).get(s)),s=c);return r.push(n.get(s)),(t=>{const o=t.reduce((t=0,e)=>e>t?e:t),r=1+Math.floor(Math.log2(o)),n=new Uint8Array(5+Math.ceil(t[e]*r/8));n[0]=r;for(let o=0;o<4;o++)n[1+o]=t[e]>>8*o&255;for(let o=0;o<t[e];o++)for(let e=0;e<r;e++){const s=40+(o*r+e);n[s>>3]|=(1<<s%8)*(t[o]>>e&1)}return n})(r)},decompress:function(o){const r=(t=>{const o=t[0],r=t.slice(1,5).reverse().reduce((t,e)=>t<<8|e,0),n=new Uint32Array(r);for(let r=0;r<t[e];r++)for(let e=0;e<o;e++){const s=40+(r*o+e);n[r]|=(1<<e)*(t[s>>3]>>s%8&1)}return n})(o),n=[];for(let e=0;e<256;e++)n.push(t(e));let s=n[r[0]],c="";const l=[s];for(let t of r.slice(1))l.push(c=t<n[e]?n[t]:s+s[0]),n.push(s+c[0]),s=c;const f=[];for(let t of l.join(""))f.push(t.codePointAt(0));return new Uint8Array(f)}}})(); File renamed without changes.This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ (()=>{return{encode:async function(t){const e=document.createElement("canvas");e.width=Math.ceil(Math.sqrt(t.length/3)),e.height=e.width;const a=e.getContext("2d"),n=a.createImageData(e.width,e.height);for(let e=0,a=0;e<7;e++)n.data[e]=e%4==3?255:t.length>>>8*a++&255;for(let a=7,h=0;a<4*e.width*e.height;a++)n.data[a]=a%4==3?255:t.charCodeAt(h++)||0;return a.putImageData(n,0,0),e.toDataURL("image/png",0)},decode:async function(t){const e=new Image;e.src=t,await new Promise(t=>e.onload=t);const a=document.createElement("canvas");a.width=e.width,a.height=e.height;const n=a.getContext("2d");n.drawImage(e,0,0);const h=n.getImageData(0,0,e.width,e.height);let o=0;for(let t=0,e=0;t<7;t++)o|=t%4==3?0:h.data[t]<<8*e++;let d="";for(let t=7;t<h.data.length;t++)d+=t%4==3?"":String.fromCharCode(h.data[t]);return d.substr(0,o)}}}); -
tscholl2 revised this gist
Aug 10, 2020 . 2 changed files with 83 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,82 @@ (function () { const fcp = String.fromCodePoint; const L = "length"; /** * @param {Uint8Array} input * @returns {Uint8Array} */ function compress(input) { const codewords = []; const dictionary = new Map(); for (let i = 0; i < 256; i++) dictionary.set(fcp(i), i); let buf = "", next = "", bufnext = ""; for (let x of input) { next = fcp(x); bufnext = buf + next; if (dictionary.has(bufnext)) buf = bufnext; else { codewords.push(dictionary.set(bufnext, dictionary.size).get(buf)); buf = next; } } codewords.push(dictionary.get(buf)); return ((input) => { /** * Condenses a byte array into an array of numbers. * @param {Uint32Array} input * @returns {Uint8Array} */ const max = input.reduce((p = 0, n) => n > p ? n : p); const bits = 1 + Math.floor(Math.log2(max)); const output = new Uint8Array(1 + 4 + Math.ceil(input[L] * bits / 8)); output[0] = bits; for (let i = 0; i < 4; i++) output[1 + i] = (input[L] >> (i * 8)) & 0xff; for (let i = 0; i < input[L]; i++) for (let j = 0; j < bits; j++) { const k = 8 * 5 + (i * bits + j); output[k >> 3] |= (1 << ((k % 8))) * ((input[i] >> j) & 1); } return output; })(codewords); } /** * @param {Uint8Array} input * @returns {Uint8Array} */ function decompress(input) { const codewords = ((input) => { /** * Uncondenses a byte array into an array of numbers. * @param {Uint8Array} input * @returns {Uint32Array} */ const bits = input[0]; const length = input.slice(1, 5).reverse().reduce((p, n) => (p << 8) | n, 0); const output = new Uint32Array(length); for (let i = 0; i < input[L]; i++) for (let j = 0; j < bits; j++) { const k = 8 * 5 + (i * bits + j); output[i] |= (1 << j) * ((input[k >> 3] >> (k % 8)) & 1); } return output; })(input); const dictionary = []; for (let i = 0; i < 256; i++) dictionary.push(fcp(i)); let prev = dictionary[codewords[0]], next = ""; const values = [prev]; for (let k of codewords.slice(1)) { values.push(next = k < dictionary[L] ? dictionary[k] : prev + prev[0]); dictionary.push(prev + next[0]); prev = next; } const output = []; for (let c of values.join("")) output.push(c.codePointAt(0)); return new Uint8Array(output); } return { compress, decompress }; })() This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ (function(){const t=String.fromCodePoint,e="length";return{compress:function(o){const r=[],n=new Map;for(let e=0;e<256;e++)n.set(t(e),e);let s="",c="",f="";for(let e of o)f=s+(c=t(e)),n.has(f)?s=f:(r.push(n.set(f,n.size).get(s)),s=c);return r.push(n.get(s)),(t=>{const o=t.reduce((t=0,e)=>e>t?e:t),r=1+Math.floor(Math.log2(o)),n=new Uint8Array(5+Math.ceil(t[e]*r/8));n[0]=r;for(let o=0;o<4;o++)n[1+o]=t[e]>>8*o&255;for(let o=0;o<t[e];o++)for(let e=0;e<r;e++){const s=40+(o*r+e);n[s>>3]|=(1<<s%8)*(t[o]>>e&1)}return n})(r)},decompress:function(o){const r=(t=>{const o=t[0],r=t.slice(1,5).reverse().reduce((t,e)=>t<<8|e,0),n=new Uint32Array(r);for(let r=0;r<t[e];r++)for(let e=0;e<o;e++){const s=40+(r*o+e);n[r]|=(1<<e)*(t[s>>3]>>s%8&1)}return n})(o),n=[];for(let e=0;e<256;e++)n.push(t(e));let s=n[r[0]],c="";const f=[s];for(let t of r.slice(1))f.push(c=t<n[e]?n[t]:s+s[0]),n.push(s+c[0]),s=c;const l=[];for(let t of f.join(""))l.push(t.codePointAt(0));return new Uint8Array(l)}}})(); -
tscholl2 revised this gist
Aug 5, 2020 . 1 changed file with 32 additions and 33 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,34 +1,33 @@ async function encode(input) { // TODO: handle unicode? const canvas = document.createElement("canvas"); canvas.width = Math.ceil(Math.sqrt(input.length / 3)); canvas.height = canvas.width; const ctx = canvas.getContext('2d'); const imgData = ctx.createImageData(canvas.width, canvas.height); for (let i = 0, j = 0; i < 7; i++) imgData.data[i] = i % 4 == 3 ? 255 : (input.length >>> (8 * j++)) & 0xff; for (let i = 7, j = 0; i < 4 * canvas.width * canvas.height; i++) imgData.data[i] = i % 4 == 3 ? 255 : input.charCodeAt(j++) || 0; ctx.putImageData(imgData, 0, 0); return canvas.toDataURL('image/png', 0); } async function decode(input) { const image = new Image(); image.src = input; await new Promise(r => image.onload = r); const canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); const imgData = ctx.getImageData(0, 0, image.width, image.height); let length = 0; for (let i = 0, j = 0; i < 7; i++) length |= i % 4 == 3 ? 0 : (imgData.data[i] << (8 * j++)); let output = ""; for (let i = 7; i < imgData.data.length; i++) output += i % 4 == 3 ? "" : String.fromCharCode(imgData.data[i]); return output.substr(0, length); } -
tscholl2 revised this gist
Aug 5, 2020 . 1 changed file with 33 additions and 35 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,36 +1,34 @@ async function encode(input) { // TODO: handle unicode? const canvas = document.createElement("canvas"); canvas.width = Math.ceil(Math.sqrt(input.length / 3)); canvas.height = canvas.width; const ctx = canvas.getContext('2d'); const imgData = ctx.createImageData(canvas.width, canvas.height); for (let i = 0, j = 0; i < 7; i++) imgData.data[i] = i % 4 == 3 ? 255 : (input.length >>> (8 * j++)) & 0xff; for (let i = 7, j = 0; i < 4 * canvas.width; i++) imgData.data[i] = i % 4 == 3 ? 255 : input.charCodeAt(j++) || 0; ctx.putImageData(imgData, 0, 0); const s = canvas.toDataURL('image/png', 0); return s; } async function decode(input) { const image = new Image(); image.src = input; await new Promise(r => image.onload = r); const canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); const imgData = ctx.getImageData(0, 0, image.width, image.height); let length = 0; for (let i = 0, j = 0; i < 7; i++) length |= i % 4 == 3 ? 0 : (imgData.data[i] << (8 * j++)); let output = ""; for (let i = 7; i < imgData.data.length; i++) output += i % 4 == 3 ? "" : String.fromCharCode(imgData.data[i]); return output.substr(0, length); } -
tscholl2 created this gist
Aug 5, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,36 @@ async function encode(input) { // TODO: handle unicode? const canvas = document.createElement("canvas"); canvas.width = Math.ceil(input.length / 3) + 8; canvas.height = 1; const ctx = canvas.getContext('2d'); const imgData = ctx.createImageData(canvas.width, 1); for (let i = 0, j = 0; i < 7; i++) imgData.data[i] = i % 4 == 3 ? 255 : (input.length >>> (8 * j++)) & 0xff; for (let i = 7, j = 0; i < 4 * canvas.width; i++) imgData.data[i] = i % 4 == 3 ? 255 : input.charCodeAt(j++) || 0; ctx.putImageData(imgData, 0, 0); return canvas.toDataURL('image/png', 0); } async function decode(input) { console.log(input) const image = new Image(); image.src = input; await new Promise(r => image.onload = r); const canvas = document.createElement("canvas"); canvas.width = image.width; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); const imgData = ctx.getImageData(0, 0, image.width, 1); let length = 0; for (let i = 0, j = 0; i < 7; i++) length |= i % 4 == 3 ? 0 : (imgData.data[i] << (8 * j++)); let output = ""; for (let i = 7; i < imgData.data.length; i++) output += i % 4 == 3 ? "" : String.fromCharCode(imgData.data[i]); return output.substr(0, length); } // Both minified async function encode(t){const e=document.createElement("canvas");e.width=Math.ceil(t.length/3)+8,e.height=1;const a=e.getContext("2d"),n=a.createImageData(e.width,1);for(let e=0,a=0;e<7;e++)n.data[e]=e%4==3?255:t.length>>>8*a++&255;for(let a=7,o=0;a<4*e.width;a++)n.data[a]=a%4==3?255:t.charCodeAt(o++)||0;return a.putImageData(n,0,0),e.toDataURL("image/png",0)}async function decode(t){console.log(t);const e=new Image;e.src=t,await new Promise(t=>e.onload=t);const a=document.createElement("canvas");a.width=e.width;const n=a.getContext("2d");n.drawImage(e,0,0);const o=n.getImageData(0,0,e.width,1);let c=0;for(let t=0,e=0;t<7;t++)c|=t%4==3?0:o.data[t]<<8*e++;let d="";for(let t=7;t<o.data.length;t++)d+=t%4==3?"":String.fromCharCode(o.data[t]);return d.substr(0,c)}