From 77aeccccefa76bd31d4d4874a733409e37ed10fd Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Aug 2023 17:44:57 -0700 Subject: [PATCH 1/5] whee --- index.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 69ad34c..866f9ff 100644 --- a/index.html +++ b/index.html @@ -22,9 +22,10 @@

- Currently just converts to grayscale and counts up unique blocks. - Next step: decimate if > 128 unique blocks per image, and combine - the most similar blocks in the output. + Currently converts to grayscale and reuses existing similar blocks as it goes, + increasing a similarity threshold (from 0) until the set fits in 128 chars. + Next step: correctly handle inverse video similarities + Further step: don't end up stuck between 64 and 128 blocks :D

Source video

From ca7faf698f8beb6b7ee239dabc7fbfb5d927c4ef Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Aug 2023 17:46:07 -0700 Subject: [PATCH 2/5] 8fps8fps8fps8fps8fps8fps8fps8fps --- index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 866f9ff..4e349cd 100644 --- a/index.html +++ b/index.html @@ -232,7 +232,10 @@ let timer = null; source.addEventListener('playing', () => { if (!timer) { - timer = setInterval(update, 1000 / 10); + // target 8 fps + // not sure we can get any faster + // downloads over sio + timer = setInterval(update, 1000 / 8); } update(); }); From 555a34b4db39267e3dbc75b33a874d1fdec50dfd Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 19 Aug 2023 12:18:37 -0700 Subject: [PATCH 3/5] working just terrible :D:wq --- index.html | 63 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/index.html b/index.html index 4e349cd..c9892e6 100644 --- a/index.html +++ b/index.html @@ -78,6 +78,30 @@ return block.map((n) => ~n & 0xf); } + function drawChar(bits, cx, cy, char, charset) { + let invert = Boolean(char & 0x80); + char &= 0x7f; + if (char >= charset.length) { + return; + } + let block = charset[char]; + for (let y = 0; y < blockHeight; y++) { + for (let x = 0; x < blockWidth; x++) { + let i = y * blockWidth + x; + let ii = (y + cy * blockHeight) * bits.width + (x + cx * blockWidth); + let gray16 = block[i]; + if (invert) { + gray16 = ~gray16 & 0x0f; + } + let gray256 = Math.round(gray16 * 255 / 15); + bits.data[ii * 4] = gray256; + bits.data[ii * 4 + 1] = gray256; + bits.data[ii * 4 + 2] = gray256; + bits.data[ii * 4 + 3] = 255; + } + } + } + function update() { let ctx = work.getContext('2d'); let pixels = new Uint8Array(width * height); @@ -142,6 +166,7 @@ chars[i] = char; } */ + for (let threshold = 0; threshold < 16; threshold++) { charIter: for (let i = 0; i < chars.length; i++) { @@ -187,43 +212,17 @@ for (let hi = 0; hi < 16; hi++) { for (let lo = 0; lo < 16; lo++) { let char = (hi << 4) | lo; - let invert = Boolean(char & 0x80); - char &= 0x7f; - if (char >= uniques.length) { - continue; - } - let block = uniques[char]; - for (let y = 0; y < blockHeight; y++) { - for (let x = 0; x < blockWidth; x++) { - let i = y * blockWidth + x; - let ii = (y + hi * blockHeight) * 16 * blockWidth + (x + lo * blockWidth); - if (block.length < i) { - debugger; - } - let gray16 = block[i]; - if (invert) { - gray16 = ~gray16 & 0x0f; - } - let gray256 = Math.round(gray16 * 255 / 15); - font.data[ii * 4] = gray256; - font.data[ii * 4 + 1] = gray256; - font.data[ii * 4 + 2] = gray256; - font.data[ii * 4 + 3] = 255; - } - } + drawChar(font, lo, hi, char, uniques); } } fontCtx.putImageData(font, 0, 0); // Redraw the blocks - for (let y = 0; y < height; y++) { - for (let x = 0; x < width; x++) { - let i = y * width + x; - let gray16 = pixels[i]; - let gray256 = Math.round(gray16 * 255 / 15); - data[i * 4] = gray256; - data[i * 4 + 1] = gray256; - data[i * 4 + 2] = gray256; + + for (let cy = 0; cy < heightBlocks; cy++) { + for (let cx = 0; cx < widthBlocks; cx++) { + let i = cy * widthBlocks + cx; + drawChar(bits, cx, cy, chars[i], uniques); } } ctx.putImageData(bits, 0, 0); From 605e6d04b9243527b3ca78a5a1522426dd085737 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 19 Aug 2023 12:54:28 -0700 Subject: [PATCH 4/5] better --- index.html | 91 +++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/index.html b/index.html index c9892e6..e0b8d79 100644 --- a/index.html +++ b/index.html @@ -74,11 +74,29 @@ return Array.from(block).map((n) => n.toString(16)).join(''); } - function inverse(block) { - return block.map((n) => ~n & 0xf); + function inverse(pixel) { + return ~pixel & 0xf; } - function drawChar(bits, cx, cy, char, charset) { + function matchBlocks(a, b, threshold) { + for (let i = 0; i < blockWidth * blockHeight; i++) { + if (Math.abs(a[i] - b[i]) > threshold) { + return false; + } + } + return true; + } + + function matchBlocksInverse(a, b, threshold) { + for (let i = 0; i < blockWidth * blockHeight; i++) { + if (Math.abs(a[i] - inverse(b[i])) > threshold) { + return false; + } + } + return true; + } + + function drawChar(imageData, cx, cy, char, charset) { let invert = Boolean(char & 0x80); char &= 0x7f; if (char >= charset.length) { @@ -88,16 +106,16 @@ for (let y = 0; y < blockHeight; y++) { for (let x = 0; x < blockWidth; x++) { let i = y * blockWidth + x; - let ii = (y + cy * blockHeight) * bits.width + (x + cx * blockWidth); + let ii = (y + cy * blockHeight) * imageData.width + (x + cx * blockWidth); let gray16 = block[i]; if (invert) { - gray16 = ~gray16 & 0x0f; + gray16 = inverse(gray16); } let gray256 = Math.round(gray16 * 255 / 15); - bits.data[ii * 4] = gray256; - bits.data[ii * 4 + 1] = gray256; - bits.data[ii * 4 + 2] = gray256; - bits.data[ii * 4 + 3] = 255; + imageData.data[ii * 4] = gray256; + imageData.data[ii * 4 + 1] = gray256; + imageData.data[ii * 4 + 2] = gray256; + imageData.data[ii * 4 + 3] = 255; } } } @@ -146,36 +164,12 @@ // // First pass: uniques extraction // Convert the 4bpp pixel indices into hex strings - let blockMap = {}; let uniques = []; - /* - for (let i = 0; i < chars.length; i++) { - let char = chars[i]; - let block = blocks[char]; - let key = hexify(blocks[i]); - let keyInverse = hexify(inverse(block)); - if (blockMap[key]) { - char = blockMap[key]; - } else if (blockMap[keyInverse]) { - char = blockMap[keyInverse]; - } else { - char = uniques.push(block) - 1; - blockMap[key] = char; - blockMap[keyInverse] = char; - } - chars[i] = char; - } - */ for (let threshold = 0; threshold < 16; threshold++) { charIter: - for (let i = 0; i < chars.length; i++) { - let char = chars[i]; - let block = blocks[char]; - if (!block) { - debugger - throw new Error('missing block'); - } + for (let i = 0; i < blocks.length; i++) { + let block = blocks[i]; fontMatch: for (let j = 0; j < uniques.length; j++) { @@ -184,14 +178,16 @@ debugger throw new Error('missing other'); } - for (let k = 0; k < blockWidth * blockHeight; k++) { - if (Math.abs(block[k] - other[k]) > threshold) { - continue fontMatch; - } + if (matchBlocks(block, other, threshold)) { + // we're close enough to reuse a character + chars[i] = j; + continue charIter; + } else if (matchBlocksInverse(block, other, threshold)) { + chars[i] = j | 0x8000; + continue charIter; + } else { + continue fontMatch; } - // we're close enough to reuse a character - chars[i] = j; - continue charIter; } // add a new char chars[i] = uniques.push(block) - 1; @@ -200,13 +196,12 @@ break; } // We need to decimate further - blocks = uniques; uniques = []; } let span = document.querySelector('#block-count'); span.textContent = `${uniques.length}`; - // Font (currently wrong! :D) + // Font let fontCtx = document.querySelector('#font').getContext('2d'); let font = fontCtx.createImageData(16 * blockWidth, 16 * blockHeight); for (let hi = 0; hi < 16; hi++) { @@ -222,7 +217,13 @@ for (let cy = 0; cy < heightBlocks; cy++) { for (let cx = 0; cx < widthBlocks; cx++) { let i = cy * widthBlocks + cx; - drawChar(bits, cx, cy, chars[i], uniques); + let char = chars[i]; + if (char & 0x8000) { + // we use a bigger bit during earlier stages + char &= 0x7f; + char |= 0x80; + } + drawChar(bits, cx, cy, char, uniques); } } ctx.putImageData(bits, 0, 0); From 88bb31fb436f37a6910c0aeafd81a3f68812205e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 19 Aug 2023 12:55:18 -0700 Subject: [PATCH 5/5] whee --- index.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/index.html b/index.html index e0b8d79..9ed6b53 100644 --- a/index.html +++ b/index.html @@ -28,13 +28,8 @@ Further step: don't end up stuck between 64 and 128 blocks :D

-

Source video

-
- -

Work canvas

-