D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
biovisualize
Full window
Github gist
Phosphenes visualization with image loader and using hermite downsampling
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!--<script src="../lib/d3.js"></script>--> <script src="https://d3js.org/d3.v3.min.js"></script> <script src="hermite.js"></script> <style> .panel { fill: black; } .controls { position: absolute; } canvas { margin-top: 40px; float: left; } #imageLoader, .slider, .count { float: left; } .slider { width: 400px; } #base-image, #phosphene-image { width: 400px; } </style> </head> <body> <div class="controls"> <input type="file" id="imageLoader" name="imageLoader"></input> <input class="slider" type="range" min="8" max="32" value="8" step="1"> <div class="count"></div> </div> <canvas id="base-image"></canvas> <canvas id="phosphene-image"></canvas> <div class="container"></div> <script> var outputW = 400; var hermite = Hermite.init('hermite-worker.js'); var imgLoader = document.getElementById('imageLoader'); imgLoader.addEventListener('change', handleImage, false); var baseCanvas = document.getElementById('base-image'); var baseCtx = baseCanvas.getContext('2d'); 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); }); function handleImage(e){ var reader = new FileReader(); reader.onload = function(event){ img = new Image; img.onload = function(){ buildBaseImg(); buildGrid(8); }; img.src = event.target.result; }; reader.readAsDataURL(e.target.files[0]); } function buildBaseImg(){ var imgW = img.width; var imgH = img.height; baseCanvas.width = imgW; baseCanvas.height = imgH; baseCtx.clearRect(0, 0, imgW, imgH); baseCtx.drawImage(img, 0, 0, imgW, imgH); imgData = baseCtx.getImageData(0, 0, imgW, imgH).data; } 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 cellSize = outputW / imgW; 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); } var outputH = outputW * imgH / 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