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