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);