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
-