added the scan&trace experiments

This commit is contained in:
Rick Companje 2014-04-27 20:12:44 +02:00
parent 0acf442a46
commit cd34ca9a03
8 changed files with 455 additions and 4 deletions

222
js/ContourFinder.js Normal file
View File

@ -0,0 +1,222 @@
function ContourFinder() {
this.pixelsWidth; // pixels width
this.pixelsHeight; // pixels height
this.pixels; // pixels (single array of r,g,b,a values of image)
this.fColor; // foreground color
this.bColor; // background color
this.threshold;
this.maxContourPoints = 500*10; //was 500*4
this.allpoints = [];
this.findContours = function(image,foregroundColor,backgroundColor,threshold) {
var w = this.pixelsWidth = image.width;
var h = this.pixelsHeight = image.height;
this.fColor = foregroundColor;
this.bColor = backgroundColor;
this.threshold = threshold;
// create a new pixel array
var imageCtx = image.getContext('2d');
alert(imageCtx);
var imageData = imageCtx.getImageData(0,0,w, h);
//console.log("imageData: ",imageData);
var pixels = this.pixels = imageData.data;
//console.log("pixels: ",pixels);
var prevValue = 0;
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var index = y*w*4+x*4; //(y*w + x)*4;
/*r = pixels[index+0];
g = pixels[index+1];
b = pixels[index+2];
a = pixels[index+3];*/
var factor = ((pixels[index] *.3 + pixels[index+1]*.59 + pixels[index+2]*.11) )
//console.log(index+": "+r+" "+" "+g+" "+b+" "+a);
//var value = g;
var value = (factor > threshold)? 255 : 0; // threshold
//console.log(" > "+value);
pixels[index+0] = value;
pixels[index+1] = value;
pixels[index+2] = value;
//pixels[index+3] = value;
}
}
//console.log("pixels: ",pixels);
// copy the image data back onto the canvas
//imageCtx.putImageData(imageData, 0, 0); // at coords 0,0
//return;
var counter = 0;
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var index = y*w*4+x*4;
r = pixels[index+0];
g = pixels[index+1];
b = pixels[index+2];
a = pixels[index+3];
var value = g;
value = (value > threshold)? 255 : 0;
// if we enter a foreGround color and red isn't 0 (already stored as contour)
if(prevValue == backgroundColor && value == foregroundColor && r != 0) {
var points = this.followContour([x,y]);
this.allpoints.push(points);
counter++;
}
//r = 255;
pixels[index+0] = r;
pixels[index+1] = g;
pixels[index+2] = b;
pixels[index+3] = a;
prevValue = value;
}
}
// console.log("counter: " +counter);
// console.log(this.getPoints(points));
// console.log("======================================");
/*for (var i = 0, n = pixels.length; i < n; i += 4) {
var grayscale = pixels[i ] * .3 + pixels[i+1] * .59 + pixels[i+2] * .11;
alpha = pixels[i+3];
//console.log("alpha: ",alpha);
var value = (alpha > threshold)? 255 : 0;
//console.log("value: ",value);
/*pixels[i ] = value; // red
pixels[i+1] = value; // green
pixels[i+2] = value; // blue
pixels[i+3] = value; // alpha*/
/*
if(alpha > threshold) {
pixels[i ] = 255; // red
}
}*/
/*for (var y = 0; y < height; y++) {
inpos = y * width * 4; // *4 for 4 ints per pixel
outpos = inpos + w2 * 4
for (var x = 0; x < w2; x++) {
r = imageData.data[inpos++] / 3; // less red
g = imageData.data[inpos++] / 3; // less green
b = imageData.data[inpos++] * 5; // MORE BLUE
a = imageData.data[inpos++]; // same alpha
b = Math.min(255, b); // clamp to [0..255]
imageData.data[outpos++] = r;
imageData.data[outpos++] = g;
imageData.data[outpos++] = b;
imageData.data[outpos++] = a;
}
}*/
// copy the image data back onto the canvas
imageCtx.putImageData(imageData, 0, 0); // at coords 0,0
}
this.followContour = function(startPoint) {
//console.log("followContour @",startPoint);
points = []; // start new contour
points.push(startPoint);
var w = this.pixelsWidth;
var h = this.pixelsHeight;
//console.log("w :",w," h: ",h);
var point = startPoint;
var numPoints = 0;
// define neighborhood (array of 4, with:
// x offset, y offset, index offset
var neighborhood = [
[1,0,1,3], // east
[0,1,w,0], // south
[-1,0,-1,1], // west
[0,-1,-w,2] // north
];
var prevIndex;
var nextNeighbor = 0; // starting point for neighborhood search (index for neighborhood array)
do {
//console.log(" point: ",point[0],point[1]);
var x = point[0];
var y = point[1];
// go clockwise trough neighbors (starting at east side)
var index = y*w*4+x*4;
this.pixels[index] = 0; // r
this.pixels[index+2] = 0; // b
var newPoint;
//console.log(" index: ",index);
var i = nextNeighbor;
//console.log(" nextNeighbor: ",nextNeighbor);
for(var j=0;j<neighborhood.length;j++) {
//console.log(" neighbor: ",i);
var nIndex = index+neighborhood[i][2]*4;
//console.log(" neighbor index: ",nIndex);
//console.log(" neighbor g index: ",nIndex+1);
//console.log(" value: ",this.pixels[nIndex+1]);
// todo: check if in range
if(this.pixels[nIndex+1] == this.fColor && nIndex != prevIndex) {
//console.log(" == fColor");
newPoint = [x+neighborhood[i][0],y+neighborhood[i][1]];
nextNeighbor = neighborhood[i][3];
break;
}
i++;
i = i%neighborhood.length;
}
if(newPoint == undefined) {
break;
} else {
//console.log(" new point: ",newPoint[0],newPoint[1]);
point = newPoint;
points.push(point);
//console.log(" points: ",this.getPoints(points));
}
prevIndex = index;
//var index = y*w*4+x*4;
numPoints++;
//console.log(point[0],startPoint[0]," ",point[1],startPoint[1]);
} while(!(point[0] == startPoint[0] && point[1] == startPoint[1]) && numPoints < this.maxContourPoints);
this.closeContour(points);
return points;
}
this.closeContour = function(points) {
//console.log("pixels: ",this.pixels);
}
this.getPoints = function(points) {
var log = "";
for(var i=0;i<points.length;i++) {
var point = points[i];
log += point[0]+","+point[1]+" > ";
}
return log;
}
}

192
js/Scan.js Normal file
View File

@ -0,0 +1,192 @@
var scanPopup;
var canvasScan,canvasScanCtx;
var contourFinder;
function initScan() {
// $("body").append('<div id="svgfont" style="display:none"></div>');
// $("#svgfont").load("img/font.svg?");
scanPopup = new Popup($("#popupScan"),$("#popupMask"));
$("#btnScanOk").on("onButtonClick",scanPopup.commit);
// $("#btnWordArtCancel").on("onButtonClick",wordArtPopup.cancel);
$("#scanPopup").bind("onPopupCancel", onScanCancel);
$("#scanPopup").bind("onPopupCommit", onScanOk);
contourFinder = new ContourFinder();
canvasScan = $("#canvasScan");
canvasScanCtx = canvasScan[0].getContext('2d');
}
function showScanDialog() {
buttonGroupAdd.hide();
scanPopup.open();
// console.log("canvas: ", canvasScanCtx);
// alert("hoi");
loadImage();
// $("#txtWordArt").focus();
// $("#txtWordArt").val(""); //clear textbox
}
function loadImage() {
var img = new Image();
img.src = "/doodle3d-contours/images/foto-(7).png";
img.onload = function() {
// alert("hoi");
canvasScanCtx.drawImage(img, 0, 0);
var foregroudColor = 255;
var backgroundColor = 0;
//var threshold = 160; //doodle3D logo
var threshold = 62; //arcade
contourFinder.findContours(canvasScan[0],foregroudColor,backgroundColor,threshold);
for (var i=0; i<contourFinder.allpoints.length; i++) {
canvasScanCtx.strokeStyle = '#'+Math.floor(Math.random()*16777215).toString(16);
drawContour(i);
}
}
//logo.src = "images/logo.png";
}
function drawContour(index) {
var points = contourFinder.allpoints[index];
if (points.length<=0) return;
beginShape();
for (var i=0; i<points.length; i++) {
// var p = points[i];
if (points[i][2]) shapeMoveTo(points[i][0],points[i][1]);
else shapeLineTo(points[i][0],points[i][1]);
}
endShape();
// canvasScanCtx.beginPath();
// canvasScanCtx.moveTo(points[0][0],points[0][1]);
// for (var i=0; i<points.length; i++) {
// canvasScanCtx.lineTo(points[i][0],points[i][1]);
// }
// canvasScanCtx.stroke();
}
function canvasDrawPoints(canvas,points) {
}
function onScanCancel() {
// $("#txtWordArt").blur();
}
function onScanOk() {
// $("#txtWordArt").blur();
// var s = $("#txtWordArt").val();
// drawTextOnCanvas(s);
}
// function drawTextOnCanvas(text) {
// if (typeof(text) == 'string') {
// var points = getStringAsPoints(text);
// var bounds = getBounds(points);
// var scaleX = (canvasWidth-50) / bounds.width;
// var scaleY = (canvasHeight-50) / bounds.height;
// var scale = Math.min(scaleX,scaleY);
// scalePoints(points,scale);
// var bounds = getBounds(points);
// translatePoints(points,-bounds.x,-bounds.y); //left top of text is (0,0)
// translatePoints(points,-bounds.width/2,-bounds.height/2); //anchor point center
// translatePoints(points,canvasWidth/2,canvasHeight/2); //center in canvas
// canvasDrawPoints(canvas,points);
// }
// }
// function getStringAsPoints(text) {
// var allPoints = [];
// var xPos = 0;
// for (var i=0; i<text.length; i++) {
// if (text[i]==" ") { //space
// xPos += 8;
// } else { //other characters
// var path = getPathFromChar(text[i]);
// var points = getPointsFromPath(path);
// if (points.length==0) continue;
// translatePoints(points,-points[0][0],0);
// var bounds = getBounds(points);
// translatePoints(points,-bounds.x,0);
// translatePoints(points,xPos,0);
// xPos+=bounds.width;
// xPos+=2;
// for (var j=0; j<points.length; j++) {
// allPoints.push(points[j]);
// }
// }
// }
// return allPoints;
// }
// function getPathFromChar(ch) {
// var index = ch.charCodeAt(0)-33;
// var element = $("#svgfont path")[index];
// if (element==undefined) return "";
// return $("#svgfont path")[index].attributes["d"].nodeValue;
// }
// function getPointsFromPath(path) {
// var points = [];
// var cmds = path.split(' ');
// var cursor = { x:0.0, y:0.0 };
// var move = false;
// var prevCmd = "";
// for (var i=0; i<cmds.length; i++) {
// var cmd = cmds[i];
// var xy = cmd.split(",");
// if (cmd=='m') move = true;
// if (xy.length==2) { // if there are two parts (a comma) we asume it's a l command. (So L is not supported)
// cursor.x += parseFloat(xy[0]);
// cursor.y += parseFloat(xy[1]);
// points.push([cursor.x,cursor.y,move]);
// move = false;
// } else if (prevCmd == "h"){
// cursor.x += parseFloat(cmd);
// points.push([cursor.x,cursor.y,move]);
// } else if (prevCmd == "v"){
// cursor.y += parseFloat(cmd);
// points.push([cursor.x,cursor.y,move]);
// } else if (prevCmd == "H"){
// cursor.x = parseFloat(cmd);
// points.push([cursor.x,cursor.y,move]);
// } else if (prevCmd == "V"){
// cursor.y = parseFloat(cmd);
// points.push([cursor.x,cursor.y,move]);
// }
// prevCmd = cmd;
// }
// return points;
// }
// function canvasDrawPoints(canvas,points) {
// beginShape();
// for (var i=0; i<points.length; i++) {
// var p = points[i];
// if (points[i][2]) shapeMoveTo(p[0],p[1]);
// else shapeLineTo(p[0],p[1]);
// }
// endShape();
// }

View File

@ -12,7 +12,7 @@ var btnNew, btnPrevious, btnNext, btnOops, btnStop, btnInfo;
var btnSettings, btnWordArt;
var btnToggleEdit, buttonGroupEdit, btnZoom, btnMove, btnRotate;
var btnToggleVerticalShapes, btnHeight, btnTwist, btnShape, btnConv, btnStraight, btnSine, btnDiv;
var buttonGroupAdd, popupWordArt;
var buttonGroupAdd, popupWordArt, btnScan;
var state;
var prevState;
@ -43,6 +43,7 @@ function initButtonBehavior() {
buttonGroupAdd = $("#buttonGroupAdd");
btnShape = new Button("#btnShape");
btnWordArt = new Button("#btnWordArt");
btnScan = new Button("#btnScan");
popupWordArt = $("#popupWordArt");
popupShape = $("#popupShape");
popupMask = $("#popupMask");
@ -68,6 +69,7 @@ function initButtonBehavior() {
btnNew.on("onButtonClick", onBtnNew);
btnAdd.on("onButtonClick", onBtnAdd);
btnWordArt.on("onButtonClick", onBtnWordArt);
btnScan.on("onButtonClick", onBtnScan);
btnShape.on("onButtonClick", onBtnShape);
btnPrint.on("onButtonClick", print);
btnStop.on("onButtonClick", stopPrint);
@ -186,6 +188,11 @@ function initButtonBehavior() {
showWordArtDialog();
}
function onBtnScan(e) {
// alert("onBtnScan");
showScanDialog();
}
function onBtnShape(e) {
showShapeDialog();
buttonGroupAdd.fadeOut();

View File

@ -73,6 +73,7 @@ $(function() {
initKeyboard();
// initVerticalShapes();
initWordArt();
initScan();
initShapeDialog();
disableDragging();
@ -84,8 +85,9 @@ $(function() {
message.init($("#message"));
printer.init();
$(document).on(Printer.UPDATE,update);
//Rick: tijdelijk uit om console schoon te houden
//printer.init();
//$(document).on(Printer.UPDATE,update);
settingsWindow.init(wifiboxURL,wifiboxCGIBinURL);
$(document).on(SettingsWindow.SETTINGS_LOADED, settingsLoaded);

View File

@ -165,7 +165,7 @@
width: 200%;
max-width: 140px; /*fixme: can this grow based on it's content?*/
padding: 5% 0 5% 5%;
#btnWordArt, #btnShape {
#btnWordArt, #btnShape, #btnScan {
width: 45%;
}
}

View File

@ -75,6 +75,25 @@
}
}
#popupScan {
width: 640px;
margin-left: -320px;
height: 480px;
margin-top: -240px;
top: 50%;
#btnScanOk {
position: absolute;
bottom: 5%;
right: 3%;
}
#canvasScan {
border: 2px solid black;
border-radius: 5px;
}
}
.columnRight {
float: right;
}

BIN
www/img/buttons/btnScan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -40,6 +40,7 @@
<div id="buttonGroupAdd" class="buttonGroup">
<img id="btnWordArt" class="btn" src="img/buttons/btnWordArt.png" />
<img id="btnShape" class="btn" src="img/buttons/btnShape.png" />
<img id="btnScan" class="btn" src="img/buttons/btnScan.png" />
</div>
</div>
@ -126,6 +127,14 @@
</div>
</div>
<div class="popup" id="popupScan">
<div class="content">
<h1>Doodle3D Scan &amp; Trace</h1>
<canvas id="canvasScan" width="600" height="300"></canvas>
<img id="btnScanOk" class="btn" src="img/buttons/btnOk.png">
</div>
</div>
<div class="popup" id="popupShape">
<div class="content">
<h1>Add a new shape</h1>