Permalink
Browse files

move heavy lifting into a web worker. chrome does not seem to support…

… this out of the box, but ff and safari work fine. Safari is handling this number crunching about 5x as fast as firefox 3.5 currently.
  • Loading branch information...
1 parent c046cd0 commit 648ca0d95a10ba92393326859e372146b7edab5e mpd committed May 18, 2010
Showing with 132 additions and 115 deletions.
  1. +4 −2 heatmap.html
  2. +14 −113 heatmap.js
  3. +114 −0 render_worker.js
View
@@ -7,8 +7,10 @@
<img id="trackme" src="img.jpg" />
</div>
- <button id="doRender">RENDER</button>
-
+ <button type="button" id="doRender">RENDER</button>
+ <div id="render-time">
+ Render Time: <span class="time">0</span> sec
+ </div>
<div id="result_container" style="position: relative;">
<img id="result" src="img.jpg" />
<canvas id="overlay" style="opacity: 0.5; position: absolute; top: 0; left: 0;"></canvas>
View
@@ -12,7 +12,17 @@ $(function () {
hueToRGB,
heatMask,
clickMask,
- applyMask;
+ applyMask,
+ worker,
+ renderStartTime;
+
+ worker = new Worker('render_worker.js');
+ worker.onmessage = function (event) {
+ renderHeat(JSON.parse(event.data).heat);
+ $('#render-time .time').text((new Date().getTime() - renderStartTime) / 1000);
+ renderStartTime = 0;
+ $('#doRender').removeAttr('disabled');
+ };
// mask we apply to a point that is moused over.
heatMask = [
@@ -77,107 +87,6 @@ $(function () {
applyMask(heatMask, eventX, eventY);
});
- /*
- * normalize to a 0-255 range
- */
- normalizeHeat = function (heat) {
- var minHeat, maxHeat, heatValues = [], normalizedHeat = {},
- denominator;
-
- $.each(heat, function (key, value) {
- heatValues.push(value);
- });
-
- minHeat = Math.min.apply(window, heatValues);
- maxHeat = Math.max.apply(window, heatValues);
-
- denominator = maxHeat - minHeat;
-
- if (denominator === 0 || denominator === Number.NEGATIVE_INFINITY) {
- denominator = 1;
- }
-
- $.each(heat, function (key, value) {
- normalizedHeat[key] = Math.floor(255 * ((value - minHeat) / denominator));
- });
-
- return normalizedHeat;
- };
-
-
- (function () {
- var gaussian, smoothedHeat, x, y, splitKey,
- i, j, result, heatVal;
-
- gaussian = [
- [2, 4, 5, 4, 2],
- [4, 9, 12, 9, 4],
- [5, 12, 15, 12, 5],
- [4, 9, 12, 9, 4],
- [2, 4, 5, 4, 2]
- ];
-
- /*
- * smooth out the edges with a gaussian blur
- * kernel taken from http://www.bv2.co.uk/?p=511
- * so I don't have to tool around with that right now.
- * replace with your own at your leisure.
- */
- smoothHeat = function (heat) {
- smoothedHeat = {};
-
- for (x = 0; x < canvasWidth; x += 1) {
- for (y = 0; y < canvasHeight; y += 1) {
- result = 0;
- // assume a 5x5 gaussian kernel here
- for (i = x - 2; i <= x + 2; i += 1) {
- if (i < 0 || i >= canvasWidth) {
- continue;
- }
-
- for (j = y - 2; j <= y + 2; j += 1) {
- if (j < 0 || j >= canvasHeight) {
- continue;
- }
-
- heatVal = heat[i + "," + j] || 0;
- result += heatVal * gaussian[i - (x - 2)][j - (y - 2)];
- }
- }
-
- // multiply by reciprocal of sum of the gaussian kernel
- // or divide by sum, as we do here.
- if (result > 0) {
- result /= 159;
- smoothedHeat[x + "," + y] = result;
- }
- }
- }
-
-// $.each(heat, function (key, value) {
-// result = 0;
-// splitKey = key.split(',');
-// x = parseInt(splitKey[0], 10);
-// y = parseInt(splitKey[1], 10);
-//
-// // assume a 5x5 gaussian kernel here
-// for (i = x - 2; i <= x + 2; i += 1) {
-// for (j = y - 2; j <= y + 2; j += 1) {
-// heatVal = heat[i + "," + j] || 0;
-// result += heatVal * gaussian[i - (x - 2)][j - (y - 2)];
-// }
-// }
-//
-// // multiply by reciprocal of sum of the gaussian kernel
-// // or divide by sum, as we do here.
-// result /= 159;
-// smoothedHeat[key] = result;
-// });
-
- return smoothedHeat;
- };
- }());
-
renderHeat = function (heat) {
var x, y, splitKey, rgb;
@@ -287,19 +196,11 @@ $(function () {
return cache.hueToRGB[cachekey];
};
- window.doRender = function () {
- renderHeat(normalizeHeat(smoothHeat(heat)));
- };
-
$('#doRender').click(function (e) {
- window.doRender();
+ $(this).attr('disabled', 'disabled');
+ renderStartTime = new Date().getTime();
+ worker.postMessage(JSON.stringify({heat: heat, width: canvasWidth, height: canvasHeight}));
e.preventDefault();
});
-// setInterval(function () {
-// renderHeat(normalizeHeat(smoothHeat(heat)));
-
- // run with no smoothing. faster, but ugly as hell.
-// renderHeat(normalizeHeat(heat));
-// }, 500);
});
View
@@ -0,0 +1,114 @@
+(function () {
+ var smoothHeat, normalizeHeat, canvasWidth, canvasHeight;
+
+ onmessage = function (event) {
+ var data = JSON.parse(event.data);
+ canvasWidth = data.width;
+ canvasHeight = data.height;
+ postMessage(JSON.stringify({heat: normalizeHeat(smoothHeat(data.heat))}));
+ };
+
+
+ (function () {
+ var gaussian, smoothedHeat, x, y, splitKey,
+ i, j, result, heatVal;
+
+ gaussian = [
+ [2, 4, 5, 4, 2],
+ [4, 9, 12, 9, 4],
+ [5, 12, 15, 12, 5],
+ [4, 9, 12, 9, 4],
+ [2, 4, 5, 4, 2]
+ ];
+
+ /*
+ * smooth out the edges with a gaussian blur
+ * kernel taken from http://www.bv2.co.uk/?p=511
+ * so I don't have to tool around with that right now.
+ * replace with your own at your leisure.
+ */
+ smoothHeat = function (heat) {
+ smoothedHeat = {};
+
+ for (x = 0; x < canvasWidth; x += 1) {
+ for (y = 0; y < canvasHeight; y += 1) {
+ result = 0;
+ // assume a 5x5 gaussian kernel here
+ for (i = x - 2; i <= x + 2; i += 1) {
+ if (i < 0 || i >= canvasWidth) {
+ continue;
+ }
+
+ for (j = y - 2; j <= y + 2; j += 1) {
+ if (j < 0 || j >= canvasHeight) {
+ continue;
+ }
+
+ heatVal = heat[i + "," + j] || 0;
+ result += heatVal * gaussian[i - (x - 2)][j - (y - 2)];
+ }
+ }
+
+ // multiply by reciprocal of sum of the gaussian kernel
+ // or divide by sum, as we do here.
+ if (result > 0) {
+ result /= 159;
+ smoothedHeat[x + "," + y] = result;
+ }
+ }
+ }
+
+// $.each(heat, function (key, value) {
+// result = 0;
+// splitKey = key.split(',');
+// x = parseInt(splitKey[0], 10);
+// y = parseInt(splitKey[1], 10);
+//
+// // assume a 5x5 gaussian kernel here
+// for (i = x - 2; i <= x + 2; i += 1) {
+// for (j = y - 2; j <= y + 2; j += 1) {
+// heatVal = heat[i + "," + j] || 0;
+// result += heatVal * gaussian[i - (x - 2)][j - (y - 2)];
+// }
+// }
+//
+// // multiply by reciprocal of sum of the gaussian kernel
+// // or divide by sum, as we do here.
+// result /= 159;
+// smoothedHeat[key] = result;
+// });
+
+ return smoothedHeat;
+ };
+ }());
+
+
+ /*
+ * normalize to a 0-255 range
+ */
+ normalizeHeat = function (heat) {
+ var minHeat, maxHeat, heatValues = [], normalizedHeat = {},
+ denominator, key;
+
+ for (key in heat) {
+ heatValues.push(heat[key]);
+ }
+
+ minHeat = Math.min.apply(this, heatValues);
+ maxHeat = Math.max.apply(this, heatValues);
+
+ denominator = maxHeat - minHeat;
+
+ if (denominator === 0 || denominator === Number.NEGATIVE_INFINITY) {
+ denominator = 1;
+ }
+
+ for (key in heat) {
+ normalizedHeat[key] = Math.floor(255 * ((heat[key] - minHeat) / denominator));
+
+ }
+
+ return normalizedHeat;
+ };
+
+}());

0 comments on commit 648ca0d

Please sign in to comment.