mirror of
https://github.com/bspeice/speice.io
synced 2024-12-23 00:58:09 -05:00
79 lines
1.9 KiB
TypeScript
79 lines
1.9 KiB
TypeScript
import { histIndex, imageIndex } from "./0-utility";
|
|
import { camera } from "./2a-variations";
|
|
import { flameFinal, FlameFinal } from "./2c-final";
|
|
|
|
export abstract class Accumulator {
|
|
histogram: number[] = [];
|
|
|
|
constructor(
|
|
protected readonly width: number,
|
|
protected readonly height: number
|
|
) {
|
|
for (var i = 0; i < width * height; i++) {
|
|
this.histogram.push(0);
|
|
}
|
|
}
|
|
|
|
accumulate(x: number, y: number) {
|
|
const [pixelX, pixelY] = camera(x, y, this.width);
|
|
|
|
if (
|
|
pixelX < 0 ||
|
|
pixelX >= this.width ||
|
|
pixelY < 0 ||
|
|
pixelY >= this.height
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const index = histIndex(pixelX, pixelY, this.width);
|
|
this.histogram[index] += 1;
|
|
}
|
|
|
|
abstract render(image: ImageData): void;
|
|
}
|
|
|
|
class AccumulateBinary extends Accumulator {
|
|
render(image: ImageData) {
|
|
for (var x = 0; x < image.width; x++) {
|
|
for (var y = 0; y < image.height; y++) {
|
|
const index = histIndex(x, y, image.width);
|
|
|
|
// Color black if this pixel is part of the solution set, white otherwise
|
|
const value = this.histogram[index] > 0 ? 0 : 0xff;
|
|
|
|
const iIdx = imageIndex(x, y, image.width);
|
|
image.data[iIdx + 0] = value;
|
|
image.data[iIdx + 1] = value;
|
|
image.data[iIdx + 2] = value;
|
|
image.data[iIdx + 3] = value ? 0xff : 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export function render(
|
|
flame: FlameFinal,
|
|
quality: number,
|
|
accumulator: Accumulator,
|
|
image: ImageData
|
|
) {
|
|
const iterations = quality * image.width * image.height;
|
|
|
|
for (var i = 0; i < iterations; i++) {
|
|
flame.step();
|
|
|
|
if (i > 20) {
|
|
const [flameX, flameY] = flame.current();
|
|
accumulator.accumulate(flameX, flameY);
|
|
}
|
|
}
|
|
|
|
accumulator.render(image);
|
|
}
|
|
|
|
export function renderBinary(image: ImageData) {
|
|
const accumulator = new AccumulateBinary(image.width, image.height);
|
|
render(flameFinal, 10, accumulator, image);
|
|
}
|