Published
Edited
Dec 2, 2020
5 forks
23 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
img = world.image()
Insert cell
Insert cell
imgWidth = img.naturalWidth
Insert cell
imgHeight = img.naturalHeight
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
canvas = {
const ny = imgHeight / tileSize
const w = nx * tileSize
const h = ny * tileSize
const context = DOM.context2d(w, h)

// we draw the image to the canvas
context.drawImage(await img, -dx * tileSize, 0)
// and get the pixels colors
const imageData = context.getImageData(0, 0, w * devicePixelRatio, h * devicePixelRatio)

// from imageData, we search unique tiles and create a map of the tiles
const tiles = []
const mapData = context.createImageData(nx, ny)
let mapIndex = 0

for(let y = 0; y < ny; y ++) {
for(let x = 0; x < nx; x ++) {
const tileData = context.createImageData(tileSize * devicePixelRatio, tileSize * devicePixelRatio)
let tileIndex = 0
let tileID = ''
let average = [0, 0, 0]
for(let yy = 0; yy < tileSize * devicePixelRatio; yy ++) {
for(let xx = 0; xx < tileSize * devicePixelRatio; xx ++) {
const pixelX = x * tileSize * devicePixelRatio + xx
const pixelY = y * tileSize * devicePixelRatio + yy
const pixelIndex = (pixelY * (w * devicePixelRatio) + pixelX) * 4
for(let i = 0; i < 4; i++) {
tileData.data[tileIndex ++] = imageData.data[pixelIndex + i]
if(xx > 0 && xx < tileSize * devicePixelRatio - 1 &&
yy > 0 && yy < tileSize * devicePixelRatio - 1 && i < 3) {
average[i] += imageData.data[pixelIndex + i]
if(xx % 2 == 0 && yy % 2 == 0) tileID += imageData.data[pixelIndex + i].toString(36)
}
}
}
}
average = average.map(d => d / ((tileSize * devicePixelRatio - 2) ** 2) | 0)
// if the tile is already referenced we use its index as grey level for our map of tiles
let c = tiles.findIndex(tile => tile.tileID === tileID)
// else we add it to our unique tiles and use its index as grey level for our map of tiles
if(c === - 1) {
tiles.push({ tileData, tileID })
c = tiles.length - 1
}

mapData.data[mapIndex] = c
mapData.data[mapIndex + 1] = c
mapData.data[mapIndex + 2] = c
mapData.data[mapIndex + 3] = 255
mapIndex += 4
}
}
const image = new Image()
image.style.border = 'solid 1px red'
image.src = context.canvas.toDataURL('image/png')
image.mapData = mapData
image.tiles = tiles
return image
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
nxOutput = 60
Insert cell
nyOutput = 20
Insert cell
model = new wfc.OverlappingModel(canvas.mapData.data, nx, imgHeight / tileSize, 2, nxOutput, nyOutput, true, false, 1, 0)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more