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...