From fcfd508f0c3d6ae60aa275cbf85f0258f8e9dedd Mon Sep 17 00:00:00 2001 From: Jake Read <jake.read@cba.mit.edu> Date: Mon, 11 Sep 2017 16:53:51 -0400 Subject: [PATCH] bounding box for KiCad svg imports --- modules/image/boundingbox | 203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 modules/image/boundingbox diff --git a/modules/image/boundingbox b/modules/image/boundingbox new file mode 100644 index 0000000..62199b3 --- /dev/null +++ b/modules/image/boundingbox @@ -0,0 +1,203 @@ +// +// image threshold +// +// Neil Gershenfeld +// (c) Massachusetts Institute of Technology 2015,6 +// +// This work may be reproduced, modified, distributed, performed, and +// displayed for any purpose, but must acknowledge the mods +// project. Copyright is retained and must be preserved. The work is +// provided as is; no warranty is provided, and users accept all +// liability. +// +// closure +// +(function(){ +// +// module globals +// +var mod = {} +// +// name +// +var name = 'bounding box' +// +// initialization +// +var init = function() { + } +// +// inputs +// +var inputs = { + image:{type:'RGBA', + event:function(evt){ + mod.input = evt.detail + var ctx = mod.img.getContext("2d") + ctx.canvas.width = mod.input.width + ctx.canvas.height = mod.input.height + ctx.putImageData(mod.input,0,0) + threshold_image()}}} +// +// outputs +// +var outputs = { + image:{type:'RGBA', + event:function(){ + var ctx = mod.img.getContext("2d") + var img = ctx.getImageData(0,0,mod.img.width,mod.img.height) + mods.output(mod,'image',img)}}} +// +// interface +// +var interface = function(div){ + mod.div = div + // + // on-screen drawing canvas + // + var canvas = document.createElement('canvas') + canvas.width = mods.ui.canvas + canvas.height = mods.ui.canvas + canvas.style.backgroundColor = 'rgb(255,255,255)' + div.appendChild(canvas) + mod.canvas = canvas + div.appendChild(document.createElement('br')) + // + // off-screen image canvas + // + var canvas = document.createElement('canvas') + mod.img = canvas + // + // view button + // + var btn = document.createElement('button') + btn.style.padding = mods.ui.padding + btn.style.margin = 1 + btn.appendChild(document.createTextNode('view')) + btn.addEventListener('click',function(){ + var win = window.open('') + var btn = document.createElement('button') + btn.appendChild(document.createTextNode('close')) + btn.style.padding = mods.ui.padding + btn.style.margin = 1 + btn.addEventListener('click',function(){ + win.close() + }) + win.document.body.appendChild(btn) + win.document.body.appendChild(document.createElement('br')) + var canvas = document.createElement('canvas') + canvas.width = mod.img.width + canvas.height = mod.img.height + win.document.body.appendChild(canvas) + var ctx = canvas.getContext("2d") + ctx.drawImage(mod.img,0,0) + }) + div.appendChild(btn) + + // TODO: adjust DPI here -> KiCad flow makes more sense to do it in 1st shot, know exactly size of 'page' plotted to + } +// +// local functions +// +// threshold image +// +function threshold_image() { + var blob = new Blob(['('+worker.toString()+'())']) + var url = window.URL.createObjectURL(blob) + var webworker = new Worker(url) + webworker.addEventListener('message',function(evt) { + window.URL.revokeObjectURL(url) + console.log("evt datas", evt.data.x, evt.data.y, evt.data.width, evt.data.height) + var ctx = mod.img.getContext("2d") + var imgData = ctx.getImageData(evt.data.x, evt.data.y, evt.data.width, evt.data.height) + mod.img.height = evt.data.height; + mod.img.width = evt.data.width; + ctx.putImageData(imgData, 0,0) + var h = mod.img.height + var w = mod.img.width + console.log("h/w", h, w) + if (w > h) { + var x0 = 0 + var y0 = mod.canvas.height*.5*(1-h/w) + var wd = mod.canvas.width + var hd = mod.canvas.width*h/w + } + else { + var x0 = mod.canvas.width*.5*(1-w/h) + var y0 = 0 + var wd = mod.canvas.height*w/h + var hd = mod.canvas.height + } + var ctx = mod.canvas.getContext("2d") + ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height) + ctx.drawImage(mod.img,x0,y0,wd,hd) + webworker.terminate() + outputs.image.event() + }) + var ctx = mod.canvas.getContext("2d") + ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height) + var ctx = mod.img.getContext("2d") + ctx.putImageData(mod.input,0,0) + var img = ctx.getImageData(0,0,mod.img.width,mod.img.height) + webworker.postMessage({ + height:mod.input.height,width:mod.input.width, + buffer:img.data.buffer}, + [img.data.buffer]) + } +function worker() { + self.addEventListener('message',function(evt) { + var h = evt.data.height + var w = evt.data.width + var t = 0.75 + var minx = w + var miny = h + var maxx = 0 + var maxy = 0 + var buf = new Uint8ClampedArray(evt.data.buffer) + var r,g,b,a,i + var rowflag; + + for (var row = 0; row < h; ++row) { + rowflag = false; + for (var col = 0; col < w; ++col) { + r = buf[(h-1-row)*w*4+col*4+0] // ** WARNING ** row / column / pixel / xy position + g = buf[(h-1-row)*w*4+col*4+1] // relationships are all ?!?! + b = buf[(h-1-row)*w*4+col*4+2] + a = buf[(h-1-row)*w*4+col*4+3] + i = (r+g+b)/(3*255) + if(a == 255 || i > t){ + rowflag = true + if(col > maxx){ + maxx = col + } + if(col < minx){ + minx = col + } + } + } + if(rowflag) { + if(row > maxy){ + maxy = row - h + } + if(row < miny){ + miny = row - h + } + } + } + maxy = Math.abs(maxy) + miny = Math.abs(miny) + console.log('minx, maxx, miny, maxy', minx, maxx, miny, maxy) // see above ** WARNING ** + self.postMessage({x: minx, y: maxy, width:maxx-minx, height:miny-maxy}) + }) + } +// +// return values +// +return ({ + name:name, + init:init, + inputs:inputs, + outputs:outputs, + interface:interface + }) +}()) -- GitLab