-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathselfieripple.html
107 lines (106 loc) · 3.29 KB
/
selfieripple.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!DOCTYPE html>
<html>
<head>
<title>Port of 0xabad1dea's ioripple.asm</title>
</head>
<body style="background-color: black; color: white">
<canvas id="maincanvas" width="320" height="200" style="width: 640px; height: 400px"></canvas>
<img src="abad1dea_iss_cropped.png" id="selfie" alt="selfie">
<p>Port of <a href="http://0xabad1dea.github.io/">0xabad1dea's ioripple.asm demo</a></p>
<script>
"use strict";
window.onload = function() {
var width = 320;
var height = 200;
var canvas = document.getElementById("maincanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 320, 200);
var selfie = document.getElementById("selfie");
ctx.drawImage(selfie, 0, 0);
var imageData = ctx.getImageData(0, 0, width, height);
var imageDataData = imageData.data;
var fbData = new Uint8Array(width * height);
var palette = new Uint32Array(0x100);
/* generate the palette. I think. "noice steel blue generator". */
for (var i = 0; i < 0x100; i++) {
var red = (((i >> 1) | 8) + 60) & 0xff;
var green = (red - 60) & 0xff;
var blue = green;
red = (red << 2) & 0xff;
green = (green << 2) & 0xff;
blue = (blue << 2) & 0xff;
palette[i] = (red << 16) | (green << 8) | blue;
}
/* end palette. */
function processSelfie() {
var dataAddr = 0;
for (var i = 0; i < width * height; i++) {
var r = imageDataData[dataAddr++];
var g = imageDataData[dataAddr++];
var b = imageDataData[dataAddr++];
dataAddr++;
var combinedVal = (r + g + b) / 6;
fbData[i] = combinedVal;
}
}
processSelfie();
var frameCounter = 0;
function masterJump() {
if (frameCounter < 8) {
/* smooth: "slightly modified from bla's smoothing filter" */
for (var i = (width * height) - width - 1; i >= width; i--) {
var value = fbData[i];
var oneRowUp = fbData[i - width];
value += oneRowUp;
var oneRowDown = fbData[i + width];
value += oneRowDown;
var twoToTheLeft = fbData[i - 2];
value += twoToTheLeft;
var oneToTheRight = fbData[i + 1];
value += oneToTheRight;
value = (value << 3) / 40;
/* it's an average: 5 values * 8 = 40 * average value */
fbData[i] = value & 0xff;
}
} else {
/* Ripple implementation. As the original author claims:
* "and here is my beautiful and elegant and lovely rippler
* a maximally clever person could probably find a way to do both filters in
* one pass but if I were maximally clever I would be doing something more useful". */
for (var i = (width * height) - width - 1; i >= width; i--) {
var value = fbData[i];
var oneToTheRight = fbData[i + 1];
value += oneToTheRight;
var oneToTheLeft = fbData[i - 1];
value += oneToTheLeft;
var oneRowUp = fbData[i - width];
value += oneRowUp;
var oneRowDown = fbData[i + width];
value += oneRowDown;
value = (value >> 5) - fbData[i];
value -= (fbData[i] >> 1);
/* this makes no sense. */
fbData[i] = value & 0xff;
}
}
frameCounter = (frameCounter + 1) % 9;
blitFramebuffer();
}
function blitFramebuffer() {
for (var i = 0; i < width * height; i++) {
var imgIndex = i << 2;
var value = fbData[i];
var color = palette[value];
imageDataData[imgIndex++] = (color >> 16) & 0xff;
imageDataData[imgIndex++] = (color >> 8) & 0xff;
imageDataData[imgIndex++] = (color) & 0xff;
}
ctx.putImageData(imageData, 0, 0);
}
setInterval(masterJump, 500);
blitFramebuffer();
}
</script>
</body>
</html>