Blursort Web
Image de-composition and re-composition using blursort algorithm
by nicobrenner
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Blursort Web - https://twitter.com/nicobrenner</title>
</head>
<body>
<style>
img {
padding-right: 10px;
cursor: pointer;
}
canvas#canvas {
display: inline-block;
}
canvas#frame_canvas {
display: inline-block;
}
label#frames_label {
display: block;
}
#controls {
padding-bottom: 10px;
width: 50%;
}
</style>
<div id="info">
<p>📼 <a href='https://twitter.com/nicobrenner/status/1689739812511825921?s=20' target="_blank">Video: How to make a basic animation with blursort</a></p>
<p>📼 <a href='https://twitter.com/nicobrenner/status/1690833827214876672?s=20' target="_blank">Video: How to make an automatic animation with blursort</a></p>
</div>
<div id="controls">
<p>1) <input type='button' id="actualizar" value="Load image from URL"/>
<label for="imagen">Image URL:</label>
<input type="text" id="imagen" size='60' name="imagen" value="https://pbs.twimg.com/media/F3cEadJWIAAcUOg?format=webp&name=large">
</p>
<p>2) Apply effects, create frames and animate</p>
<input type='button' id="blursort" value="Blursort"/>
<input type='button' id="unblursort" value="Un-Blursort"/>
<input type='button' id="blursort_top" value="Blursort Top"/>
<input type='button' id="blursort_top_left" value="Blursort Top Left"/>
<input type='button' id="blursort_bottom" value="Blursort Bottom"/>
<input type='button' id="blursort_4x4" value="Blursort 4x4"/>
<input type='button' id="blursort_2x2" value="Blursort 2x2"/>
<input type='button' id="blursort_horizon" value="Blursort Horizon"/>
<input type='button' id="invert" value="Invert"/>
<input type='button' id="clear" value="Re-load and Clear Frames"/>
<select id='extract_frames'>
<option value="1" selected="selected">4</option>
<option value="2">16</option>
<option value="3">64</option>
</select>
<input type='button' id="extract_frames_button" value="Extract Frames"/>
<input...
JavaScript
var img = new Image();
var transformations = 0;
img.crossOrigin = 'anonymous';
var mapas_blursort = {}
var arreglo_frames = []
var extracting_frames = false
imagen_el = document.getElementById('imagen')
img.src = imagen_el.value
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d', {willReadFrequently: true});
var original_width = -1
var original_height = -1
canvas.width = img.width
canvas.height = img.height
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
var original = function() {
ctx.drawImage(img, 0, 0);
};
var animation_direction_forward = true
function toggle_animation_direction() {
if (animation_direction_forward) {
animation_direction_forward = false
}
else {
animation_direction_forward = true
}
}
var animation_running = false
function toggle_animation() {
window.clearTimeout();
if (animation_running) {
animation_running = false
}
else {
animate()
animation_running = true
}
}
function animate() {
console.log('animando ' + arreglo_frames.length + ' frames')
var secs = document.getElementById('tiempo').value
var cb = document.getElementById('clear_between_frames')
var clear_canvas = true
if (!cb.checked) {
clear_canvas = false
}
if (animation_direction_forward) {
var k = 0;
for (i = 0; i < arreglo_frames.length; i++) {
setTimeout(function() {
if (animation_running) {
if (clear_canvas) { ctx.clearRect(0, 0, canvas.width, canvas.height); }
ctx.drawImage(arreglo_frames[k], 0, 0);
if ((k + 1) === arreglo_frames.length) {
if (animation_running) {
setTimeout(function() { animate() }, (secs * 1000))}
}
else { k++; }
}
}, (secs * 1000) * i)
}
} else {
var k = arreglo_frames.length - 1;
for (i = arreglo_frames.length - 1; i >= 0; i--) {
setTimeout(function() {
if (animation_running) {
if...