mirror of
https://github.com/bspeice/speice.io
synced 2024-12-22 16:48:10 -05:00
Color render working
This commit is contained in:
parent
2bee6142be
commit
ce1873147c
@ -22,11 +22,11 @@ export function* chaosGameFinal({width, height, transforms, final, quality, step
|
|||||||
[x, y] = transform(x, y);
|
[x, y] = transform(x, y);
|
||||||
|
|
||||||
// highlight-start
|
// highlight-start
|
||||||
[x, y] = final(x, y);
|
const [finalX, finalY] = final(x, y);
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
if (i > 20)
|
if (i > 20)
|
||||||
plot(x, y, image);
|
plot(finalX, finalY, image);
|
||||||
|
|
||||||
if (i % step === 0)
|
if (i % step === 0)
|
||||||
yield image;
|
yield image;
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import React, {useContext, useEffect, useState} from "react";
|
||||||
|
import * as params from "../src/params";
|
||||||
|
import {PainterContext} from "../src/Canvas";
|
||||||
|
import {chaosGameColor} from "./chaosGameColor";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
quality?: number;
|
||||||
|
children?: React.ReactElement;
|
||||||
|
}
|
||||||
|
export default function FlameHistogram({quality, children}: Props) {
|
||||||
|
const {width, height, setPainter} = useContext(PainterContext);
|
||||||
|
|
||||||
|
const [counter, setCount] = useState(0);
|
||||||
|
const [xform1Color, setXform1Color] = useState(params.xform1Color);
|
||||||
|
const [xform2Color, setXform2Color] = useState(params.xform2Color);
|
||||||
|
const [xform3Color, setXform3Color] = useState(params.xform3Color);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const gameParams = {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
transforms: params.xforms,
|
||||||
|
final: params.xformFinal,
|
||||||
|
quality,
|
||||||
|
palette: params.palette,
|
||||||
|
colors: [xform1Color, xform2Color, xform3Color]
|
||||||
|
}
|
||||||
|
setPainter(chaosGameColor(gameParams));
|
||||||
|
}, [counter, xform1Color, xform2Color, xform3Color]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
<button onClick={() => setCount(counter + 1)}>Re-render {counter}</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
import {ChaosGameFinalProps} from "../2-transforms/chaosGameFinal";
|
||||||
|
import {randomBiUnit} from "../src/randomBiUnit";
|
||||||
|
import {randomChoice} from "../src/randomChoice";
|
||||||
|
import {camera, histIndex} from "../src/camera";
|
||||||
|
import {colorFromPalette, paintColor} from "./color";
|
||||||
|
|
||||||
|
type ChaosGameHistogramProps = ChaosGameFinalProps & {
|
||||||
|
palette: number[];
|
||||||
|
colors: number[];
|
||||||
|
}
|
||||||
|
export function* chaosGameColor({width, height, transforms, final, palette, colors, quality, step}: ChaosGameHistogramProps) {
|
||||||
|
let iterations = (quality ?? 1) * width * height;
|
||||||
|
step = step ?? 100_000;
|
||||||
|
|
||||||
|
let currentColor = Math.random();
|
||||||
|
const red = Array(width * height).fill(0);
|
||||||
|
const green = Array(width * height).fill(0);
|
||||||
|
const blue = Array(width * height).fill(0);
|
||||||
|
const alpha = Array(width * height).fill(0);
|
||||||
|
|
||||||
|
let [x, y] = [randomBiUnit(), randomBiUnit()];
|
||||||
|
|
||||||
|
for (let i = 0; i < iterations; i++) {
|
||||||
|
const [transformIndex, transform] = randomChoice(transforms);
|
||||||
|
[x, y] = transform(x, y);
|
||||||
|
|
||||||
|
const [finalX, finalY] = final(x, y);
|
||||||
|
|
||||||
|
if (i > 20) {
|
||||||
|
const [pixelX, pixelY] = camera(finalX, finalY, width);
|
||||||
|
const pixelIndex = histIndex(pixelX, pixelY, width, 1);
|
||||||
|
|
||||||
|
if (pixelIndex < 0 || pixelIndex >= alpha.length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
currentColor = (currentColor + colors[transformIndex]) / 2;
|
||||||
|
const [r, g, b] = colorFromPalette(palette, currentColor);
|
||||||
|
red[pixelIndex] += r;
|
||||||
|
green[pixelIndex] += g;
|
||||||
|
blue[pixelIndex] += b;
|
||||||
|
alpha[pixelIndex] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % step === 0)
|
||||||
|
yield paintColor(width, height, red, green, blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield paintColor(width, height, red, green, blue, alpha);
|
||||||
|
}
|
@ -8,7 +8,7 @@ export type ChaosGameHistogramProps = ChaosGameFinalProps & {
|
|||||||
painter: (width: number, histogram: Uint32Array) => ImageData;
|
painter: (width: number, histogram: Uint32Array) => ImageData;
|
||||||
}
|
}
|
||||||
export function* chaosGameHistogram({width, height, transforms, final, quality, step, painter}: ChaosGameHistogramProps) {
|
export function* chaosGameHistogram({width, height, transforms, final, quality, step, painter}: ChaosGameHistogramProps) {
|
||||||
let iterations = (quality ?? 10) * width * height;
|
let iterations = (quality ?? 1) * width * height;
|
||||||
step = step ?? 100_000;
|
step = step ?? 100_000;
|
||||||
|
|
||||||
const histogram = new Uint32Array(width * height);
|
const histogram = new Uint32Array(width * height);
|
||||||
|
29
blog/2024-11-15-playing-with-fire/3-log-density/color.ts
Normal file
29
blog/2024-11-15-playing-with-fire/3-log-density/color.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import {histIndex} from "../src/camera";
|
||||||
|
|
||||||
|
export function colorFromPalette(palette: number[], colorIndex: number): [number, number, number] {
|
||||||
|
const paletteIndex = Math.floor(colorIndex * (palette.length / 3)) * 3;
|
||||||
|
return [palette[paletteIndex], palette[paletteIndex + 1], palette[paletteIndex + 2]];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function paintColor(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
red: number[],
|
||||||
|
green: number[],
|
||||||
|
blue: number[],
|
||||||
|
alpha: number[]
|
||||||
|
): ImageData {
|
||||||
|
const image = new ImageData(width, height);
|
||||||
|
|
||||||
|
for (let i = 0; i < width * height; i++) {
|
||||||
|
const alphaScale = Math.log10(alpha[i]) / (alpha[i] * 1.5);
|
||||||
|
|
||||||
|
const pixelIndex = i * 4;
|
||||||
|
image.data[pixelIndex] = red[i] * alphaScale * 0xff;
|
||||||
|
image.data[pixelIndex + 1] = green[i] * alphaScale * 0xff;
|
||||||
|
image.data[pixelIndex + 2] = blue[i] * alphaScale * 0xff;
|
||||||
|
image.data[pixelIndex + 3] = alpha[i] * alphaScale * 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
slug: 2024/11/playing-with-fire-log-density
|
slug: 2024/11/playing-with-fire-log-density
|
||||||
title: "Playing with fire: Log-density display"
|
title: "Playing with fire: Log-density and color"
|
||||||
date: 2024-11-15 14:00:00
|
date: 2024-11-15 14:00:00
|
||||||
authors: [bspeice]
|
authors: [bspeice]
|
||||||
tags: []
|
tags: []
|
||||||
@ -32,10 +32,16 @@ import Canvas from "../src/Canvas";
|
|||||||
import FlameHistogram from "./FlameHistogram";
|
import FlameHistogram from "./FlameHistogram";
|
||||||
import {paintLinear} from "./paintLinear";
|
import {paintLinear} from "./paintLinear";
|
||||||
|
|
||||||
<Canvas><FlameHistogram quality={5} paintFn={paintLinear}/></Canvas>
|
<!-- <Canvas><FlameHistogram quality={0.5} paintFn={paintLinear}/></Canvas> -->
|
||||||
|
|
||||||
## Log display
|
## Log display
|
||||||
|
|
||||||
import {paintLogarithmic} from './paintLogarithmic'
|
import {paintLogarithmic} from './paintLogarithmic'
|
||||||
|
|
||||||
<Canvas><FlameHistogram quality={10} paintFn={paintLogarithmic}/></Canvas>
|
<!-- <Canvas><FlameHistogram quality={0.5} paintFn={paintLogarithmic}/></Canvas> -->
|
||||||
|
|
||||||
|
## Color
|
||||||
|
|
||||||
|
import FlameColor from "./FlameColor";
|
||||||
|
|
||||||
|
<Canvas><FlameColor quality={10}/></Canvas>
|
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
slug: 2024/11/playing-with-fire-color
|
|
||||||
title: "Playing with fire: Color"
|
|
||||||
date: 2024-11-15 15:00:00
|
|
||||||
authors: [bspeice]
|
|
||||||
tags: []
|
|
||||||
---
|
|
@ -76,7 +76,7 @@ export const xforms: [number, Transform][] = [
|
|||||||
|
|
||||||
export const xformFinal: Transform = applyPost(xformFinalCoefsPost, applyTransform(xformFinalCoefs, xformFinalVariations));
|
export const xformFinal: Transform = applyPost(xformFinalCoefsPost, applyTransform(xformFinalCoefs, xformFinalVariations));
|
||||||
|
|
||||||
export const palette =
|
export const paletteString =
|
||||||
"7E3037762C45722B496E2A4E6A2950672853652754632656" +
|
"7E3037762C45722B496E2A4E6A2950672853652754632656" +
|
||||||
"5C265C5724595322574D2155482153462050451F4E441E4D" +
|
"5C265C5724595322574D2155482153462050451F4E441E4D" +
|
||||||
"431E4C3F1E473F1E453F1E433F1E3F3F1E3B3E1E393E1E37" +
|
"431E4C3F1E473F1E453F1E433F1E3F3F1E3B3E1E393E1E37" +
|
||||||
@ -109,3 +109,13 @@ export const palette =
|
|||||||
"E9A411E5A313E1A113DD9F13D99D14D49C15D09815CC9518" +
|
"E9A411E5A313E1A113DD9F13D99D14D49C15D09815CC9518" +
|
||||||
"C79318C38F1ABE8B1AB9871DB4811FB07D1FAB7621A67123" +
|
"C79318C38F1ABE8B1AB9871DB4811FB07D1FAB7621A67123" +
|
||||||
"A16A249C6227975E289256298E502A89482C853F2D803A2E"
|
"A16A249C6227975E289256298E502A89482C853F2D803A2E"
|
||||||
|
|
||||||
|
function hexToBytes(hex: string) {
|
||||||
|
let bytes: number[] = [];
|
||||||
|
for (let i = 0; i < hex.length; i += 2) {
|
||||||
|
bytes.push(parseInt(hex.substring(i, i + 2), 16));
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const palette = hexToBytes(paletteString).map(value => value / 0xff);
|
Loading…
Reference in New Issue
Block a user