Skip to content

Instantly share code, notes, and snippets.

@geelen
Last active June 2, 2018 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geelen/1f9ebc3ee6a1c159f76e48f6a7ca935c to your computer and use it in GitHub Desktop.
Save geelen/1f9ebc3ee6a1c159f76e48f6a7ca935c to your computer and use it in GitHub Desktop.
(async () => {
const cols = 44
const rows = 36
const size = 90
const speedX = 0.02
const speedY = 0.0
const loadImage = url => {
const img = document.createElement('img')
img.crossOrigin = true
return new Promise(resolve => {
img.onload = () => resolve(img)
img.src = url
})
}
document.body.innerHTML = ''
document.body.style = 'margin: 0; background: palegoldenrod; display: flex; flex-direction: column; justify-content: center; align-items: center;'
// const img = await loadImage('https://i.imgur.com/umlMniN.png')
// const img = await loadImage('https://i.imgur.com/AVjtBoG.png')
const img = await loadImage('https://i.imgur.com/VhXMCPu.png')
const imgHeight = Math.round(size / img.width * img.height)
window.img = img
const canvas = document.createElement('canvas')
window.canvas = canvas
canvas.width = size * Math.ceil(cols / size)
canvas.height = imgHeight * Math.ceil(rows / imgHeight)
const ctx = canvas.getContext('2d')
window.ctx = ctx
document.body.appendChild(canvas)
const textarea = document.createElement('textarea')
textarea.addEventListener('click', textarea.select)
document.body.appendChild(textarea)
const output = document.createElement('canvas')
output.width = cols
output.height = rows
output.style = 'background: white; width: 440px; height: 360px; image-rendering: pixelated'
const ctx2 = output.getContext('2d')
document.body.appendChild(output)
ctx.fillStyle = 'black'
ctx.fillRect(0,0, canvas.width, canvas.height)
// ctx.imageSmoothingEnabled = false
const tile = (img, size, offset = 0) => {
let x = offset
while (x <= canvas.width) {
let y = offset
while (y <= canvas.height) {
ctx.drawImage(img, x, y, size, imgHeight)
y += imgHeight
}
x += size
}
}
tile(img, size)
const { data, width, height } = ctx.getImageData(0, 0, canvas.width, canvas.height)
const json = JSON.stringify({
width, height, data: [...data],
speedX, speedY
})
textarea.value = `const texture = ${json}`
// REPLACE THIS WITH THE JSON
const texture = JSON.parse(json)
// RENDER TO THE ARCH
function paintTexture(frame, rows, cols, frameX, frameY) {
const x_frac = frameX - Math.floor(frameX)
const y_frac = frameY - Math.floor(frameY)
const lerp = (line, j, x_a, x_b, y_a, y_b) => {
for (let i = 0; i < 3; i++) {
line[j * 3 + i] = (
x_frac * y_frac * texture.data[y_b + x_b + i] +
(1 - x_frac) * y_frac * texture.data[y_b + x_a + i] +
x_frac * (1 - y_frac) * texture.data[y_a + x_b + i] +
(1 - x_frac) * (1 - y_frac) * texture.data[y_a + x_a + i]
)
}
}
for (let i = 0; i < rows; i++) {
const texRowA = texture.width * 4 * (Math.floor(i + frameY) % texture.height)
const texRowB = texture.width * 4 * (Math.ceil (i + frameY) % texture.height)
const lineSize = cols * 3;
const line = frame.subarray(lineSize * i, lineSize* (i + 1));
for (let j = 0; j < cols; j++) {
const texColA = 4 * (Math.floor(j + frameX) % texture.width)
const texColB = 4 * (Math.ceil (j + frameX) % texture.width)
lerp(line, j, texColA, texColB, texRowA, texRowB)
}
}
}
/*export*/ function transform(buffer, rows, cols, frameCount, fps, isFirst) {
const frameSize = 3 * rows * cols;
for (let i = 0; i < frameCount; i++) {
const second = i / fps;
const frame = new Uint8Array(buffer, frameSize * i, frameSize);
paintTexture(frame, rows, cols, 10000 + i * texture.speedX, 10000 + i * texture.speedY)
}
}
/*
export default function () {
return Promise.resolve({
transform,
})
}
*/
// END RENDER CODE
const frameCount = 35 * 2
const frameSize = 3 * 36 * 44
const fps = 35
const buffer = new ArrayBuffer(rows * cols * 3 * frameCount)
transform(buffer, rows, cols, frameCount, fps, false)
window.buffer = buffer
if (window.lastTimeout) clearTimeout(window.lastTimeout)
let frameNr = 0
const draw = () => {
window.lastTimeout = setTimeout(draw, Math.round(1000 / fps))
const frame = new ImageData(44, 36)
const image = new Uint8Array(buffer, frameNr * frameSize, frameSize)
for (let i = 0; i < frameSize; i++) {
frame.data[i * 4 + 0] = image[i * 3 + 0]
frame.data[i * 4 + 1] = image[i * 3 + 1]
frame.data[i * 4 + 2] = image[i * 3 + 2]
frame.data[i * 4 + 3] = 255
}
ctx2.putImageData(frame, 0, 0)
frameNr = (frameNr + 1) % frameCount
}
draw()
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment