wip mostly fixed
This commit is contained in:
parent
9631e2e026
commit
b0e7d1f579
2 changed files with 57 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue