mirror of
https://github.com/viliusle/miniPaint.git
synced 2026-02-06 13:51:51 +00:00
Merge origin/master into gh-pages
Conflicts: index.html js/settings.js libs/kdtree.js
This commit is contained in:
commit
8996137c01
@ -225,12 +225,11 @@
|
||||
<div style="display:none;" id="tmp"></div>
|
||||
<div id="popup"></div>
|
||||
|
||||
<script src="libs/jquery-1.8.3.js"></script>
|
||||
<script src="libs/jquery.js"></script>
|
||||
<script src="libs/menu.js"></script>
|
||||
<script src="libs/imagefilters.js"></script>
|
||||
<script src="libs/imagefilters.min.js"></script>
|
||||
<script src="libs/glfx.js"></script>
|
||||
<script src="libs/exif.js"></script>
|
||||
<script src="libs/exif-binaryajax.js"></script>
|
||||
<script src="libs/exif.min.js"></script>
|
||||
<script src="libs/harmony.js"></script>
|
||||
<script src="libs/vintage.js"></script>
|
||||
<script src="libs/kdtree.js"></script>
|
||||
|
||||
@ -9,7 +9,7 @@ var canvas_preview = document.getElementById("canvas_preview").getContext("2d");
|
||||
//settings
|
||||
var AUTHOR = 'ViliusL';
|
||||
var EMAIL = 'www.viliusl@gmail.com';
|
||||
var VERSION = '2.2.1';
|
||||
var VERSION = '2.2.2';
|
||||
var WIDTH = 800; //canvas midth
|
||||
var HEIGHT = 600; //canvas height
|
||||
var RATIO = WIDTH/HEIGHT; //width & height ratio
|
||||
|
||||
@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Binary Ajax 0.1.10
|
||||
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
|
||||
* Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt]
|
||||
*/
|
||||
var BinaryFile = function(strData, iDataOffset, iDataLength) {
|
||||
var data = strData;
|
||||
var dataOffset = iDataOffset || 0;
|
||||
var dataLength = 0;
|
||||
|
||||
this.getRawData = function() {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (typeof strData == "string") {
|
||||
dataLength = iDataLength || data.length;
|
||||
|
||||
this.getByteAt = function(iOffset) {
|
||||
return data.charCodeAt(iOffset + dataOffset) & 0xFF;
|
||||
}
|
||||
|
||||
this.getBytesAt = function(iOffset, iLength) {
|
||||
var aBytes = [];
|
||||
|
||||
for (var i = 0; i < iLength; i++) {
|
||||
aBytes[i] = data.charCodeAt((iOffset + i) + dataOffset) & 0xFF
|
||||
};
|
||||
|
||||
return aBytes;
|
||||
}
|
||||
} else if (typeof strData == "unknown") {
|
||||
dataLength = iDataLength || IEBinary_getLength(data);
|
||||
|
||||
this.getByteAt = function(iOffset) {
|
||||
return IEBinary_getByteAt(data, iOffset + dataOffset);
|
||||
}
|
||||
|
||||
this.getBytesAt = function(iOffset, iLength) {
|
||||
return new VBArray(IEBinary_getBytesAt(data, iOffset + dataOffset, iLength)).toArray();
|
||||
}
|
||||
}
|
||||
|
||||
this.getLength = function() {
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
this.getSByteAt = function(iOffset) {
|
||||
var iByte = this.getByteAt(iOffset);
|
||||
if (iByte > 127)
|
||||
return iByte - 256;
|
||||
else
|
||||
return iByte;
|
||||
}
|
||||
|
||||
this.getShortAt = function(iOffset, bBigEndian) {
|
||||
var iShort = bBigEndian ?
|
||||
(this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1)
|
||||
: (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset)
|
||||
if (iShort < 0) iShort += 65536;
|
||||
return iShort;
|
||||
}
|
||||
this.getSShortAt = function(iOffset, bBigEndian) {
|
||||
var iUShort = this.getShortAt(iOffset, bBigEndian);
|
||||
if (iUShort > 32767)
|
||||
return iUShort - 65536;
|
||||
else
|
||||
return iUShort;
|
||||
}
|
||||
this.getLongAt = function(iOffset, bBigEndian) {
|
||||
var iByte1 = this.getByteAt(iOffset),
|
||||
iByte2 = this.getByteAt(iOffset + 1),
|
||||
iByte3 = this.getByteAt(iOffset + 2),
|
||||
iByte4 = this.getByteAt(iOffset + 3);
|
||||
|
||||
var iLong = bBigEndian ?
|
||||
(((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4
|
||||
: (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;
|
||||
if (iLong < 0) iLong += 4294967296;
|
||||
return iLong;
|
||||
}
|
||||
this.getSLongAt = function(iOffset, bBigEndian) {
|
||||
var iULong = this.getLongAt(iOffset, bBigEndian);
|
||||
if (iULong > 2147483647)
|
||||
return iULong - 4294967296;
|
||||
else
|
||||
return iULong;
|
||||
}
|
||||
|
||||
this.getStringAt = function(iOffset, iLength) {
|
||||
var aStr = [];
|
||||
|
||||
var aBytes = this.getBytesAt(iOffset, iLength);
|
||||
for (var j=0; j < iLength; j++) {
|
||||
aStr[j] = String.fromCharCode(aBytes[j]);
|
||||
}
|
||||
return aStr.join("");
|
||||
}
|
||||
|
||||
this.getCharAt = function(iOffset) {
|
||||
return String.fromCharCode(this.getByteAt(iOffset));
|
||||
}
|
||||
this.toBase64 = function() {
|
||||
return window.btoa(data);
|
||||
}
|
||||
this.fromBase64 = function(strBase64) {
|
||||
data = window.atob(strBase64);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var BinaryAjax = (function() {
|
||||
|
||||
function createRequest() {
|
||||
var oHTTP = null;
|
||||
if (window.ActiveXObject) {
|
||||
oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
} else if (window.XMLHttpRequest) {
|
||||
oHTTP = new XMLHttpRequest();
|
||||
}
|
||||
return oHTTP;
|
||||
}
|
||||
|
||||
function getHead(strURL, fncCallback, fncError) {
|
||||
var oHTTP = createRequest();
|
||||
if (oHTTP) {
|
||||
if (fncCallback) {
|
||||
if (typeof(oHTTP.onload) != "undefined") {
|
||||
oHTTP.onload = function() {
|
||||
if (oHTTP.status == "200") {
|
||||
fncCallback(this);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
oHTTP = null;
|
||||
};
|
||||
} else {
|
||||
oHTTP.onreadystatechange = function() {
|
||||
if (oHTTP.readyState == 4) {
|
||||
if (oHTTP.status == "200") {
|
||||
fncCallback(this);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
oHTTP = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
oHTTP.open("HEAD", strURL, true);
|
||||
oHTTP.send(null);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
}
|
||||
|
||||
function sendRequest(strURL, fncCallback, fncError, aRange, bAcceptRanges, iFileSize) {
|
||||
var oHTTP = createRequest();
|
||||
if (oHTTP) {
|
||||
|
||||
var iDataOffset = 0;
|
||||
if (aRange && !bAcceptRanges) {
|
||||
iDataOffset = aRange[0];
|
||||
}
|
||||
var iDataLen = 0;
|
||||
if (aRange) {
|
||||
iDataLen = aRange[1]-aRange[0]+1;
|
||||
}
|
||||
|
||||
if (fncCallback) {
|
||||
if (typeof(oHTTP.onload) != "undefined") {
|
||||
oHTTP.onload = function() {
|
||||
if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
|
||||
oHTTP.binaryResponse = new BinaryFile(oHTTP.responseText, iDataOffset, iDataLen);
|
||||
oHTTP.fileSize = iFileSize || oHTTP.getResponseHeader("Content-Length");
|
||||
fncCallback(oHTTP);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
oHTTP = null;
|
||||
};
|
||||
} else {
|
||||
oHTTP.onreadystatechange = function() {
|
||||
if (oHTTP.readyState == 4) {
|
||||
if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
|
||||
// IE6 craps if we try to extend the XHR object
|
||||
var oRes = {
|
||||
status : oHTTP.status,
|
||||
// IE needs responseBody, Chrome/Safari needs responseText
|
||||
binaryResponse : new BinaryFile(
|
||||
typeof oHTTP.responseBody == "unknown" ? oHTTP.responseBody : oHTTP.responseText, iDataOffset, iDataLen
|
||||
),
|
||||
fileSize : iFileSize || oHTTP.getResponseHeader("Content-Length")
|
||||
};
|
||||
fncCallback(oRes);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
oHTTP = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
oHTTP.open("GET", strURL, true);
|
||||
|
||||
if (oHTTP.overrideMimeType) oHTTP.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
|
||||
if (aRange && bAcceptRanges) {
|
||||
oHTTP.setRequestHeader("Range", "bytes=" + aRange[0] + "-" + aRange[1]);
|
||||
}
|
||||
|
||||
oHTTP.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 1970 00:00:00 GMT");
|
||||
|
||||
oHTTP.send(null);
|
||||
} else {
|
||||
if (fncError) fncError();
|
||||
}
|
||||
}
|
||||
|
||||
return function(strURL, fncCallback, fncError, aRange) {
|
||||
|
||||
if (aRange) {
|
||||
getHead(
|
||||
strURL,
|
||||
function(oHTTP) {
|
||||
var iLength = parseInt(oHTTP.getResponseHeader("Content-Length"),10);
|
||||
var strAcceptRanges = oHTTP.getResponseHeader("Accept-Ranges");
|
||||
|
||||
var iStart, iEnd;
|
||||
iStart = aRange[0];
|
||||
if (aRange[0] < 0)
|
||||
iStart += iLength;
|
||||
iEnd = iStart + aRange[1] - 1;
|
||||
|
||||
sendRequest(strURL, fncCallback, fncError, [iStart, iEnd], (strAcceptRanges == "bytes"), iLength);
|
||||
}
|
||||
);
|
||||
|
||||
} else {
|
||||
sendRequest(strURL, fncCallback, fncError);
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*
|
||||
document.write(
|
||||
"<script type='text/vbscript'>\r\n"
|
||||
+ "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
|
||||
+ " IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n"
|
||||
+ "End Function\r\n"
|
||||
+ "Function IEBinary_getLength(strBinary)\r\n"
|
||||
+ " IEBinary_getLength = LenB(strBinary)\r\n"
|
||||
+ "End Function\r\n"
|
||||
+ "</script>\r\n"
|
||||
);
|
||||
*/
|
||||
|
||||
document.write(
|
||||
"<script type='text/vbscript'>\r\n"
|
||||
+ "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
|
||||
+ " IEBinary_getByteAt = AscB(MidB(strBinary, iOffset + 1, 1))\r\n"
|
||||
+ "End Function\r\n"
|
||||
+ "Function IEBinary_getBytesAt(strBinary, iOffset, iLength)\r\n"
|
||||
+ " Dim aBytes()\r\n"
|
||||
+ " ReDim aBytes(iLength - 1)\r\n"
|
||||
+ " For i = 0 To iLength - 1\r\n"
|
||||
+ " aBytes(i) = IEBinary_getByteAt(strBinary, iOffset + i)\r\n"
|
||||
+ " Next\r\n"
|
||||
+ " IEBinary_getBytesAt = aBytes\r\n"
|
||||
+ "End Function\r\n"
|
||||
+ "Function IEBinary_getLength(strBinary)\r\n"
|
||||
+ " IEBinary_getLength = LenB(strBinary)\r\n"
|
||||
+ "End Function\r\n"
|
||||
+ "</script>\r\n"
|
||||
);
|
||||
1389
libs/exif.js
1389
libs/exif.js
File diff suppressed because it is too large
Load Diff
3
libs/exif.min.js
vendored
Normal file
3
libs/exif.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -42,7 +42,7 @@ b.texImage2D(b.TEXTURE_2D,0,b.RGBA,1,1,0,b.RGBA,b.UNSIGNED_BYTE,null);b.bindFram
|
||||
0,b.RGBA,2,2,0,b.RGBA,b.FLOAT,new Float32Array([2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));var e=b.createProgram(),d=b.createShader(b.VERTEX_SHADER),g=b.createShader(b.FRAGMENT_SHADER);b.shaderSource(d,"attribute vec2 vertex;void main(){gl_Position=vec4(vertex,0.0,1.0);}");b.shaderSource(g,"uniform sampler2D texture;void main(){gl_FragColor=texture2D(texture,vec2(0.5));}");b.compileShader(d);b.compileShader(g);b.attachShader(e,d);b.attachShader(e,
|
||||
g);b.linkProgram(e);d=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,d);b.bufferData(b.ARRAY_BUFFER,new Float32Array([0,0]),b.STREAM_DRAW);b.enableVertexAttribArray(0);b.vertexAttribPointer(0,2,b.FLOAT,!1,0,0);d=new Uint8Array(4);b.useProgram(e);b.viewport(0,0,1,1);b.bindTexture(b.TEXTURE_2D,c);b.drawArrays(b.POINTS,0,1);b.readPixels(0,0,1,1,b.RGBA,b.UNSIGNED_BYTE,d);return 127===d[0]||128===d[0]}function d(){}function c(a){"OES_texture_float_linear"===a?(void 0===this.$OES_texture_float_linear$&&Object.defineProperty(this,
|
||||
"$OES_texture_float_linear$",{enumerable:!1,configurable:!1,writable:!1,value:new d}),a=this.$OES_texture_float_linear$):a=n.call(this,a);return a}function e(){var a=f.call(this);-1===a.indexOf("OES_texture_float_linear")&&a.push("OES_texture_float_linear");return a}try{var g=document.createElement("canvas").getContext("experimental-webgl")}catch(l){}if(g&&-1===g.getSupportedExtensions().indexOf("OES_texture_float_linear")&&a(g)){var n=WebGLRenderingContext.prototype.getExtension,f=WebGLRenderingContext.prototype.getSupportedExtensions;
|
||||
WebGLRenderingContext.prototype.getExtension=c;WebGLRenderingContext.prototype.getSupportedExtensions=e}})();var a;v.canvas=function(){var b=document.createElement("canvas");try{a=b.getContext("experimental-webgl",{premultipliedAlpha:!1})}catch(d){a=null}if(!a)console.log("This browser does not support WebGL");b._={gl:a,isInitialized:!1,texture:null,spareTexture:null,flippedShader:null};b.texture=k(A);b.draw=k(C);b.update=k(D);b.replace=k(E);b.contents=k(F);b.getPixelArray=k(G);b.brightnessContrast=k(H);
|
||||
WebGLRenderingContext.prototype.getExtension=c;WebGLRenderingContext.prototype.getSupportedExtensions=e}})();var a;v.canvas=function(){var b=document.createElement("canvas");try{a=b.getContext("experimental-webgl",{premultipliedAlpha:!1})}catch(d){a=null}if(!a)throw"This browser does not support WebGL";b._={gl:a,isInitialized:!1,texture:null,spareTexture:null,flippedShader:null};b.texture=k(A);b.draw=k(C);b.update=k(D);b.replace=k(E);b.contents=k(F);b.getPixelArray=k(G);b.brightnessContrast=k(H);
|
||||
b.hexagonalPixelate=k(X);b.hueSaturation=k(K);b.colorHalftone=k(U);b.triangleBlur=k(S);b.unsharpMask=k(N);b.perspective=k(aa);b.matrixWarp=k($);b.bulgePinch=k(Z);b.tiltShift=k(R);b.dotScreen=k(V);b.edgeWork=k(W);b.lensBlur=k(Q);b.zoomBlur=k(T);b.noise=k(L);b.denoise=k(J);b.curves=k(I);b.swirl=k(ba);b.ink=k(Y);b.vignette=k(P);b.vibrance=k(O);b.sepia=k(M);return b};v.splineInterpolate=t;var h=function(){function b(b,c){var e=a.createShader(b);a.shaderSource(e,c);a.compileShader(e);if(!a.getShaderParameter(e,
|
||||
a.COMPILE_STATUS))throw"compile error: "+a.getShaderInfoLog(e);return e}function d(d,l){this.texCoordAttribute=this.vertexAttribute=null;this.program=a.createProgram();d=d||c;l=l||e;l="precision highp float;"+l;a.attachShader(this.program,b(a.VERTEX_SHADER,d));a.attachShader(this.program,b(a.FRAGMENT_SHADER,l));a.linkProgram(this.program);if(!a.getProgramParameter(this.program,a.LINK_STATUS))throw"link error: "+a.getProgramInfoLog(this.program);}var c="attribute vec2 vertex;attribute vec2 _texCoord;varying vec2 texCoord;void main(){texCoord=_texCoord;gl_Position=vec4(vertex*2.0-1.0,0.0,1.0);}",
|
||||
e="uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,texCoord);}";d.prototype.destroy=function(){a.deleteProgram(this.program);this.program=null};d.prototype.uniforms=function(b){a.useProgram(this.program);for(var e in b)if(b.hasOwnProperty(e)){var c=a.getUniformLocation(this.program,e);if(null!==c){var d=b[e];if("[object Array]"==Object.prototype.toString.call(d))switch(d.length){case 1:a.uniform1fv(c,new Float32Array(d));break;
|
||||
|
||||
3237
libs/imagefilters.js
3237
libs/imagefilters.js
File diff suppressed because it is too large
Load Diff
4
libs/imagefilters.min.js
vendored
Normal file
4
libs/imagefilters.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
libs/jquery-1.8.3.js
vendored
2
libs/jquery-1.8.3.js
vendored
File diff suppressed because one or more lines are too long
5
libs/jquery.js
vendored
Normal file
5
libs/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
278
libs/kdtree.js
278
libs/kdtree.js
@ -1,139 +1,139 @@
|
||||
/*
|
||||
author: Vladimir Seregin (Peko)
|
||||
|
||||
usage: var KDTREE = new datastructure.KDTree([{x: 22, y:55},...]);
|
||||
var nearest = KDTREE.getNearestNeighbours({x: x, y: y}, NUM_NEAREST);
|
||||
*/
|
||||
|
||||
var datastructure = (function() {
|
||||
var AXIS_X = 0;
|
||||
var AXIS_Y = 1;
|
||||
var K = 2; // I only require a 2d k-d tree
|
||||
function KDTreeNode(point) {
|
||||
this.point = point;
|
||||
this.leftChild = null;
|
||||
this.rightChild = null;
|
||||
}
|
||||
function KDTree(points) {
|
||||
var boundingRect = {
|
||||
maxX: -Math.pow(2, 31),
|
||||
minX: Math.pow(2, 31) - 1,
|
||||
maxY: -Math.pow(2, 31),
|
||||
minY: Math.pow(2, 31) - 1
|
||||
};
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
boundingRect.minX = Math.min(boundingRect.minX, points[i].x);
|
||||
boundingRect.minY = Math.min(boundingRect.minY, points[i].y);
|
||||
boundingRect.maxX = Math.max(boundingRect.maxX, points[i].x);
|
||||
boundingRect.maxY = Math.max(boundingRect.maxY, points[i].y);
|
||||
}
|
||||
this.rootNode = createKDTree_(points, 0, boundingRect);
|
||||
};
|
||||
function createKDTree_(points, depth, boundingRect) {
|
||||
if (points.length == 0) {
|
||||
return null;
|
||||
}
|
||||
var axis = depth % K;
|
||||
points.sort(function (a, b) {
|
||||
if (axis == AXIS_X) {
|
||||
return a.x - b.x;
|
||||
} else {
|
||||
return a.y - b.y;
|
||||
}
|
||||
});
|
||||
var medianIndex = Math.floor(points.length / 2);
|
||||
var node = new KDTreeNode(points[medianIndex]);
|
||||
node.boundingRect = boundingRect;
|
||||
var leftChildBoundingRect = {
|
||||
minX: boundingRect.minX,
|
||||
maxX: axis == AXIS_X ? node.point.x : boundingRect.maxX,
|
||||
minY: boundingRect.minY,
|
||||
maxY: axis == AXIS_Y ? node.point.y : boundingRect.maxY
|
||||
};
|
||||
var rightChildBoundingRect = {
|
||||
minX: axis == AXIS_X ? node.point.x : boundingRect.minX,
|
||||
maxX: boundingRect.maxX,
|
||||
minY: axis == AXIS_Y ? node.point.y : boundingRect.minY,
|
||||
maxY: boundingRect.maxY
|
||||
};
|
||||
node.leftChild = createKDTree_(points.slice(0, medianIndex), depth + 1, leftChildBoundingRect);
|
||||
node.rightChild = createKDTree_(points.slice(medianIndex + 1), depth + 1, rightChildBoundingRect);
|
||||
return node;
|
||||
}
|
||||
KDTree.prototype.getNearestNeighbour = function(searchCoord, opt_consideredPoints) {
|
||||
var results = [];
|
||||
this.getNearestNeighbours_(this.rootNode, searchCoord, 0, results, 1, opt_consideredPoints);
|
||||
return results.length == 0 ? null : results[0].node.point;
|
||||
};
|
||||
KDTree.prototype.getNearestNeighbours = function(searchCoord, maxResults, opt_consideredPoints) {
|
||||
var results = [];
|
||||
this.getNearestNeighbours_(this.rootNode, searchCoord, 0, results, maxResults, opt_consideredPoints);
|
||||
var points = [];
|
||||
for (var i = 0; i < results.length; ++i) {
|
||||
points.push(results[i].node.point);
|
||||
}
|
||||
return points;
|
||||
};
|
||||
KDTree.prototype.getNearestNeighbours_ = function(currNode, searchCoord, depth, results, maxResults, opt_consideredPoints) {
|
||||
if (opt_consideredPoints) {
|
||||
opt_consideredPoints.push(currNode.point);
|
||||
}
|
||||
var axis = depth % K;
|
||||
var currNodeDistanceToDesiredCoord = getSquaredEuclidianDistance(searchCoord.x, searchCoord.y, currNode.point.x, currNode.point.y);
|
||||
var bestSeen = {node:currNode, distance: currNodeDistanceToDesiredCoord};
|
||||
insertResult_(results, bestSeen, maxResults);
|
||||
var searchNodeSplittingCoord = axis == AXIS_X ? searchCoord.x : searchCoord.y;
|
||||
var currNodeSplittingCoord = axis == AXIS_X ? currNode.point.x : currNode.point.y;
|
||||
var searchLeft = searchNodeSplittingCoord < currNodeSplittingCoord;
|
||||
var targetChild = searchLeft ? currNode.leftChild : currNode.rightChild;
|
||||
var oppositeChild = searchLeft ? currNode.rightChild : currNode.leftChild;
|
||||
if (targetChild) {
|
||||
this.getNearestNeighbours_(targetChild, searchCoord, depth + 1, results, maxResults, opt_consideredPoints);
|
||||
}
|
||||
if (oppositeChild) {
|
||||
var toX, toY;
|
||||
if (axis == AXIS_X) {
|
||||
toX = currNode.point.x;
|
||||
toY = searchCoord.y;
|
||||
if (searchCoord.y < oppositeChild.boundingRect.minY) {
|
||||
toY = oppositeChild.boundingRect.minY;
|
||||
} else if (searchCoord.y > oppositeChild.boundingRect.maxY) {
|
||||
toY = oppositeChild.boundingRect.maxY;
|
||||
}
|
||||
} else {
|
||||
toY = currNode.point.y;
|
||||
toX = searchCoord.x;
|
||||
if (searchCoord.x < oppositeChild.boundingRect.minX) {
|
||||
toX = oppositeChild.boundingRect.minX;
|
||||
} else if (searchCoord.x > oppositeChild.boundingRect.maxX) {
|
||||
toX = oppositeChild.boundingRect.maxX;
|
||||
}
|
||||
}
|
||||
var squaredDist = getSquaredEuclidianDistance(searchCoord.x, searchCoord.y, toX, toY);
|
||||
if (squaredDist <= results[results.length - 1].distance) {
|
||||
this.getNearestNeighbours_(oppositeChild, searchCoord, depth + 1, results, maxResults, opt_consideredPoints);
|
||||
}
|
||||
}
|
||||
};
|
||||
function insertResult_(results, insertNode, maxResults) {
|
||||
var insertIndex;
|
||||
for (insertIndex = results.length - 1; insertIndex >= 0; --insertIndex) {
|
||||
var nearestNeighbourNode = results[insertIndex];
|
||||
if (insertNode.distance > nearestNeighbourNode.distance) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
results.splice(insertIndex + 1, 0, insertNode);
|
||||
if (results.length > maxResults) {
|
||||
results.pop();
|
||||
}
|
||||
}
|
||||
function getSquaredEuclidianDistance(x1, y1, x2, y2) {
|
||||
var dx = x1 - x2;
|
||||
var dy = y1 - y2;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
var module = {};
|
||||
module.KDTree = KDTree; // KDTree constructor.
|
||||
return module;
|
||||
})();
|
||||
/*
|
||||
author: Vladimir Seregin (Peko), http://jsdo.it/peko/wKvk
|
||||
|
||||
usage: var KDTREE = new datastructure.KDTree([{x: 22, y:55},...]);
|
||||
var nearest = KDTREE.getNearestNeighbours({x: x, y: y}, NUM_NEAREST);
|
||||
*/
|
||||
|
||||
var datastructure = (function() {
|
||||
var AXIS_X = 0;
|
||||
var AXIS_Y = 1;
|
||||
var K = 2; // I only require a 2d k-d tree
|
||||
function KDTreeNode(point) {
|
||||
this.point = point;
|
||||
this.leftChild = null;
|
||||
this.rightChild = null;
|
||||
}
|
||||
function KDTree(points) {
|
||||
var boundingRect = {
|
||||
maxX: -Math.pow(2, 31),
|
||||
minX: Math.pow(2, 31) - 1,
|
||||
maxY: -Math.pow(2, 31),
|
||||
minY: Math.pow(2, 31) - 1
|
||||
};
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
boundingRect.minX = Math.min(boundingRect.minX, points[i].x);
|
||||
boundingRect.minY = Math.min(boundingRect.minY, points[i].y);
|
||||
boundingRect.maxX = Math.max(boundingRect.maxX, points[i].x);
|
||||
boundingRect.maxY = Math.max(boundingRect.maxY, points[i].y);
|
||||
}
|
||||
this.rootNode = createKDTree_(points, 0, boundingRect);
|
||||
};
|
||||
function createKDTree_(points, depth, boundingRect) {
|
||||
if (points.length == 0) {
|
||||
return null;
|
||||
}
|
||||
var axis = depth % K;
|
||||
points.sort(function (a, b) {
|
||||
if (axis == AXIS_X) {
|
||||
return a.x - b.x;
|
||||
} else {
|
||||
return a.y - b.y;
|
||||
}
|
||||
});
|
||||
var medianIndex = Math.floor(points.length / 2);
|
||||
var node = new KDTreeNode(points[medianIndex]);
|
||||
node.boundingRect = boundingRect;
|
||||
var leftChildBoundingRect = {
|
||||
minX: boundingRect.minX,
|
||||
maxX: axis == AXIS_X ? node.point.x : boundingRect.maxX,
|
||||
minY: boundingRect.minY,
|
||||
maxY: axis == AXIS_Y ? node.point.y : boundingRect.maxY
|
||||
};
|
||||
var rightChildBoundingRect = {
|
||||
minX: axis == AXIS_X ? node.point.x : boundingRect.minX,
|
||||
maxX: boundingRect.maxX,
|
||||
minY: axis == AXIS_Y ? node.point.y : boundingRect.minY,
|
||||
maxY: boundingRect.maxY
|
||||
};
|
||||
node.leftChild = createKDTree_(points.slice(0, medianIndex), depth + 1, leftChildBoundingRect);
|
||||
node.rightChild = createKDTree_(points.slice(medianIndex + 1), depth + 1, rightChildBoundingRect);
|
||||
return node;
|
||||
}
|
||||
KDTree.prototype.getNearestNeighbour = function(searchCoord, opt_consideredPoints) {
|
||||
var results = [];
|
||||
this.getNearestNeighbours_(this.rootNode, searchCoord, 0, results, 1, opt_consideredPoints);
|
||||
return results.length == 0 ? null : results[0].node.point;
|
||||
};
|
||||
KDTree.prototype.getNearestNeighbours = function(searchCoord, maxResults, opt_consideredPoints) {
|
||||
var results = [];
|
||||
this.getNearestNeighbours_(this.rootNode, searchCoord, 0, results, maxResults, opt_consideredPoints);
|
||||
var points = [];
|
||||
for (var i = 0; i < results.length; ++i) {
|
||||
points.push(results[i].node.point);
|
||||
}
|
||||
return points;
|
||||
};
|
||||
KDTree.prototype.getNearestNeighbours_ = function(currNode, searchCoord, depth, results, maxResults, opt_consideredPoints) {
|
||||
if (opt_consideredPoints) {
|
||||
opt_consideredPoints.push(currNode.point);
|
||||
}
|
||||
var axis = depth % K;
|
||||
var currNodeDistanceToDesiredCoord = getSquaredEuclidianDistance(searchCoord.x, searchCoord.y, currNode.point.x, currNode.point.y);
|
||||
var bestSeen = {node:currNode, distance: currNodeDistanceToDesiredCoord};
|
||||
insertResult_(results, bestSeen, maxResults);
|
||||
var searchNodeSplittingCoord = axis == AXIS_X ? searchCoord.x : searchCoord.y;
|
||||
var currNodeSplittingCoord = axis == AXIS_X ? currNode.point.x : currNode.point.y;
|
||||
var searchLeft = searchNodeSplittingCoord < currNodeSplittingCoord;
|
||||
var targetChild = searchLeft ? currNode.leftChild : currNode.rightChild;
|
||||
var oppositeChild = searchLeft ? currNode.rightChild : currNode.leftChild;
|
||||
if (targetChild) {
|
||||
this.getNearestNeighbours_(targetChild, searchCoord, depth + 1, results, maxResults, opt_consideredPoints);
|
||||
}
|
||||
if (oppositeChild) {
|
||||
var toX, toY;
|
||||
if (axis == AXIS_X) {
|
||||
toX = currNode.point.x;
|
||||
toY = searchCoord.y;
|
||||
if (searchCoord.y < oppositeChild.boundingRect.minY) {
|
||||
toY = oppositeChild.boundingRect.minY;
|
||||
} else if (searchCoord.y > oppositeChild.boundingRect.maxY) {
|
||||
toY = oppositeChild.boundingRect.maxY;
|
||||
}
|
||||
} else {
|
||||
toY = currNode.point.y;
|
||||
toX = searchCoord.x;
|
||||
if (searchCoord.x < oppositeChild.boundingRect.minX) {
|
||||
toX = oppositeChild.boundingRect.minX;
|
||||
} else if (searchCoord.x > oppositeChild.boundingRect.maxX) {
|
||||
toX = oppositeChild.boundingRect.maxX;
|
||||
}
|
||||
}
|
||||
var squaredDist = getSquaredEuclidianDistance(searchCoord.x, searchCoord.y, toX, toY);
|
||||
if (squaredDist <= results[results.length - 1].distance) {
|
||||
this.getNearestNeighbours_(oppositeChild, searchCoord, depth + 1, results, maxResults, opt_consideredPoints);
|
||||
}
|
||||
}
|
||||
};
|
||||
function insertResult_(results, insertNode, maxResults) {
|
||||
var insertIndex;
|
||||
for (insertIndex = results.length - 1; insertIndex >= 0; --insertIndex) {
|
||||
var nearestNeighbourNode = results[insertIndex];
|
||||
if (insertNode.distance > nearestNeighbourNode.distance) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
results.splice(insertIndex + 1, 0, insertNode);
|
||||
if (results.length > maxResults) {
|
||||
results.pop();
|
||||
}
|
||||
}
|
||||
function getSquaredEuclidianDistance(x1, y1, x2, y2) {
|
||||
var dx = x1 - x2;
|
||||
var dy = y1 - y2;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
var module = {};
|
||||
module.KDTree = KDTree; // KDTree constructor.
|
||||
return module;
|
||||
})();
|
||||
|
||||
@ -14,10 +14,11 @@ onmessage = function (event){
|
||||
var ratio_h = H / H2;
|
||||
var ratio_w_half = Math.ceil(ratio_w/2);
|
||||
var ratio_h_half = Math.ceil(ratio_h/2);
|
||||
var start_row = Math.round(H2*core/max_cores);
|
||||
var offset = Math.round(H2*core/max_cores) * W2 * 4;
|
||||
var start_row = Math.ceil(H2*core/max_cores)-1;
|
||||
if(start_row < 0) start_row = 0;
|
||||
var offset = Math.floor(H2*core/max_cores) * W2 * 4;
|
||||
|
||||
for(var j = start_row; j < start_row + Math.round(H2/max_cores); j++){
|
||||
for(var j = start_row; j < start_row + Math.ceil(H2/max_cores); j++){
|
||||
for(var i = 0; i < W2; i++){
|
||||
var x2 = (i + j*W2) * 4;
|
||||
var weight = 0;
|
||||
@ -45,7 +46,7 @@ onmessage = function (event){
|
||||
}
|
||||
}
|
||||
}
|
||||
var x2 = (i + j*W2) * 4 - offset; //var x2 = (Math.ceil(i*W2/W) + Math.ceil(j*H2/H)*W2) * 4 - offset;
|
||||
var x2 = (i + j*W2) * 4 - offset;
|
||||
data2[x2] = gx_r / weights;
|
||||
data2[x2 + 1] = gx_g / weights;
|
||||
data2[x2 + 2] = gx_b / weights;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user