D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
biovisualize
Full window
Github gist
Phosphenes visualization face
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v3.min.js"></script> <script src="hermite.js"></script> <style> .panel { fill: black; } canvas { display: none; } .slider { width: 400px; } #phosphene-image { width: 400px; } </style> </head> <body> <canvas id="phosphene-image"></canvas> <div class="container"></div> <div class="controls"> <input class="slider" type="range" min="8" max="32" value="8" step="1"><br> <div class="count"></div> </div> <script> var link = 'https://lh3.googleusercontent.com/-wsJQUCf8bBY/VqkpGaZG-qI/AAAAAAAAC7Y/BzdFJUXN1-w/s461-Ic42/MongolianSmileBW2.jpg'; var outputW = 400; var hermite = Hermite.init('hermite-worker.js'); var phospheneCanvas = document.getElementById('phosphene-image'); var phospheneCtx = phospheneCanvas.getContext('2d'); var root = d3.select('.container').append('svg'); var panel = root.append('rect').classed('panel', true); root.append('defs').append('filter') .attr({ id: 'f1', x: 0, y: 0 }) .append('feGaussianBlur') .attr({ in: 'SourceGraphic', stdDeviation: 2 }); var imgData, img; d3.select('.slider').on('input', function(d){ buildGrid(this.value); }); img = new Image; img.onload = function(){ buildGrid(8); }; img.crossOrigin = ''; img.src = link; function buildGrid(outputResolution){ d3.select('.count').text(outputResolution * outputResolution + ' phosphenes'); var imgW = outputResolution; var imgH = imgW * img.height / img.width; phospheneCanvas.width = img.width; phospheneCanvas.height = img.height ; phospheneCtx.drawImage(img, 0, 0, img.width, img.height); hermite.resize({ source: phospheneCanvas, width: imgW, height: imgH }, function(output) { imgData = phospheneCtx.getImageData(0, 0, imgW, imgH).data; var data = []; var dataIdx = -1; var r, g, b, gray; for(var i = 0; i < imgData.length / 4; i++){ if(i % imgW === 0){ dataIdx++; data.push([]); } r = imgData[i*4]; g = imgData[i*4+1]; b = imgData[i*4+2]; gray = r*0.2126 + g*0.7152 + b*0.0722; data[dataIdx].push(gray); } buildPhosphenes(data, imgH, imgW); }); } function buildPhosphenes(data, imgH, imgW){ var outputH = outputW * imgH / imgW; var cellSize = outputW / imgW; root.attr({width: outputW, height: outputH}); panel.attr({width: outputW, height: outputH}); var rowGroup = root.selectAll('g.row') .data(data); rowGroup.enter().append('g') .classed('row', true) .attr({ transform: function(d, i){ var y = cellSize * i; var x = 0; if(i % 2 === 0){ x += cellSize / 2; } return 'translate(' + [x, y] + ')'; } }); rowGroup .attr({ transform: function(d, i){ var y = cellSize * i; var x = 0; if(i % 2 === 0){ x += cellSize / 4; } else{ x -= cellSize / 4; } return 'translate(' + [x, y] + ')'; } }); rowGroup.exit().remove(); var cells = rowGroup.selectAll('circle.cell') .data(function(d, i){ return d; }); cells.enter().append('circle') .classed('cell', true); cells.attr({ r: (cellSize / 2) * 0.9, fill: function(d){ return d3.rgb(d, d, d).toString(); }, filter: 'url(#f1)', cy: cellSize / 2, cx: function(d, i){ return cellSize * i + cellSize / 2; } }); cells.exit().remove(); } </script> </body> </html>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js