newUI, python3,...

This commit is contained in:
sam 2020-09-19 14:28:56 +02:00
parent 0bb0049f02
commit e9d3009ffb
551 changed files with 22992 additions and 787437 deletions

View file

@ -0,0 +1,72 @@
"use strict";
var emotionClassifier = function() {
var previousParameters = [];
var classifier = {};
var emotions = [];
var coefficient_length;
this.getEmotions = function() {
return emotions;
}
this.init = function(model) {
// load it
for (var m in model) {
emotions.push(m);
classifier[m] = {};
classifier[m]['bias'] = model[m]['bias'];
classifier[m]['coefficients'] = model[m]['coefficients'];
}
coefficient_length = classifier[emotions[0]]['coefficients'].length;
}
this.getBlank = function() {
var prediction = [];
for (var j = 0;j < emotions.length;j++) {
prediction[j] = {"emotion" : emotions[j], "value" : 0.0};
}
return prediction;
}
this.predict = function(parameters) {
var prediction = [];
for (var j = 0;j < emotions.length;j++) {
var e = emotions[j];
var score = classifier[e].bias;
for (var i = 0;i < coefficient_length;i++) {
score += classifier[e].coefficients[i]*parameters[i+6];
}
prediction[j] = {"emotion" : e, "value" : 0.0};
prediction[j]['value'] = 1.0/(1.0 + Math.exp(-score));
}
return prediction;
}
this.meanPredict = function (parameters) {
// store to array of 10 previous parameters
previousParameters.splice(0, previousParameters.length == 10 ? 1 : 0);
previousParameters.push(parameters.slice(0));
if (previousParameters.length > 9) {
// calculate mean of parameters?
var meanParameters = [];
for (var i = 0;i < parameters.length;i++) {
meanParameters[i] = 0;
}
for (var i = 0;i < previousParameters.length;i++) {
for (var j = 0;j < parameters.length;j++) {
meanParameters[j] += previousParameters[i][j];
}
}
for (var i = 0;i < parameters.length;i++) {
meanParameters[i] /= 10;
}
// calculate logistic regression
return this.predict(meanParameters);
} else {
return false;
}
}
}

View file

@ -0,0 +1,26 @@
var emotionModel = {
"angry" : {
"bias" : -2.3768163629,
"coefficients" : [-0.026270300474413848, 0.037963304603547195, 0.25318394482150264, -0.36801694354709802, -0.059638621925431838, 6.3145056900010567e-17, 0.094520059272651849, 0.21347244366388901, 0.42885313652690621, -1.5592214434343613e-14, 0.13850079872874066, -5.1485910666665307e-16, 0.33298910350203975, 8.0357363919330235e-16, 0.0025325096363696059, -0.44615090964065951, -1.5784656134660036e-15, 0.047596008125675944],
},
"disgusted" : {
"bias" : -2.27900176842,
"coefficients" : [0.042360511043701296, 0.1282033922181087, 0.12391812407152457, -0.27567823277270387, 0.1421150306247343, -3.1081856766624292e-16, 0.12612972927139088, 0.23426310789552218, 0.058894842405560956, -4.0618311657856847e-15, 0.22340906131116328, -5.81584759084207e-15, 0.25735218595500009, 1.3658078149815552e-15, -0.12506850140605949, -0.9463447584787309, -4.555025133881674e-15, 0.07141679477545719],
},
"fear" : {
"bias" : -3.40339917096,
"coefficients" : [-0.1484066846778026, -0.090079860583144475, -0.16138464891003612, 0.078750143250805593, 0.070521075864349317, 3.6426173865029096e-14, 0.54106033239630258, 0.049586639890528791, -0.10793093750863458, -5.1279691693889055e-15, -0.092243236155683667, -1.5165430767377168e-14, 0.19842076279793416, 3.8282960479670228e-15, -0.67367184030514637, -0.2166709100861198, 1.1995348541944584e-14, -0.20024153378658624],
},
"sad" : {
"bias" : -2.75274632938,
"coefficients" : [0.092611010001705449, -0.12883530427748521, -0.068975994604949298, -0.19623077060801897, 0.055312197843294802, -3.5874521027522394e-16, 0.46315306348086854, -0.32103622843654361, -0.46536626891885491, 1.725612051187888e-14, -0.40841535552399683, 2.1258665882389598e-14, 0.45405204011625938, 5.9194289392226669e-15, 0.094410500655151899, -0.4861387223131064, -3.030330454831321e-15, 0.73708254653765559],
},
"surprised" : {
"bias" : -2.86262062696,
"coefficients" : [-0.12854109490879712, -0.049194392540246726, -0.22856553950573175, 0.2992140056765602, -0.25975558754705375, 1.4688408313649554e-09, -0.13685597104348368, -0.23581884244542603, 0.026447180058097462, 1.6822695398601112e-10, 0.095712304864421921, -4.4670230074132591e-10, 0.40505706085269738, 2.7821987602166784e-11, -0.54367856543588833, -0.096320945782919151, 1.4239801195516449e-10, -0.7238167998685946],
},
"happy" : {
"bias" : -1.4786712822,
"coefficients" : [0.014837209675880276, 0.31092627456808286, -0.1214238695400552, 0.45265837869400843, 0.36700140259900887, 1.7113646510738279e-15, -0.4786251427206033, -0.15377369505521801, -0.16948121903942992, 6.0300272629176253e-15, -0.021184992727875669, -6.9318606881292957e-15, -0.81611603551588852, -3.7883560238442657e-15, 0.1486320646217055, 0.94973410351769527, 3.6260400713070416e-15, -0.31361179943007411],
},
};

View file

@ -0,0 +1,293 @@
"use strict";
var faceDeformer = function() {
var gl, verticeMap;
var numTriangles;
var maxx, minx, maxy, miny;
var width, height;
var first = true;
var texCoordBuffer, gridCoordbuffer;
var texCoordLocation;
var pdmModel;
var usegrid = false;
var drawProgram, gridProgram;
this.init = function(canvas) {
// ready a webgl element
gl = getWebGLContext(canvas);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
}
this.load = function(element, points, pModel, vertices) {
pdmModel = pModel;
if (vertices) {
verticeMap = vertices;
} else {
verticeMap = pdmModel.path.vertices;
}
numTriangles = verticeMap.length;
// get cropping
maxx = 0;
minx = element.width;
maxy = 0;
miny = element.height;
for (var i = 0;i < points.length;i++) {
if (points[i][0] > maxx) maxx = points[i][0];
if (points[i][0] < minx) minx = points[i][0];
if (points[i][1] > maxy) maxy = points[i][1];
if (points[i][1] < miny) miny = points[i][1];
}
minx = Math.floor(minx);
maxx = Math.ceil(maxx);
miny = Math.floor(miny);
maxy = Math.ceil(maxy);
width = maxx-minx;
height = maxy-miny;
if (element.tagName == 'VIDEO' || element.tagName == 'IMG') {
var ca = document.createElement('canvas');
ca.width = element.width;
ca.height = element.height;
var cc = ca.getContext('2d');
cc.drawImage(element, 0, 0, element.width, element.height);
} else if (element.tagName == 'CANVAS') {
var cc = element.getContext('2d');
}
var image = cc.getImageData(minx, miny, width, height);
// correct points
var nupoints = [];
for (var i = 0;i < points.length;i++) {
nupoints[i] = [];
nupoints[i][0] = points[i][0] - minx;
nupoints[i][1] = points[i][1] - miny;
}
// create vertices based on points
var textureVertices = [];
for (var i = 0;i < verticeMap.length;i++) {
textureVertices.push(nupoints[verticeMap[i][0]][0]/width);
textureVertices.push(nupoints[verticeMap[i][0]][1]/height);
textureVertices.push(nupoints[verticeMap[i][1]][0]/width);
textureVertices.push(nupoints[verticeMap[i][1]][1]/height);
textureVertices.push(nupoints[verticeMap[i][2]][0]/width);
textureVertices.push(nupoints[verticeMap[i][2]][1]/height);
}
if (first) {
// create program for drawing grid
var gridVertexShaderProg = [
"attribute vec2 a_position;",
"",
"uniform vec2 u_resolution;",
"",
"void main() {",
" vec2 zeroToOne = a_position / u_resolution;",
" vec2 zeroToTwo = zeroToOne * 2.0;",
" vec2 clipSpace = zeroToTwo - 1.0;",
" gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);",
"}"
].join('\n');
var gridFragmentShaderProg = [
"void main() {",
" gl_FragColor = vec4(0.2, 0.2, 0.2, 1.0);",
"}"
].join('\n');
var gridVertexShader = loadShader(gl, gridVertexShaderProg, gl.VERTEX_SHADER);
var gridFragmentShader = loadShader(gl, gridFragmentShaderProg, gl.FRAGMENT_SHADER);
try {
gridProgram = createProgram(gl, [gridVertexShader, gridFragmentShader]);
} catch(err) {
alert("There was a problem setting up the webGL programs. Maybe you should try it in another browser. :(");
}
gridCoordbuffer = gl.createBuffer();
// create program for drawing deformed face
var vertexShaderProg = [
"attribute vec2 a_texCoord;",
"attribute vec2 a_position;",
"",
"varying vec2 v_texCoord;",
"",
"uniform vec2 u_resolution;",
"",
"void main() {",
" vec2 zeroToOne = a_position / u_resolution;",
" vec2 zeroToTwo = zeroToOne * 2.0;",
" vec2 clipSpace = zeroToTwo - 1.0;",
" gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);",
" ",
" v_texCoord = a_texCoord;",
"}"
].join('\n');
var fragmentShaderProg = [
"precision mediump float;",
"",
"uniform sampler2D u_image;",
"",
"varying vec2 v_texCoord;",
"",
"void main() {",
" gl_FragColor = texture2D(u_image, v_texCoord);",
"}"
].join('\n');
var vertexShader = loadShader(gl, vertexShaderProg, gl.VERTEX_SHADER);
var fragmentShader = loadShader(gl, fragmentShaderProg, gl.FRAGMENT_SHADER);
drawProgram = createProgram(gl, [vertexShader, fragmentShader]);
texCoordBuffer = gl.createBuffer();
first = false;
}
// load program for drawing grid
gl.useProgram(gridProgram);
// set the resolution for grid program
var resolutionLocation = gl.getUniformLocation(gridProgram, "u_resolution");
gl.uniform2f(resolutionLocation, gl.drawingBufferWidth, gl.drawingBufferHeight);
// load program for drawing deformed face
gl.useProgram(drawProgram);
// look up where the vertex data needs to go.
texCoordLocation = gl.getAttribLocation(drawProgram, "a_texCoord");
// provide texture coordinates for face vertices (i.e. where we're going to copy face vertices from).
gl.enableVertexAttribArray(texCoordLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureVertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
// Create the texture.
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
// set the resolution for draw program
resolutionLocation = gl.getUniformLocation(drawProgram, "u_resolution");
gl.uniform2f(resolutionLocation, gl.drawingBufferWidth, gl.drawingBufferHeight);
}
this.draw = function(points) {
if (usegrid) {
// switch program if needed
gl.useProgram(drawProgram);
//texCoordLocation = gl.getAttribLocation(drawProgram, "a_texCoord");
gl.enableVertexAttribArray(texCoordLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
usegrid = false;
}
// create drawvertices based on points
var vertices = [];
for (var i = 0;i < verticeMap.length;i++) {
vertices.push(points[verticeMap[i][0]][0]);
vertices.push(points[verticeMap[i][0]][1]);
vertices.push(points[verticeMap[i][1]][0]);
vertices.push(points[verticeMap[i][1]][1]);
vertices.push(points[verticeMap[i][2]][0]);
vertices.push(points[verticeMap[i][2]][1]);
}
var positionLocation = gl.getAttribLocation(drawProgram, "a_position");
// Create a buffer for the position of the vertices.
var drawPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, drawPosBuffer);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Draw the face vertices
gl.drawArrays(gl.TRIANGLES, 0, numTriangles*3);
}
this.drawGrid = function(points) {
if (!usegrid) {
gl.useProgram(gridProgram);
usegrid = true;
}
// create drawvertices based on points
var vertices = [];
// create new texturegrid
for (var i = 0;i < verticeMap.length;i++) {
vertices.push(points[verticeMap[i][0]][0]);
vertices.push(points[verticeMap[i][0]][1]);
vertices.push(points[verticeMap[i][1]][0]);
vertices.push(points[verticeMap[i][1]][1]);
vertices.push(points[verticeMap[i][1]][0]);
vertices.push(points[verticeMap[i][1]][1]);
vertices.push(points[verticeMap[i][2]][0]);
vertices.push(points[verticeMap[i][2]][1]);
vertices.push(points[verticeMap[i][2]][0]);
vertices.push(points[verticeMap[i][2]][1]);
vertices.push(points[verticeMap[i][0]][0]);
vertices.push(points[verticeMap[i][0]][1]);
}
var positionLocation = gl.getAttribLocation(gridProgram, "a_position");
// Create a buffer for position of the vertices (lines)
gl.bindBuffer(gl.ARRAY_BUFFER, gridCoordbuffer);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Draw the lines
gl.drawArrays(gl.LINES, 0, numTriangles*6);
}
this.clear = function() {
gl.clear(gl.COLOR_BUFFER_BIT);
}
this.calculatePositions = function(parameters, useTransforms) {
var x, y, a, b;
var numParameters = parameters.length;
var positions = [];
for (var i = 0;i < pdmModel.patchModel.numPatches;i++) {
x = pdmModel.shapeModel.meanShape[i][0];
y = pdmModel.shapeModel.meanShape[i][1];
for (var j = 0;j < numParameters-4;j++) {
x += pdmModel.shapeModel.eigenVectors[(i*2)][j]*parameters[j+4];
y += pdmModel.shapeModel.eigenVectors[(i*2)+1][j]*parameters[j+4];
}
if (useTransforms) {
a = parameters[0]*x - parameters[1]*y + parameters[2];
b = parameters[0]*y + parameters[1]*x + parameters[3];
x += a;
y += b;
}
positions[i] = [x,y];
}
return positions;
}
}

View file

@ -0,0 +1,4 @@
var emotionModel = {
"female" : {"bias" : 0.2032715028,"coefficients" : [-0.012175107151058892, -0.02547077166891205, -0.2566348527573602, 0.11310242239983805, 0.047662190057044897, -2.8042459462986078e-16, 0.3195685402512452, 0.28237816481413897, 0.18543701164340573, -6.7673159194176704e-15, -0.19586878878113456, 4.2056286434386572e-15, -0.28249143405077398, -3.1307226033279127e-15, -0.20117514352322866, 0.078204621229952198, -2.9508044403457735e-16, 0.099928680431662836],},
"male" : {"bias" : -0.2032715028,"coefficients" : [0.012175107151058849, 0.02547077166891203, 0.25663485275736025, -0.11310242239983825, -0.047662190057045001, 2.9467555630692706e-16, -0.31956854025124526, -0.28237816481413891, -0.18543701164340579, 6.7687148929820262e-15, 0.19586878878113456, -4.1758151261263302e-15, 0.28249143405077398, 3.122371549856354e-15, 0.20117514352322877, -0.078204621229952295, 2.161563179053083e-16, -0.099928680431662809],},
};

View file

@ -0,0 +1,7 @@
// stats.js r8 - http://github.com/mrdoob/stats.js
var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign=
"left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height=
"30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding=
"0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"),
a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/
100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}};

5
www/trckr/js/libs/d3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

94
www/trckr/js/libs/dat.gui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
www/trckr/js/libs/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,185 @@
/**
* Poisson Image Editing module
* http://rest-term.com
*/
(function() {
var Poisson; // top-level namaspace
var _root = this; // reference to 'window' or 'global'
if(typeof exports !== 'undefined') {
Poisson = exports; // for CommonJS
} else {
Poisson = _root.Poisson = {};
}
// core operations
var EPS = 1.0E-08;
var ctx = null,
images = [new Image(), new Image(), new Image()],
files = [],
data = [],
loadedCount = 0;
var sumf = new Float64Array(3),
sumfstar = new Float64Array(3),
sumvq = new Float64Array(3),
fp = new Float64Array(3),
fq = new Float64Array(3),
gp = new Float64Array(3),
gq = new Float64Array(3),
subf = new Float64Array(3),
naddr = new Int32Array(4),
subg = new Float64Array(3);
function pt1(y, offsetY, x, offsetX, w, h, sumf, blendData, m, sumvq, srcData, l, naddr) {
if(y + offsetY >= 0 && x + offsetX >= 0 &&
y + offsetY < h && x + offsetX < w) {
for(n=0; n<4; n++) {
for(var c=0; c<3; c++) {
sumf[c] += blendData[naddr[n] + m + c];
sumvq[c] += srcData[l + c] - srcData[naddr[n] + c];
}
}
}
}
function pt2(y, offsetY, x, offsetX, w, h, fp, gp, dstData, fq, gq, sumfstar, subf, subg, sumf, blendData, m, sumvq, srcData, l, naddr) {
if(y + offsetY >= 0 && x + offsetX >= 0 &&
y + offsetY < h && x + offsetX < w) {
fp[0] = dstData[l + m];
fp[1] = dstData[l + m + 1];
fp[2] = dstData[l + m + 2];
gp[0] = srcData[l];
gp[1] = srcData[l + 1];
gp[2] = srcData[l + 2];
for(n=0; n<4; n++) {
for(c=0; c<3; c++) {
fq[c] = dstData[naddr[n] + m + c];
// modification : we ignore pixels outside face mask, since these cause artifacts
//gq[c] = srcData[naddr[n] + c];
gq[c] = srcData[l+c];
sumfstar[c] += fq[c];
subf[c] = fp[c] - fq[c];
subf[c] = subf[c] > 0 ? subf[c] : -subf[c];
subg[c] = gp[c] - gq[c];
subg[c] = subg[c] > 0 ? subg[c] : -subg[c];
if(subf[c] > subg[c]) {
sumvq[c] += subf[c];
} else {
sumvq[c] += subg[c];
}
}
}
}
}
function pt3(fp, c, sumf, sumfstar, sumvq, terminate, EPS, blendData, l, m, srcData, paste) {
fp[c] = (sumf[c] + sumfstar[c] + sumvq[c])*0.25; // division 4
error = Math.floor(fp[c] - blendData[l + m + c]);
error = error > 0 ? error : -error;
if(terminate[c] && error >
EPS*(1 + (fp[c] > 0 ? fp[c] : -fp[c]))) {
terminate[c] = false;
//log[l+m+c] = {x:x,y:y,c:c,error:error};
}
blendData[l + m + c] = fp[c];
if(paste) blendData[l + m + c] = srcData[l + c];
}
var core = {
// loads images
load: function(srcCanvas, dstCanvas, maskCanvas, onComplete, onError) {
ctx = document.createElement('canvas').getContext('2d');
// load complete handler
var imgData = srcCanvas.getContext('2d').getImageData(0, 0, srcCanvas.width, srcCanvas.height);
data[0] = imgData;
imgData = dstCanvas.getContext('2d').getImageData(0, 0, dstCanvas.width, dstCanvas.height);
data[1] = imgData;
imgData = maskCanvas.getContext('2d').getImageData(0, 0, maskCanvas.width, maskCanvas.height);
data[2] = imgData;
ctx.drawImage(dstCanvas, 0, 0);
data[3] = dstCanvas.getContext('2d').getImageData(0, 0, dstCanvas.width, dstCanvas.height);
if(typeof onComplete === 'function') {
onComplete(data);
}
},
reset: function() {
ctx.drawImage(dstCanvas, 0, 0);
data[3] = ctx.getImageData(0, 0, dstCanvas.width, dstCanvas.height);
return data[3];
},
// applies poisson image editing
blend: function(iteration, offsetX, offsetY, paste) {
var w = data[0].width,
h = data[0].height,
len = w*h*4,
srcData = data[0].data,
dstData = data[1].data,
maskData = data[2].data,
blendData = data[3].data,
edge = false,
error = 0.0,
threashold = 128,
terminate = [],
step, l, m;
var log = {};
// validation
if(!(parseInt(iteration) && typeof(offsetX) == "number" && typeof(offsetY) == "number")) {
throw TypeError('invalid parameter type');
}
// core operation
for(var i=0; i<iteration; i++) {
terminate = [true, true, true];
for(var y=1; y<h-1; y++) {
step = y*w << 2;
for(var x=1; x<w-1; x++) {
l = step + (x << 2);
m = offsetY*w + offsetX << 2;
naddr[0] = l - (w << 2);
naddr[1] = l - 4;
naddr[2] = l + 4;
naddr[3] = l + (w << 2);
if(maskData[l] > threashold) { // on the mask
sumf[0] = 0;
sumf[1] = 0;
sumf[2] = 0;
sumfstar[0] = 0;
sumfstar[1] = 0;
sumfstar[2] = 0;
sumvq[0] = 0;
sumvq[1] = 0;
sumvq[2] = 0;
edge = false;
for(var n=0; n<4; n++) {
if(maskData[naddr[n]] <= threashold) {
edge = true;
break;
}
}
if(!edge) {
pt1(y, offsetY, x, offsetX, w, h, sumf, blendData, m, sumvq, srcData, l, naddr);
} else {
pt2(y, offsetY, x, offsetX, w, h, fp, gp, dstData, fq, gq, sumfstar, subf, subg, sumf, blendData, m, sumvq, srcData, l, naddr);
}
for(c=0; c<3; c++) {
pt3(fp, c, sumf, sumfstar, sumvq, terminate, EPS, blendData, l, m, srcData, paste)
}
} // end mask
} // end x loop
} // end y loop
if(terminate[0] && terminate[1] && terminate[2]) break;
} // end iteration
//core.debugPlot(blendData, log);
return data[3];
},
debugPlot: function(img, data) {
for(var i in data) {
console.log(data[i]);
img[i] = 255;
}
}
};
// aliases (public APIs)
Poisson.load = core.load;
Poisson.reset = core.reset;
Poisson.blend = core.blend;
}).call(this);

View file

@ -0,0 +1,44 @@
// helper functions
/**
* Provides requestAnimationFrame in a cross browser way.
*/
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
return window.setTimeout(callback, 1000/60);
};
})();
/**
* Provides cancelRequestAnimationFrame in a cross browser way.
*/
window.cancelRequestAnimFrame = (function() {
return window.cancelAnimationFrame ||
window.webkitCancelRequestAnimationFrame ||
window.mozCancelRequestAnimationFrame ||
window.oCancelRequestAnimationFrame ||
window.msCancelRequestAnimationFrame ||
window.clearTimeout;
})();
// video support utility functions
function supports_video() {
return !!document.createElement('video').canPlayType;
}
function supports_h264_baseline_video() {
if (!supports_video()) { return false; }
var v = document.createElement("video");
return v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
}
function supports_webm_video() {
if (!supports_video()) { return false; }
var v = document.createElement("video");
return v.canPlayType('video/webm; codecs="vp8"');
}

View file

@ -0,0 +1,333 @@
// This code is based on webgl-utils.js authored by Gregg Tavares, license below:
/*
* Copyright (c) 2011, Gregg Tavares
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of greggman.com nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function(){
var LOGGING_ENABLED = true;
/**
* Wrapped logging function.
* @param {string} msg The message to log.
*/
const log = function (msg) {
if (!LOGGING_ENABLED) { return; }
if (window.console && window.console.log) {
window.console.log(msg);
}
};
/**
* Wrapped logging function.
* @param {string} msg The message to log.
*/
const error = function (msg) {
if (!LOGGING_ENABLED) { return; }
if (window.console) {
if (window.console.error) {
window.console.error(msg);
} else if (window.console.log) {
window.console.log(msg);
}
}
throw msg;
};
/**
* Turn off all logging.
*/
const loggingOff = function () {
LOGGING_ENABLED = false;
};
/**
* Check if the page is embedded.
* @return {boolean} True of we are in an iframe
*/
const isInIFrame = function () {
return window !== window.top;
};
/**
* Converts a WebGL enum to a string
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {number} value The enum value.
* @return {string} The enum as a string.
*/
const glEnumToString = function (gl, value) {
for (var p in gl) {
if (gl[p] === value) {
return p;
}
}
return '0x' + value.toString(16);
};
/**
* Creates the HTLM for a failure message
* @param {string} canvasContainerId id of container of th
* canvas.
* @return {string} The html.
*/
const makeFailHTML = function (msg) {
return '' +
'<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' +
'<td align="center">' +
'<div style="display: table-cell; vertical-align: middle;">' +
'<div style="">' + msg + '</div>' +
'</div>' +
'</td></tr></table>';
};
/**
* Mesasge for getting a webgl browser
* @type {string}
*/
// const GET_A_WEBGL_BROWSER = '' +
// 'This page requires a browser that supports WebGL.<br/>' +
// '<a href="http://get.webgl.org">Click here to upgrade your browser.</a>';
/**
* Mesasge for need better hardware
* @type {string}
*/
// const OTHER_PROBLEM = '' +
// "It doesn't appear your computer can support WebGL.<br/>" +
// '<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>';
/**
* Creates a webgl context. If creation fails it will
* change the contents of the container of the <canvas>
* tag to an error message with the correct links for WebGL.
* @param {Element} canvas. The canvas element to create a
* context from.
* @param {WebGLContextCreationAttirbutes} optAttribs Any
* creation attributes you want to pass in.
* @return {WebGLRenderingContext} The created context.
*/
const setupWebGL = function (canvas, optAttribs) {
// const showLink = function (str) {
// var container = canvas.parentNode;
// if (container) {
// container.innerHTML = makeFailHTML(str);
// }
// };
if (!window.WebGLRenderingContext) {
// showLink(GET_A_WEBGL_BROWSER);
return null;
}
var context = create3DContext(canvas, optAttribs);
if (!context) {
// showLink(OTHER_PROBLEM);
return null;
}
return context;
};
/**
* Creates a webgl context.
* @param {!Canvas} canvas The canvas tag to get context
* from. If one is not passed in one will be created.
* @return {!WebGLContext} The created context.
*/
const create3DContext = function (canvas, optAttribs) {
var names = ['webgl', 'experimental-webgl'];
var context = null;
for (var ii = 0; ii < names.length; ++ii) {
try {
context = canvas.getContext(names[ii], optAttribs);
} catch (e) {}
if (context) {
break;
}
}
return context;
};
const updateCSSIfInIFrame = function () {
if (isInIFrame()) {
document.body.className = 'iframe';
}
};
/**
* Gets a WebGL context.
* makes its backing store the size it is displayed.
*/
const getWebGLContext = function (canvas) {
if (isInIFrame()) {
updateCSSIfInIFrame();
// make the canvas backing store the size it's displayed.
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
var gl = setupWebGL(canvas);
return gl;
};
/**
* Loads a shader.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {string} shaderSource The shader source.
* @param {number} shaderType The type of shader.
* @param {function(string): void) optErrorCallback callback for errors.
* @return {!WebGLShader} The created shader.
*/
const loadShader = function (gl, shaderSource, shaderType, optErrorCallback) {
var errFn = optErrorCallback || error;
// Create the shader object
var shader = gl.createShader(shaderType);
// Load the shader source
gl.shaderSource(shader, shaderSource);
// Compile the shader
gl.compileShader(shader);
// Check the compile status
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
// Something went wrong during compilation; get the error
var lastError = gl.getShaderInfoLog(shader);
errFn("*** Error compiling shader '" + shader + "':" + lastError);
gl.deleteShader(shader);
return null;
}
return shader;
};
/**
* Creates a program, attaches shaders, binds attrib locations, links the
* program and calls useProgram.
* @param {!Array.<!WebGLShader>} shaders The shaders to attach
* @param {!Array.<string>} optAttribs The attribs names.
* @param {!Array.<number>} optLocations The locations for the attribs.
*/
const loadProgram = function (gl, shaders, optAttribs, optLocations) {
var program = gl.createProgram();
for (var i = 0; i < shaders.length; ++i) {
gl.attachShader(program, shaders[i]);
}
if (optAttribs) {
for (var i = 0; i < optAttribs.length; ++i) {
gl.bindAttribLocation(
program,
optLocations ? optLocations[i] : i,
optAttribs[i]);
}
}
gl.linkProgram(program);
// Check the link status
const linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
// something went wrong with the link
const lastError = gl.getProgramInfoLog(program);
error('Error in program linking:' + lastError);
gl.deleteProgram(program);
return null;
}
return program;
};
/**
* Loads a shader from a script tag.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {string} scriptId The id of the script tag.
* @param {number} optShaderType The type of shader. If not passed in it will
* be derived from the type of the script tag.
* @param {function(string): void) optErrorCallback callback for errors.
* @return {!WebGLShader} The created shader.
*/
const createShaderFromScript = function (
gl, scriptId, optShaderType, optErrorCallback
) {
var shaderSource = '';
var shaderType;
var shaderScript = document.getElementById(scriptId);
if (!shaderScript) {
throw new Error('*** Error: unknown script element' + scriptId);
}
shaderSource = shaderScript.text;
if (!optShaderType) {
if (shaderScript.type === 'x-shader/x-vertex') {
shaderType = gl.VERTEX_SHADER;
} else if (shaderScript.type === 'x-shader/x-fragment') {
shaderType = gl.FRAGMENT_SHADER;
} else if (
shaderType !== gl.VERTEX_SHADER &&
shaderType !== gl.FRAGMENT_SHADER
) {
throw new Error('*** Error: unknown shader type');
}
}
return loadShader(
gl,
shaderSource,
optShaderType || shaderType,
optErrorCallback
);
};
if (typeof exports === 'object' && typeof module !== 'undefined') {
module.exports = {
setupWebGL : setupWebGL,
createProgram : loadProgram,
createShaderFromScript : createShaderFromScript,
getWebGLContext : getWebGLContext,
loadShader : loadShader
}
} else {
// export to global
window.setupWebGL = setupWebGL;
window.createProgram = loadProgram;
window.createShaderFromScriptElement = createShaderFromScript;
window.getWebGLContext = getWebGLContext;
window.loadShader = loadShader;
}
}());