This demo visualization shows a photomosaic (& videomosaic) implemented in hardware:
(press r to randomly pick another painting)
Strategy
A palette is built in software, comprising an array of paintings sorted in ascending order based on a selected lightness metric as the sorting criterion. The low-resolution texel produced by the pixelator (specifically, texture2D(source, stepCoord)) is then employed as a lookup key to sample the palette during the rendering of the mosaic tiles within the fragment shader.
Palette creation using p5.quadrille.js
Each painting in the data set is first pushed onto a paintings array:
let paintings
let n
function preload() {
// ...
paintings = []
for (let i = 1; i <= n; i++) {
paintings.push(loadImage(`p${i}.jpg`))
}
the obtained paintings array is used to create a palette quadrille which is then sorted (in ascending order) using the cell average LUMA (although other lightness metrics may too be employed as sorting criterion), and then rendered side-by-side onto a p5.Framebuffer object:
const SAMPLE_RES = 90
let palette
let fbo
function setup() {
// ...
palette = createQuadrille(paintings)
fbo = createFramebuffer({ width: SAMPLE_RES * palette.width,
height: SAMPLE_RES, format: FLOAT })
palette.sort({ ascending: true, cellLength: SAMPLE_RES })
fbo.begin()
drawQuadrille(palette, { cellLength: SAMPLE_RES,
outlineWeight: 0,
x: -SAMPLE_RES * palette.width / 2,
y: -SAMPLE_RES * palette.height / 2 })
fbo.end()
}
the resulting fbo should look like this:
is emitted as the uniform sampler2D palette to the shader where it is gets sampled to fill the mosaic tiles.
References
- wikipedia:
- Photographic Mosaic. Observation: the photomosaic implemented here is one of the “easy kinds” mentioned in this article.
- Ascii art
- Coding train ascii-text images implemented in software tutorial: