Last active
February 27, 2025 10:31
-
-
Save nildopontes/223899c9c2892561c9de56dc7f42bc69 to your computer and use it in GitHub Desktop.
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 characters
class ePNG { | |
constructor(data, w, h){ | |
if(data.length != (w * h * 4)) return console.error(`Corrupted samples.`); | |
this.buffer = new Uint8Array(w * h * 4 + h); | |
for(let i = 0; i < h; i++){ | |
this.buffer.set(data.slice(i * w * 4, (i + 1) * w * 4), i * w * 4 + 1 + i); | |
} | |
this.makeCRCTable(); | |
this.ihdr = new Uint8Array([0, 0, 0, 13, 73, 72, 68, 82, ...this.set32bit(w), ...this.set32bit(h), 8, 6, 0, 0, 0, 0, 0, 0, 0]); | |
this.ihdr.set(this.getCRC32(this.ihdr.slice(4, 21)), 21); | |
} | |
set32bit(v){ | |
return [v >> 24 & 255, v >> 16 & 255, v >> 8 & 255, v & 255]; | |
} | |
makeCRCTable(){ | |
let c, a = []; | |
for(let n = 0; n < 256; n++){ | |
c = n; | |
for(let k = 0; k < 8; k++){ | |
c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; | |
} | |
a.push(c); | |
} | |
this.crcTable = a; | |
} | |
getCRC32(data){ | |
let crc = -1; | |
data.map(v => crc = crc >>> 8 ^ this.crcTable[(crc ^ v) & 255]); | |
return this.set32bit(crc ^ -1 >>> 0); | |
} | |
compress(input){ | |
let cs = new CompressionStream('deflate'); | |
let writer = cs.writable.getWriter(); | |
writer.write(input); | |
writer.close(); | |
return new Response(cs.readable).bytes(); | |
} | |
encode(){ | |
return new Promise((resolve, reject) => { | |
this.compress(this.buffer).then(c => { | |
let idat = new Uint8Array([...this.set32bit(c.length), 73, 68, 65, 84, ...c, ...this.getCRC32([73, 68, 65, 84, ...c])]); | |
resolve(new Blob([new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]), this.ihdr, idat, new Uint8Array([0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130])], {type: "image/png"})); | |
}); | |
}); | |
} | |
} | |
/* EXEMPLO DE USO | |
window.addEventListener('load', e => { | |
let colors = [], d = []; | |
for(let c = 0; c < 256; c++) colors.push([parseInt(Math.random() * 255, 10), parseInt(Math.random() * 255, 10), parseInt(Math.random() * 255, 10), 255]); | |
for(let i = 0; i < 500; i++){ | |
let color = parseInt(Math.random() * 255, 10); | |
for(let j = 0; j < 500; j++){ | |
d.push(...colors[color]); | |
} | |
} | |
let t0 = Date.now(); | |
png = new ePNG(d, 500, 500); | |
png.encode().then(b => { | |
let url = window.URL.createObjectURL(b); | |
document.body.innerHTML += `<br><hr><br><br><span>Tamanho: ${parseInt(b.size / 1024, 10)} KB</span><br><span>Tempo decorrido: ${Date.now() - t0} milissegundos</span><br><img src="${url}">`; | |
}); | |
}); | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment