Last active
June 3, 2018 14:06
-
-
Save geelen/f33a8f7a17d776265fff6de05d190f4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(async () => { | |
const rows = 44 | |
const cols = 36 | |
const fps = 12 | |
const gif = "http://i.imgur.com/ifR7csn.gif" | |
const rotate = false | |
const mirror = false | |
const vertmirror = false | |
document.body.innerHTML = '' | |
document.body.style = 'margin: 0; background: palegoldenrod; display: flex; flex-direction: column; justify-content: center; align-items: center;' | |
const canvas = document.createElement('canvas') | |
canvas.style = 'width: 360px; height: 440px; image-rendering: pixelated; transform: scaleY(-1);' | |
canvas.width = cols | |
canvas.height = rows | |
const ctx = canvas.getContext('2d') | |
window.ctx = ctx | |
document.body.appendChild(canvas) | |
const textarea = document.createElement('textarea') | |
textarea.addEventListener('click', textarea.select) | |
textarea.style = 'height: 100px; width: 360px;' | |
const button = document.createElement('button') | |
button.type = button | |
button.disabled = true | |
button.innerHTML = "Loading X-GIF..." | |
const link = document.createElement('link'); | |
link.rel = 'import'; | |
link.href = 'http://geelen.github.io/x-gif/dist/x-gif.html'; | |
link.setAttribute('async', true); // make it async! | |
const loaded = new Promise(res => link.onload = res) | |
document.head.appendChild(link) | |
await loaded | |
button.innerHTML = "Loading gif..." | |
const xgif = document.createElement('x-gif') | |
xgif.setAttribute('src', gif) | |
await xgif.controller.playback.ready | |
// document.body.appendChild(xgif) | |
console.log(xgif) | |
button.addEventListener('click', () => { | |
textarea.value = 'Rendering string...\n(This can take a while)\n(Your browser will lock up)\n(#sorrynotsorry)' | |
document.body.appendChild(textarea) | |
button.style.display = 'none' | |
setTimeout(done, 100) | |
}) | |
document.body.appendChild(button) | |
button.innerHTML = "Animating..." | |
const frames = [] | |
let frameNr = 0 | |
const gif_frames = xgif.shadowRoot.querySelectorAll('img') | |
ctx.fillStyle = 'black' | |
ctx.fillRect(0,0, canvas.width, canvas.height) | |
if (window.lastTimeout) clearTimeout(window.lastTimeout) | |
const draw = () => { | |
if (xgif.controller.playback.gif.frames[frameNr].disposal === 2) { | |
ctx.fillRect(0,0, canvas.width, canvas.height) | |
} | |
// RENDER SOMETHING TO CANVAS | |
if (mirror) { | |
ctx.save() | |
ctx.translate(cols, 0) | |
ctx.rotate(Math.PI / 2) | |
ctx.drawImage(gif_frames[frameNr], 0 - 20, cols / 2, rows + 50, cols / 2 + 8) | |
ctx.restore() | |
ctx.save() | |
ctx.translate(cols / 2, 0) | |
ctx.rotate(Math.PI / 2) | |
ctx.scale(1, -1) | |
ctx.drawImage(gif_frames[frameNr], 0 - 20, 0, rows + 50, cols / 2 + 8) | |
ctx.restore() | |
} | |
else if (rotate) { | |
ctx.save() | |
ctx.translate(cols, 0) | |
ctx.rotate(Math.PI / 2) | |
ctx.drawImage(gif_frames[frameNr], 0, 0, rows, cols) | |
ctx.restore() | |
} else if (vertmirror) { | |
ctx.save() | |
ctx.translate(0, rows) | |
ctx.scale(1, -1) | |
ctx.drawImage(gif_frames[frameNr], 0, 0, cols, rows) | |
ctx.restore() | |
} else { | |
ctx.drawImage(gif_frames[frameNr], 0, 0, cols, rows) | |
} | |
// OK STOP NOW THANKS | |
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) | |
const rgbData = [] | |
imageData.data.forEach((x,i) => { | |
if (i % 4 !== 3) rgbData.push(x) | |
}) | |
frames.push(rgbData) | |
if (frameNr < gif_frames.length - 1) { | |
window.lastTimeout = setTimeout(draw, Math.round(1000 / fps)) | |
} else { | |
button.innerHTML = 'Render string' | |
button.disabled = false | |
} | |
frameNr++ | |
} | |
draw() | |
function done() { | |
const str = | |
`const frames_str = [ | |
${frames.map(frame => `"${btoa(frame.map(x => String.fromCharCode(x)).join(''))}"`).join(',\n')} | |
] | |
const frames = frames_str.map(str => { | |
const binstr = atob(str) | |
return [...binstr].map(char => char.charCodeAt(0)) | |
}) | |
export function transform(buffer, rows, cols, frameCount, fps, isFirst) { | |
const frameSize = 3 * rows * cols | |
const lineSize = cols * 3 | |
for (let i = 0; i < frameCount; i++) { | |
const frame = new Uint8Array(buffer, frameSize * i, frameSize) | |
const texture = frames[Math.floor(i/${35/fps}) % frames.length] | |
for (let j = 0; j < rows; j++) { | |
const line = frame.subarray(lineSize * j, lineSize* (j + 1)); | |
for (let k = 0; k < cols; k++) { | |
line[k * 3 + 0] = texture[j * cols * 3 + k * 3 + 0] | |
line[k * 3 + 1] = texture[j * cols * 3 + k * 3 + 1] | |
line[k * 3 + 2] = texture[j * cols * 3 + k * 3 + 2] | |
} | |
} | |
} | |
} | |
export default function () { | |
return Promise.resolve({ | |
transform, | |
}) | |
} | |
` | |
textarea.value = str | |
} | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment