speice.io/blog/2024-11-15-playing-with-fire/3-log-density/index.mdx

81 lines
2.9 KiB
Plaintext
Raw Normal View History

2024-12-01 15:16:30 -05:00
---
slug: 2024/11/playing-with-fire-log-density
2024-12-02 22:36:25 -05:00
title: "Playing with fire: Log-density and color"
2024-12-01 15:16:30 -05:00
date: 2024-11-15 14:00:00
authors: [bspeice]
tags: []
---
So far, our `plot()` function has been fairly simple; map an input coordinate
to a specific pixel, and color in that pixel.
This works well for simple function systems (like Sierpinski's Gasket),
but more complex systems (like our reference parameters) produce grainy images.
2024-12-13 20:03:53 -05:00
Every additional time we plot a pixel, we're wasting work.
Can we do something more intelligent instead?
2024-12-01 15:16:30 -05:00
<!-- truncate -->
## Image histograms
2024-12-09 22:18:13 -05:00
:::note
This post covers sections 4 and 5 of the Fractal Flame Algorithm paper
:::
2024-12-01 15:16:30 -05:00
To start with, it's worth demonstrating how much work is actually "wasted."
2024-12-13 20:03:53 -05:00
Previously, pixels would be either transparent or opaque depending on whether
we encountered them while running the chaos game.
We'll render the reference image again, but this time, keep track of how many times
we encounter each pixel during the chaos game. At the end, we'll "paint" our final image
by setting each pixel's transparency based on how frequently we encounter it:
2024-12-01 15:16:30 -05:00
import CodeBlock from "@theme/CodeBlock";
2024-12-01 21:57:10 -05:00
import paintLinearSource from "!!raw-loader!./paintLinear"
<CodeBlock language="typescript">{paintLinearSource}</CodeBlock>
2024-12-08 22:50:46 -05:00
import {SquareCanvas} from "../src/Canvas";
import FlameHistogram from "./FlameHistogram";
2024-12-01 21:57:10 -05:00
import {paintLinear} from "./paintLinear";
2024-12-08 22:50:46 -05:00
<SquareCanvas><FlameHistogram quality={5} paint={paintLinear}/></SquareCanvas>
2024-12-01 21:57:10 -05:00
## Log display
2024-12-13 20:03:53 -05:00
Using a histogram to paint our image is definitely a quality improvement,
but it produces "ghostly" images. In our reference parameters, the outer circle
is preserved, but the interior appears to be missing!
To fix this, we'll introduce the second major innovation of the fractal flame algorithm: tone mapping.
This technique is used in computer graphics to adjust for the fact that
people perceive brightness on a logarithmic scale.
As a concrete example, high dynamic range (HDR) photography uses this technique to capture
nice images of scenes with very different brightness levels. If you want to take a picture of something dark,
you need a long exposure time. However, long exposures lead to bright spots that "wash out" and become nothing but white.
If we take multiple images using different exposure times, we can blend them together to create
a final image where everything is visible.
TODO: HDR link?
In fractal flames, this "tone map" is accomplished
import paintLogarithmicSource from "!!raw-loader!./paintLogarithmic"
<CodeBlock language="typescript">{paintLogarithmicSource}</CodeBlock>
2024-12-01 21:57:10 -05:00
import {paintLogarithmic} from './paintLogarithmic'
2024-12-08 22:50:46 -05:00
<SquareCanvas><FlameHistogram quality={10} paint={paintLogarithmic}/></SquareCanvas>
2024-12-02 22:36:25 -05:00
## Color
import paintColorSource from "!!raw-loader!./paintColor"
<CodeBlock language="typescript">{paintColorSource}</CodeBlock>
2024-12-02 22:36:25 -05:00
import FlameColor from "./FlameColor";
2024-12-08 22:50:46 -05:00
<SquareCanvas><FlameColor quality={15}/></SquareCanvas>