diff --git a/dither-image.js b/dither-image.js index 2690485..f7be3d4 100644 --- a/dither-image.js +++ b/dither-image.js @@ -5,14 +5,18 @@ import { import Jimp from 'Jimp'; -function zeroes(n) { +function repeat(val, n) { let arr = []; for (let i = 0; i < n; i++) { - arr.push(0); + arr.push(val); } return arr; } +function zeroes(n) { + return repeat(0, n); +} + function toLinear(val) { // use a 2.4 gamma approximation // this is BT.1886 compatible @@ -584,6 +588,10 @@ function decimate(input, palette, n) { // preface the reserved bits let buckets = reserved.slice().map((c) => [atariRGB[c]]).concat([input.slice()]); + if (input.length != 160) { + console.log(input.length); + throw new Error('xxx bad input size'); + } /* let buckets = [input.slice()]; @@ -633,6 +641,10 @@ function decimate(input, palette, n) { while (buckets.length < n) { // Find the bucket with the greatest range in any channel let ranges = buckets.map((bucket) => { + if (bucket.length == 0) { + console.log(buckets); + throw new Error('xxx empty bucket'); + } let red = bucket.map((rgb) => rgb.r); let green = bucket.map((rgb) => rgb.g); let blue = bucket.map((rgb) => rgb.b); @@ -648,16 +660,17 @@ function decimate(input, palette, n) { let greatest = 0; let index = -1; for (let i = 0; i < topRanges.length; i++) { - if (topRanges[i] >= greatest) { + //if (topRanges[i] >= greatest) { + if (topRanges[i] > greatest) { greatest = topRanges[i]; index = i; } } if (index == -1) { // We just ran out of colors! Pad the buckets. - while (buckets.length < n) { - buckets.push([new RGB(0, 0, 0)]); - } + //while (buckets.length < n) { + // buckets.push([new RGB(0, 0, 0)]); + //} break; } let [lo, hi] = medianCut(buckets[index], ranges[index]); @@ -775,19 +788,25 @@ async function loadImage(src) { let width = image.bitmap.width; let height = image.bitmap.height; - //if (width != 160 || height != 160) { - if (width != 160) { + + let aspect = width / height; + let dar = 2 / 1.2; + if (aspect > ((320 / 1.2) / 192)) { + // wide width = 160; - //height = 160; - //height = 192; - let dar = 1.2 / 2; - height = (width * image.bitmap.width / image.bitmap.height) * dar; - height = Math.round(height); + height = Math.round((width * image.bitmap.height / image.bitmap.width) * dar); if (height & 1) { height++; } - image = image.resize(width, height); + } else { + // tall + height = 192; + width = Math.round((height * image.bitmap.width / image.bitmap.height) / dar); + if (width & 1) { + width++; + } } + image = image.resize(width, height); let rgba = image.bitmap.data.slice(); return { @@ -823,17 +842,15 @@ async function convert(source) { height, rgba } = await loadImage(source); + console.log({width,height}); - if (width !== 160) { - throw new Error(`expected 160px-compatible width, got ${width} pixels`); + if (width > 160) { + throw new Error(`expected <160px width, got ${width} pixels`); } - /* - if (height !== 160) { - // @fixme support up to 240px - throw new Error(`expected 160px height, got ${height} pixels`); + if (height > 192) { + throw new Error(`expected <192px height, got ${height} pixels`); } - */ if (rgba.length != width * 4 * height) { console.log(` @@ -860,10 +877,26 @@ async function convert(source) { allColors.push(i); } + let left = [], right = []; + let padding = 0; + if (width < 160) { + padding = 160 - width; + + let black = new RGB(0, 0, 0); + left = repeat(black, padding >> 1); + right = repeat(black, padding + 1 >> 1); + } + let lines = []; for (let y = 0; y < height; y++) { let inputLine = input .slice(y * width, (y + 1) * width); + + if (padding) { + console.log(`length was ${inputLine.length}`); + inputLine = left.concat(inputLine, right); + console.log(`length is now ${inputLine.length}`); + } if (y > 0) { let error = lines[y - 1].error; inputLine = inputLine.map((rgb, x) => rgb.add(error[x]).clamp()); @@ -872,7 +905,7 @@ async function convert(source) { lines.push(line); } return { - width, + width: width + padding, height, lines }; @@ -983,7 +1016,7 @@ ${byte2byte(odd(frame.palette3))} .align 1024 displaylist: ; 24 lines overscan - .repeat 4 + .repeat 3 .byte $70 ; 8 blank lines .endrep ; include a DLI to mark us as frame 0 diff --git a/dither4.s b/dither4.s index 64a570d..b985633 100644 --- a/dither4.s +++ b/dither4.s @@ -34,8 +34,7 @@ bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 -;scanline_offset = 46 -scanline_offset = 46 +scanline_offset = 38 scanline_max = (lines_per_frame - scanline_offset) / 2 .data