mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
v 0.8.0b
This commit is contained in:
parent
707913f630
commit
680044ddd6
65 changed files with 14257 additions and 13020 deletions
2
libs/d3-scale-chromatic.v1.min.js
vendored
2
libs/d3-scale-chromatic.v1.min.js
vendored
File diff suppressed because one or more lines are too long
2
libs/d3.min.js
vendored
Normal file
2
libs/d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
libs/d3.v4.min.js
vendored
2
libs/d3.v4.min.js
vendored
File diff suppressed because one or more lines are too long
1
libs/delaunator.min.js
vendored
Normal file
1
libs/delaunator.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):t.Delaunator=i()}(this,function(){"use strict";var t=Math.pow(2,-52),i=function(i){var n=i.length>>1;if(n>0&&"number"!=typeof i[0])throw new Error("Expected coords to contain numbers.");this.coords=i;var s=2*n-5,l=this.triangles=new Uint32Array(3*s),o=this.halfedges=new Int32Array(3*s);this._hashSize=Math.ceil(Math.sqrt(n));for(var f=this.hullPrev=new Uint32Array(n),u=this.hullNext=new Uint32Array(n),v=this.hullTri=new Uint32Array(n),d=new Int32Array(this._hashSize).fill(-1),_=new Uint32Array(n),y=1/0,g=1/0,c=-1/0,w=-1/0,p=0;p<n;p++){var b=i[2*p],x=i[2*p+1];b<y&&(y=b),x<g&&(g=x),b>c&&(c=b),x>w&&(w=x),_[p]=p}for(var z,S,k,A=(y+c)/2,T=(g+w)/2,M=1/0,K=0;K<n;K++){var m=r(A,T,i[2*K],i[2*K+1]);m<M&&(z=K,M=m)}var U=i[2*z],L=i[2*z+1];M=1/0;for(var N=0;N<n;N++)if(N!==z){var E=r(U,L,i[2*N],i[2*N+1]);E<M&&E>0&&(S=N,M=E)}for(var D=i[2*S],F=i[2*S+1],I=1/0,P=0;P<n;P++)if(P!==z&&P!==S){var j=h(U,L,D,F,i[2*P],i[2*P+1]);j<I&&(k=P,I=j)}var q=i[2*k],B=i[2*k+1];if(I===1/0)throw new Error("No Delaunay triangulation exists for this input.");if(a(U,L,D,F,q,B)){var C=S,G=D,H=F;S=k,D=q,F=B,k=C,q=G,B=H}var J=function(t,i,r,a,h,e){var n=r-t,s=a-i,l=h-t,o=e-i,f=n*n+s*s,u=l*l+o*o,v=.5/(n*o-s*l);return{x:t+(o*f-s*u)*v,y:i+(n*u-l*f)*v}}(U,L,D,F,q,B);this._cx=J.x,this._cy=J.y;for(var O=new Float64Array(n),Q=0;Q<n;Q++)O[Q]=r(i[2*Q],i[2*Q+1],J.x,J.y);!function t(i,r,a,h){if(h-a<=20)for(var n=a+1;n<=h;n++){for(var s=i[n],l=r[s],o=n-1;o>=a&&r[i[o]]>l;)i[o+1]=i[o--];i[o+1]=s}else{var f=a+h>>1,u=a+1,v=h;e(i,f,u),r[i[a]]>r[i[h]]&&e(i,a,h),r[i[u]]>r[i[h]]&&e(i,u,h),r[i[a]]>r[i[u]]&&e(i,a,u);for(var d=i[u],_=r[d];;){do{u++}while(r[i[u]]<_);do{v--}while(r[i[v]]>_);if(v<u)break;e(i,u,v)}i[a+1]=i[v],i[v]=d,h-u+1>=v-a?(t(i,r,u,h),t(i,r,a,v-1)):(t(i,r,a,v-1),t(i,r,u,h))}}(_,O,0,n-1),this.hullStart=z;var R=3;u[z]=f[k]=S,u[S]=f[z]=k,u[k]=f[S]=z,v[z]=0,v[S]=1,v[k]=2,d[this._hashKey(U,L)]=z,d[this._hashKey(D,F)]=S,d[this._hashKey(q,B)]=k,this.trianglesLen=0,this._addTriangle(z,S,k,-1,-1,-1);for(var V=0,W=void 0,X=void 0;V<_.length;V++){var Y=_[V],Z=i[2*Y],$=i[2*Y+1];if(!(V>0&&Math.abs(Z-W)<=t&&Math.abs($-X)<=t)&&(W=Z,X=$,Y!==z&&Y!==S&&Y!==k)){for(var tt=0,it=0,rt=this._hashKey(Z,$);it<this._hashSize&&(-1===(tt=d[(rt+it)%this._hashSize])||tt===u[tt]);it++);for(var at=tt=f[tt],ht=void 0;ht=u[at],!a(Z,$,i[2*at],i[2*at+1],i[2*ht],i[2*ht+1]);)if((at=ht)===tt){at=-1;break}if(-1!==at){var et=this._addTriangle(at,Y,u[at],-1,-1,v[at]);v[Y]=this._legalize(et+2),v[at]=et,R++;for(var nt=u[at];ht=u[nt],a(Z,$,i[2*nt],i[2*nt+1],i[2*ht],i[2*ht+1]);)et=this._addTriangle(nt,Y,ht,v[Y],-1,v[nt]),v[Y]=this._legalize(et+2),u[nt]=nt,R--,nt=ht;if(at===tt)for(;a(Z,$,i[2*(ht=f[at])],i[2*ht+1],i[2*at],i[2*at+1]);)et=this._addTriangle(ht,Y,at,-1,v[at],v[ht]),this._legalize(et+2),v[ht]=et,u[at]=at,R--,at=ht;this.hullStart=f[Y]=at,u[at]=f[nt]=Y,u[Y]=nt,d[this._hashKey(Z,$)]=Y,d[this._hashKey(i[2*at],i[2*at+1])]=at}}}this.hull=new Uint32Array(R);for(var st=0,lt=this.hullStart;st<R;st++)this.hull[st]=lt,lt=u[lt];this.hullPrev=this.hullNext=this.hullTri=null,this.triangles=l.subarray(0,this.trianglesLen),this.halfedges=o.subarray(0,this.trianglesLen)};function r(t,i,r,a){var h=t-r,e=i-a;return h*h+e*e}function a(t,i,r,a,h,e){return(a-i)*(h-r)-(r-t)*(e-a)<0}function h(t,i,r,a,h,e){var n=r-t,s=a-i,l=h-t,o=e-i,f=n*n+s*s,u=l*l+o*o,v=.5/(n*o-s*l),d=(o*f-s*u)*v,_=(n*u-l*f)*v;return d*d+_*_}function e(t,i,r){var a=t[i];t[i]=t[r],t[r]=a}function n(t){return t[0]}function s(t){return t[1]}return i.from=function(t,r,a){void 0===r&&(r=n),void 0===a&&(a=s);for(var h=t.length,e=new Float64Array(2*h),l=0;l<h;l++){var o=t[l];e[2*l]=r(o),e[2*l+1]=a(o)}return new i(e)},i.prototype._hashKey=function(t,i){return Math.floor((r=t-this._cx,a=i-this._cy,h=r/(Math.abs(r)+Math.abs(a)),(a>0?3-h:1+h)/4*this._hashSize))%this._hashSize;var r,a,h},i.prototype._legalize=function(t){var i=this.triangles,r=this.coords,a=this.halfedges,h=a[t],e=t-t%3,n=h-h%3,s=e+(t+1)%3,l=e+(t+2)%3,o=n+(h+2)%3;if(-1===h)return l;var f,u,v,d,_,y,g,c,w,p,b,x,z,S,k,A,T=i[l],M=i[t],K=i[s],m=i[o];if(f=r[2*T],u=r[2*T+1],v=r[2*M],d=r[2*M+1],_=r[2*K],y=r[2*K+1],g=r[2*m],c=r[2*m+1],(w=f-g)*((x=d-c)*(A=(z=_-g)*z+(S=y-c)*S)-(k=(b=v-g)*b+x*x)*S)-(p=u-c)*(b*A-k*z)+(w*w+p*p)*(b*S-x*z)<0){i[t]=m,i[h]=T;var U=a[o];if(-1===U){var L=this.hullStart;do{if(this.hullTri[L]===o){this.hullTri[L]=t;break}L=this.hullNext[L]}while(L!==this.hullStart)}this._link(t,U),this._link(h,a[l]),this._link(l,o);var N=n+(h+1)%3;return this._legalize(t),this._legalize(N)}return l},i.prototype._link=function(t,i){this.halfedges[t]=i,-1!==i&&(this.halfedges[i]=t)},i.prototype._addTriangle=function(t,i,r,a,h,e){var n=this.trianglesLen;return this.triangles[n]=t,this.triangles[n+1]=i,this.triangles[n+2]=r,this._link(n,a),this._link(n+1,h),this._link(n+2,e),this.trianglesLen+=3,n},i});
|
||||
23
libs/jquery-ui.css
vendored
23
libs/jquery-ui.css
vendored
|
|
@ -314,13 +314,13 @@ body .ui-dialog {
|
|||
left: 0;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
background-color: inherit;
|
||||
}
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .4em 1em;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
font-size: 1.2em;
|
||||
min-width: 150px;
|
||||
}
|
||||
.ui-dialog .ui-dialog-title {
|
||||
float: left;
|
||||
|
|
@ -330,18 +330,33 @@ body .ui-dialog {
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar button {
|
||||
position: absolute;
|
||||
right: .5em;
|
||||
top: 53%;
|
||||
width: 18px;
|
||||
margin: -10px 0 0 0;
|
||||
padding: 0;
|
||||
height: 18px;
|
||||
color: #ffffff;
|
||||
background: none;
|
||||
font-size: 10px;
|
||||
border: 1px solid #c5c5c5;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-collapse {
|
||||
margin: -10px 22px 0 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-close {
|
||||
margin: -10px 0 0 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar button:active {
|
||||
border: 1px solid #5d4651;
|
||||
color: #5d4651;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-content {
|
||||
position: relative;
|
||||
border: 0;
|
||||
|
|
|
|||
10
libs/jquery-ui.min.js
vendored
10
libs/jquery-ui.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,232 +0,0 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.polylabel = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
||||
var Queue = require('tinyqueue');
|
||||
|
||||
module.exports = polylabel;
|
||||
|
||||
function polylabel(polygon, precision, debug) {
|
||||
precision = precision || 1.0;
|
||||
|
||||
// find the bounding box of the outer ring
|
||||
var minX, minY, maxX, maxY;
|
||||
for (var i = 0; i < polygon[0].length; i++) {
|
||||
var p = polygon[0][i];
|
||||
if (!i || p[0] < minX) minX = p[0];
|
||||
if (!i || p[1] < minY) minY = p[1];
|
||||
if (!i || p[0] > maxX) maxX = p[0];
|
||||
if (!i || p[1] > maxY) maxY = p[1];
|
||||
}
|
||||
|
||||
var width = maxX - minX;
|
||||
var height = maxY - minY;
|
||||
var cellSize = Math.min(width, height);
|
||||
var h = cellSize / 2;
|
||||
|
||||
// a priority queue of cells in order of their "potential" (max distance to polygon)
|
||||
var cellQueue = new Queue(null, compareMax);
|
||||
|
||||
// cover polygon with initial cells
|
||||
for (var x = minX; x < maxX; x += cellSize) {
|
||||
for (var y = minY; y < maxY; y += cellSize) {
|
||||
cellQueue.push(new Cell(x + h, y + h, h, polygon));
|
||||
}
|
||||
}
|
||||
|
||||
// take centroid as the first best guess
|
||||
var bestCell = getCentroidCell(polygon);
|
||||
var numProbes = cellQueue.length;
|
||||
|
||||
while (cellQueue.length) {
|
||||
// pick the most promising cell from the queue
|
||||
var cell = cellQueue.pop();
|
||||
|
||||
// update the best cell if we found a better one
|
||||
if (cell.d > bestCell.d) {
|
||||
bestCell = cell;
|
||||
if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
|
||||
}
|
||||
|
||||
// do not drill down further if there's no chance of a better solution
|
||||
if (cell.max - bestCell.d <= precision) continue;
|
||||
|
||||
// split the cell into four cells
|
||||
h = cell.h / 2;
|
||||
cellQueue.push(new Cell(cell.x - h, cell.y - h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x + h, cell.y - h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x - h, cell.y + h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x + h, cell.y + h, h, polygon));
|
||||
numProbes += 4;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.log('num probes: ' + numProbes);
|
||||
console.log('best distance: ' + bestCell.d);
|
||||
}
|
||||
|
||||
return [bestCell.x, bestCell.y];
|
||||
}
|
||||
|
||||
function compareMax(a, b) {
|
||||
return b.max - a.max;
|
||||
}
|
||||
|
||||
function Cell(x, y, h, polygon) {
|
||||
this.x = x; // cell center x
|
||||
this.y = y; // cell center y
|
||||
this.h = h; // half the cell size
|
||||
this.d = pointToPolygonDist(x, y, polygon); // distance from cell center to polygon
|
||||
this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
|
||||
}
|
||||
|
||||
// signed distance from point to polygon outline (negative if point is outside)
|
||||
function pointToPolygonDist(x, y, polygon) {
|
||||
var inside = false;
|
||||
var minDistSq = Infinity;
|
||||
|
||||
for (var k = 0; k < polygon.length; k++) {
|
||||
var ring = polygon[k];
|
||||
|
||||
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
|
||||
var a = ring[i];
|
||||
var b = ring[j];
|
||||
|
||||
if ((a[1] > y !== b[1] > y) &&
|
||||
(x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0])) inside = !inside;
|
||||
|
||||
minDistSq = Math.min(minDistSq, getSegDistSq(x, y, a, b));
|
||||
}
|
||||
}
|
||||
|
||||
return (inside ? 1 : -1) * Math.sqrt(minDistSq);
|
||||
}
|
||||
|
||||
// get polygon centroid
|
||||
function getCentroidCell(polygon) {
|
||||
var area = 0;
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var points = polygon[0];
|
||||
|
||||
for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
|
||||
var a = points[i];
|
||||
var b = points[j];
|
||||
var f = a[0] * b[1] - b[0] * a[1];
|
||||
x += (a[0] + b[0]) * f;
|
||||
y += (a[1] + b[1]) * f;
|
||||
area += f * 3;
|
||||
}
|
||||
return new Cell(x / area, y / area, 0, polygon);
|
||||
}
|
||||
|
||||
// get squared distance from a point to a segment
|
||||
function getSegDistSq(px, py, a, b) {
|
||||
|
||||
var x = a[0];
|
||||
var y = a[1];
|
||||
var dx = b[0] - x;
|
||||
var dy = b[1] - y;
|
||||
|
||||
if (dx !== 0 || dy !== 0) {
|
||||
|
||||
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
|
||||
|
||||
if (t > 1) {
|
||||
x = b[0];
|
||||
y = b[1];
|
||||
|
||||
} else if (t > 0) {
|
||||
x += dx * t;
|
||||
y += dy * t;
|
||||
}
|
||||
}
|
||||
|
||||
dx = px - x;
|
||||
dy = py - y;
|
||||
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
},{"tinyqueue":2}],2:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
||||
module.exports = TinyQueue;
|
||||
|
||||
function TinyQueue(data, compare) {
|
||||
if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
|
||||
|
||||
this.data = data || [];
|
||||
this.length = this.data.length;
|
||||
this.compare = compare || defaultCompare;
|
||||
|
||||
if (data) for (var i = Math.floor(this.length / 2); i >= 0; i--) this._down(i);
|
||||
}
|
||||
|
||||
function defaultCompare(a, b) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
TinyQueue.prototype = {
|
||||
|
||||
push: function (item) {
|
||||
this.data.push(item);
|
||||
this.length++;
|
||||
this._up(this.length - 1);
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
var top = this.data[0];
|
||||
this.data[0] = this.data[this.length - 1];
|
||||
this.length--;
|
||||
this.data.pop();
|
||||
this._down(0);
|
||||
return top;
|
||||
},
|
||||
|
||||
peek: function () {
|
||||
return this.data[0];
|
||||
},
|
||||
|
||||
_up: function (pos) {
|
||||
var data = this.data,
|
||||
compare = this.compare;
|
||||
|
||||
while (pos > 0) {
|
||||
var parent = Math.floor((pos - 1) / 2);
|
||||
if (compare(data[pos], data[parent]) < 0) {
|
||||
swap(data, parent, pos);
|
||||
pos = parent;
|
||||
|
||||
} else break;
|
||||
}
|
||||
},
|
||||
|
||||
_down: function (pos) {
|
||||
var data = this.data,
|
||||
compare = this.compare,
|
||||
len = this.length;
|
||||
|
||||
while (true) {
|
||||
var left = 2 * pos + 1,
|
||||
right = left + 1,
|
||||
min = pos;
|
||||
|
||||
if (left < len && compare(data[left], data[min]) < 0) min = left;
|
||||
if (right < len && compare(data[right], data[min]) < 0) min = right;
|
||||
|
||||
if (min === pos) return;
|
||||
|
||||
swap(data, min, pos);
|
||||
pos = min;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function swap(data, i, j) {
|
||||
var tmp = data[i];
|
||||
data[i] = data[j];
|
||||
data[j] = tmp;
|
||||
}
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -1,387 +0,0 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PriorityQueue = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||||
var AbstractPriorityQueue, ArrayStrategy, BHeapStrategy, BinaryHeapStrategy, PriorityQueue,
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
AbstractPriorityQueue = _dereq_('./PriorityQueue/AbstractPriorityQueue');
|
||||
|
||||
ArrayStrategy = _dereq_('./PriorityQueue/ArrayStrategy');
|
||||
|
||||
BinaryHeapStrategy = _dereq_('./PriorityQueue/BinaryHeapStrategy');
|
||||
|
||||
BHeapStrategy = _dereq_('./PriorityQueue/BHeapStrategy');
|
||||
|
||||
PriorityQueue = (function(superClass) {
|
||||
extend(PriorityQueue, superClass);
|
||||
|
||||
function PriorityQueue(options) {
|
||||
options || (options = {});
|
||||
options.strategy || (options.strategy = BinaryHeapStrategy);
|
||||
options.comparator || (options.comparator = function(a, b) {
|
||||
return (a || 0) - (b || 0);
|
||||
});
|
||||
PriorityQueue.__super__.constructor.call(this, options);
|
||||
}
|
||||
|
||||
return PriorityQueue;
|
||||
|
||||
})(AbstractPriorityQueue);
|
||||
|
||||
PriorityQueue.ArrayStrategy = ArrayStrategy;
|
||||
|
||||
PriorityQueue.BinaryHeapStrategy = BinaryHeapStrategy;
|
||||
|
||||
PriorityQueue.BHeapStrategy = BHeapStrategy;
|
||||
|
||||
module.exports = PriorityQueue;
|
||||
|
||||
|
||||
},{"./PriorityQueue/AbstractPriorityQueue":2,"./PriorityQueue/ArrayStrategy":3,"./PriorityQueue/BHeapStrategy":4,"./PriorityQueue/BinaryHeapStrategy":5}],2:[function(_dereq_,module,exports){
|
||||
var AbstractPriorityQueue;
|
||||
|
||||
module.exports = AbstractPriorityQueue = (function() {
|
||||
function AbstractPriorityQueue(options) {
|
||||
var ref;
|
||||
if ((options != null ? options.strategy : void 0) == null) {
|
||||
throw 'Must pass options.strategy, a strategy';
|
||||
}
|
||||
if ((options != null ? options.comparator : void 0) == null) {
|
||||
throw 'Must pass options.comparator, a comparator';
|
||||
}
|
||||
this.priv = new options.strategy(options);
|
||||
this.length = (options != null ? (ref = options.initialValues) != null ? ref.length : void 0 : void 0) || 0;
|
||||
}
|
||||
|
||||
AbstractPriorityQueue.prototype.queue = function(value) {
|
||||
this.length++;
|
||||
this.priv.queue(value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.dequeue = function(value) {
|
||||
if (!this.length) {
|
||||
throw 'Empty queue';
|
||||
}
|
||||
this.length--;
|
||||
return this.priv.dequeue();
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.peek = function(value) {
|
||||
if (!this.length) {
|
||||
throw 'Empty queue';
|
||||
}
|
||||
return this.priv.peek();
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
return this.priv.clear();
|
||||
};
|
||||
|
||||
return AbstractPriorityQueue;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],3:[function(_dereq_,module,exports){
|
||||
var ArrayStrategy, binarySearchForIndexReversed;
|
||||
|
||||
binarySearchForIndexReversed = function(array, value, comparator) {
|
||||
var high, low, mid;
|
||||
low = 0;
|
||||
high = array.length;
|
||||
while (low < high) {
|
||||
mid = (low + high) >>> 1;
|
||||
if (comparator(array[mid], value) >= 0) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
module.exports = ArrayStrategy = (function() {
|
||||
function ArrayStrategy(options) {
|
||||
var ref;
|
||||
this.options = options;
|
||||
this.comparator = this.options.comparator;
|
||||
this.data = ((ref = this.options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||
this.data.sort(this.comparator).reverse();
|
||||
}
|
||||
|
||||
ArrayStrategy.prototype.queue = function(value) {
|
||||
var pos;
|
||||
pos = binarySearchForIndexReversed(this.data, value, this.comparator);
|
||||
this.data.splice(pos, 0, value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.dequeue = function() {
|
||||
return this.data.pop();
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.peek = function() {
|
||||
return this.data[this.data.length - 1];
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.clear = function() {
|
||||
this.data.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return ArrayStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],4:[function(_dereq_,module,exports){
|
||||
var BHeapStrategy;
|
||||
|
||||
module.exports = BHeapStrategy = (function() {
|
||||
function BHeapStrategy(options) {
|
||||
var arr, i, j, k, len, ref, ref1, shift, value;
|
||||
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
this.pageSize = (options != null ? options.pageSize : void 0) || 512;
|
||||
this.length = 0;
|
||||
shift = 0;
|
||||
while ((1 << shift) < this.pageSize) {
|
||||
shift += 1;
|
||||
}
|
||||
if (1 << shift !== this.pageSize) {
|
||||
throw 'pageSize must be a power of two';
|
||||
}
|
||||
this._shift = shift;
|
||||
this._emptyMemoryPageTemplate = arr = [];
|
||||
for (i = j = 0, ref = this.pageSize; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
arr.push(null);
|
||||
}
|
||||
this._memory = [];
|
||||
this._mask = this.pageSize - 1;
|
||||
if (options.initialValues) {
|
||||
ref1 = options.initialValues;
|
||||
for (k = 0, len = ref1.length; k < len; k++) {
|
||||
value = ref1[k];
|
||||
this.queue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BHeapStrategy.prototype.queue = function(value) {
|
||||
this.length += 1;
|
||||
this._write(this.length, value);
|
||||
this._bubbleUp(this.length, value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.dequeue = function() {
|
||||
var ret, val;
|
||||
ret = this._read(1);
|
||||
val = this._read(this.length);
|
||||
this.length -= 1;
|
||||
if (this.length > 0) {
|
||||
this._write(1, val);
|
||||
this._bubbleDown(1, val);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.peek = function() {
|
||||
return this._read(1);
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
this._memory.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._write = function(index, value) {
|
||||
var page;
|
||||
page = index >> this._shift;
|
||||
while (page >= this._memory.length) {
|
||||
this._memory.push(this._emptyMemoryPageTemplate.slice(0));
|
||||
}
|
||||
return this._memory[page][index & this._mask] = value;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._read = function(index) {
|
||||
return this._memory[index >> this._shift][index & this._mask];
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._bubbleUp = function(index, value) {
|
||||
var compare, indexInPage, parentIndex, parentValue;
|
||||
compare = this.comparator;
|
||||
while (index > 1) {
|
||||
indexInPage = index & this._mask;
|
||||
if (index < this.pageSize || indexInPage > 3) {
|
||||
parentIndex = (index & ~this._mask) | (indexInPage >> 1);
|
||||
} else if (indexInPage < 2) {
|
||||
parentIndex = (index - this.pageSize) >> this._shift;
|
||||
parentIndex += parentIndex & ~(this._mask >> 1);
|
||||
parentIndex |= this.pageSize >> 1;
|
||||
} else {
|
||||
parentIndex = index - 2;
|
||||
}
|
||||
parentValue = this._read(parentIndex);
|
||||
if (compare(parentValue, value) < 0) {
|
||||
break;
|
||||
}
|
||||
this._write(parentIndex, value);
|
||||
this._write(index, parentValue);
|
||||
index = parentIndex;
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._bubbleDown = function(index, value) {
|
||||
var childIndex1, childIndex2, childValue1, childValue2, compare;
|
||||
compare = this.comparator;
|
||||
while (index < this.length) {
|
||||
if (index > this._mask && !(index & (this._mask - 1))) {
|
||||
childIndex1 = childIndex2 = index + 2;
|
||||
} else if (index & (this.pageSize >> 1)) {
|
||||
childIndex1 = (index & ~this._mask) >> 1;
|
||||
childIndex1 |= index & (this._mask >> 1);
|
||||
childIndex1 = (childIndex1 + 1) << this._shift;
|
||||
childIndex2 = childIndex1 + 1;
|
||||
} else {
|
||||
childIndex1 = index + (index & this._mask);
|
||||
childIndex2 = childIndex1 + 1;
|
||||
}
|
||||
if (childIndex1 !== childIndex2 && childIndex2 <= this.length) {
|
||||
childValue1 = this._read(childIndex1);
|
||||
childValue2 = this._read(childIndex2);
|
||||
if (compare(childValue1, value) < 0 && compare(childValue1, childValue2) <= 0) {
|
||||
this._write(childIndex1, value);
|
||||
this._write(index, childValue1);
|
||||
index = childIndex1;
|
||||
} else if (compare(childValue2, value) < 0) {
|
||||
this._write(childIndex2, value);
|
||||
this._write(index, childValue2);
|
||||
index = childIndex2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (childIndex1 <= this.length) {
|
||||
childValue1 = this._read(childIndex1);
|
||||
if (compare(childValue1, value) < 0) {
|
||||
this._write(childIndex1, value);
|
||||
this._write(index, childValue1);
|
||||
index = childIndex1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return BHeapStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],5:[function(_dereq_,module,exports){
|
||||
var BinaryHeapStrategy;
|
||||
|
||||
module.exports = BinaryHeapStrategy = (function() {
|
||||
function BinaryHeapStrategy(options) {
|
||||
var ref;
|
||||
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
this.length = 0;
|
||||
this.data = ((ref = options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||
this._heapify();
|
||||
}
|
||||
|
||||
BinaryHeapStrategy.prototype._heapify = function() {
|
||||
var i, j, ref;
|
||||
if (this.data.length > 0) {
|
||||
for (i = j = 1, ref = this.data.length; 1 <= ref ? j < ref : j > ref; i = 1 <= ref ? ++j : --j) {
|
||||
this._bubbleUp(i);
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.queue = function(value) {
|
||||
this.data.push(value);
|
||||
this._bubbleUp(this.data.length - 1);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.dequeue = function() {
|
||||
var last, ret;
|
||||
ret = this.data[0];
|
||||
last = this.data.pop();
|
||||
if (this.data.length > 0) {
|
||||
this.data[0] = last;
|
||||
this._bubbleDown(0);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.peek = function() {
|
||||
return this.data[0];
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
this.data.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype._bubbleUp = function(pos) {
|
||||
var parent, x;
|
||||
while (pos > 0) {
|
||||
parent = (pos - 1) >>> 1;
|
||||
if (this.comparator(this.data[pos], this.data[parent]) < 0) {
|
||||
x = this.data[parent];
|
||||
this.data[parent] = this.data[pos];
|
||||
this.data[pos] = x;
|
||||
pos = parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype._bubbleDown = function(pos) {
|
||||
var last, left, minIndex, right, x;
|
||||
last = this.data.length - 1;
|
||||
while (true) {
|
||||
left = (pos << 1) + 1;
|
||||
right = left + 1;
|
||||
minIndex = pos;
|
||||
if (left <= last && this.comparator(this.data[left], this.data[minIndex]) < 0) {
|
||||
minIndex = left;
|
||||
}
|
||||
if (right <= last && this.comparator(this.data[right], this.data[minIndex]) < 0) {
|
||||
minIndex = right;
|
||||
}
|
||||
if (minIndex !== pos) {
|
||||
x = this.data[minIndex];
|
||||
this.data[minIndex] = this.data[pos];
|
||||
this.data[pos] = x;
|
||||
pos = minIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return BinaryHeapStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
436
libs/quantize.js
436
libs/quantize.js
|
|
@ -1,436 +0,0 @@
|
|||
// Forked from color-thief.js Copyright 2011 Lokesh Dhakar under MIT license
|
||||
// var pixelArray = [[190,197,190], [202,204,200], [207,214,210]]; // ... etc;
|
||||
// var cmap = MMCQ.quantize(pixelArray, colorCount);
|
||||
// var palette = cmap ? cmap.palette() : null;
|
||||
|
||||
// Protovis. Copyright 2010 Stanford Visualization Group (http://mbostock.github.com/protovis/)
|
||||
// Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
|
||||
if (!pv) {
|
||||
var pv = {
|
||||
map: function(array, f) {
|
||||
var o = {};
|
||||
return f ? array.map(function(d, i) { o.index = i; return f.call(o, d); }) : array.slice();
|
||||
},
|
||||
naturalOrder: function(a, b) {
|
||||
return (a < b) ? -1 : ((a > b) ? 1 : 0);
|
||||
},
|
||||
sum: function(array, f) {
|
||||
var o = {};
|
||||
return array.reduce(f ? function(p, d, i) { o.index = i; return p + f.call(o, d); } : function(p, d) { return p + d; }, 0);
|
||||
},
|
||||
max: function(array, f) {
|
||||
return Math.max.apply(null, f ? pv.map(array, f) : array);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// MMCQ (Modified median cut quantization). Algorithm from the Leptonica library, modified by Nick Rabinowitz
|
||||
// quantize.js Copyright 2008 Nick Rabinowitz under MIT license
|
||||
var MMCQ = (function() {
|
||||
// private constants
|
||||
var sigbits = 5,
|
||||
rshift = 8 - sigbits,
|
||||
maxIterations = 1000,
|
||||
fractByPopulations = 0.75;
|
||||
|
||||
// get reduced-space color index for a pixel
|
||||
function getColorIndex(r, g, b) {
|
||||
return (r << (2 * sigbits)) + (g << sigbits) + b;
|
||||
}
|
||||
|
||||
// Simple priority queue
|
||||
function PQueue(comparator) {
|
||||
var contents = [],
|
||||
sorted = false;
|
||||
|
||||
function sort() {
|
||||
contents.sort(comparator);
|
||||
sorted = true;
|
||||
}
|
||||
|
||||
return {
|
||||
push: function(o) {
|
||||
contents.push(o);
|
||||
sorted = false;
|
||||
},
|
||||
peek: function(index) {
|
||||
if (!sorted) sort();
|
||||
if (index===undefined) index = contents.length - 1;
|
||||
return contents[index];
|
||||
},
|
||||
pop: function() {
|
||||
if (!sorted) sort();
|
||||
return contents.pop();
|
||||
},
|
||||
size: function() {
|
||||
return contents.length;
|
||||
},
|
||||
map: function(f) {
|
||||
return contents.map(f);
|
||||
},
|
||||
debug: function() {
|
||||
if (!sorted) sort();
|
||||
return contents;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 3d color space box
|
||||
function VBox(r1, r2, g1, g2, b1, b2, histo) {
|
||||
var vbox = this;
|
||||
vbox.r1 = r1;
|
||||
vbox.r2 = r2;
|
||||
vbox.g1 = g1;
|
||||
vbox.g2 = g2;
|
||||
vbox.b1 = b1;
|
||||
vbox.b2 = b2;
|
||||
vbox.histo = histo;
|
||||
}
|
||||
VBox.prototype = {
|
||||
volume: function(force) {
|
||||
var vbox = this;
|
||||
if (!vbox._volume || force) {
|
||||
vbox._volume = ((vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1));
|
||||
}
|
||||
return vbox._volume;
|
||||
},
|
||||
count: function(force) {
|
||||
var vbox = this,
|
||||
histo = vbox.histo;
|
||||
if (!vbox._count_set || force) {
|
||||
var npix = 0,
|
||||
index, i, j, k;
|
||||
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||
index = getColorIndex(i,j,k);
|
||||
npix += (histo[index] || 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
vbox._count = npix;
|
||||
vbox._count_set = true;
|
||||
}
|
||||
return vbox._count;
|
||||
},
|
||||
copy: function() {
|
||||
var vbox = this;
|
||||
return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
|
||||
},
|
||||
avg: function(force) {
|
||||
var vbox = this,
|
||||
histo = vbox.histo;
|
||||
if (!vbox._avg || force) {
|
||||
var ntot = 0,
|
||||
mult = 1 << (8 - sigbits),
|
||||
rsum = 0,
|
||||
gsum = 0,
|
||||
bsum = 0,
|
||||
hval,
|
||||
i, j, k, histoindex;
|
||||
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||
histoindex = getColorIndex(i,j,k);
|
||||
hval = histo[histoindex] || 0;
|
||||
ntot += hval;
|
||||
rsum += (hval * (i + 0.5) * mult);
|
||||
gsum += (hval * (j + 0.5) * mult);
|
||||
bsum += (hval * (k + 0.5) * mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ntot) {
|
||||
vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)];
|
||||
} else {
|
||||
// console.log('empty box');
|
||||
vbox._avg = [
|
||||
~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
|
||||
~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
|
||||
~~(mult * (vbox.b1 + vbox.b2 + 1) / 2)
|
||||
];
|
||||
}
|
||||
}
|
||||
return vbox._avg;
|
||||
},
|
||||
contains: function(pixel) {
|
||||
var vbox = this,
|
||||
rval = pixel[0] >> rshift;
|
||||
gval = pixel[1] >> rshift;
|
||||
bval = pixel[2] >> rshift;
|
||||
return (rval >= vbox.r1 && rval <= vbox.r2 &&
|
||||
gval >= vbox.g1 && gval <= vbox.g2 &&
|
||||
bval >= vbox.b1 && bval <= vbox.b2);
|
||||
}
|
||||
};
|
||||
|
||||
// Color map
|
||||
function CMap() {
|
||||
this.vboxes = new PQueue(function(a,b) {
|
||||
return pv.naturalOrder(
|
||||
a.vbox.count()*a.vbox.volume(),
|
||||
b.vbox.count()*b.vbox.volume()
|
||||
);
|
||||
});
|
||||
}
|
||||
CMap.prototype = {
|
||||
push: function(vbox) {
|
||||
this.vboxes.push({
|
||||
vbox: vbox,
|
||||
color: vbox.avg()
|
||||
});
|
||||
},
|
||||
palette: function() {
|
||||
return this.vboxes.map(function(vb) { return vb.color; });
|
||||
},
|
||||
size: function() {
|
||||
return this.vboxes.size();
|
||||
},
|
||||
map: function(color) {
|
||||
var vboxes = this.vboxes;
|
||||
for (var i=0; i<vboxes.size(); i++) {
|
||||
if (vboxes.peek(i).vbox.contains(color)) {
|
||||
return vboxes.peek(i).color;
|
||||
}
|
||||
}
|
||||
return this.nearest(color);
|
||||
},
|
||||
nearest: function(color) {
|
||||
var vboxes = this.vboxes,
|
||||
d1, d2, pColor;
|
||||
for (var i=0; i<vboxes.size(); i++) {
|
||||
d2 = Math.sqrt(
|
||||
Math.pow(color[0] - vboxes.peek(i).color[0], 2) +
|
||||
Math.pow(color[1] - vboxes.peek(i).color[1], 2) +
|
||||
Math.pow(color[2] - vboxes.peek(i).color[2], 2)
|
||||
);
|
||||
if (d2 < d1 || d1 === undefined) {
|
||||
d1 = d2;
|
||||
pColor = vboxes.peek(i).color;
|
||||
}
|
||||
}
|
||||
return pColor;
|
||||
},
|
||||
forcebw: function() {
|
||||
// XXX: won't work yet
|
||||
var vboxes = this.vboxes;
|
||||
vboxes.sort(function(a,b) { return pv.naturalOrder(pv.sum(a.color), pv.sum(b.color));});
|
||||
|
||||
// force darkest color to black if everything < 5
|
||||
var lowest = vboxes[0].color;
|
||||
if (lowest[0] < 5 && lowest[1] < 5 && lowest[2] < 5)
|
||||
vboxes[0].color = [0,0,0];
|
||||
|
||||
// force lightest color to white if everything > 251
|
||||
var idx = vboxes.length-1,
|
||||
highest = vboxes[idx].color;
|
||||
if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
|
||||
vboxes[idx].color = [255,255,255];
|
||||
}
|
||||
};
|
||||
|
||||
// histo (1-d array, giving the number of pixels in
|
||||
// each quantized region of color space), or null on error
|
||||
function getHisto(pixels) {
|
||||
var histosize = 1 << (3 * sigbits),
|
||||
histo = new Array(histosize),
|
||||
index, rval, gval, bval;
|
||||
pixels.forEach(function(pixel) {
|
||||
rval = pixel[0] >> rshift;
|
||||
gval = pixel[1] >> rshift;
|
||||
bval = pixel[2] >> rshift;
|
||||
index = getColorIndex(rval, gval, bval);
|
||||
histo[index] = (histo[index] || 0) + 1;
|
||||
});
|
||||
return histo;
|
||||
}
|
||||
|
||||
function vboxFromPixels(pixels, histo) {
|
||||
var rmin=1000000, rmax=0,
|
||||
gmin=1000000, gmax=0,
|
||||
bmin=1000000, bmax=0,
|
||||
rval, gval, bval;
|
||||
// find min/max
|
||||
pixels.forEach(function(pixel) {
|
||||
rval = pixel[0] >> rshift;
|
||||
gval = pixel[1] >> rshift;
|
||||
bval = pixel[2] >> rshift;
|
||||
if (rval < rmin) rmin = rval;
|
||||
else if (rval > rmax) rmax = rval;
|
||||
if (gval < gmin) gmin = gval;
|
||||
else if (gval > gmax) gmax = gval;
|
||||
if (bval < bmin) bmin = bval;
|
||||
else if (bval > bmax) bmax = bval;
|
||||
});
|
||||
return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo);
|
||||
}
|
||||
|
||||
function medianCutApply(histo, vbox) {
|
||||
if (!vbox.count()) return;
|
||||
|
||||
var rw = vbox.r2 - vbox.r1 + 1,
|
||||
gw = vbox.g2 - vbox.g1 + 1,
|
||||
bw = vbox.b2 - vbox.b1 + 1,
|
||||
maxw = pv.max([rw, gw, bw]);
|
||||
// only one pixel, no split
|
||||
if (vbox.count() == 1) {
|
||||
return [vbox.copy()];
|
||||
}
|
||||
/* Find the partial sum arrays along the selected axis. */
|
||||
var total = 0,
|
||||
partialsum = [],
|
||||
lookaheadsum = [],
|
||||
i, j, k, sum, index;
|
||||
if (maxw == rw) {
|
||||
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||
sum = 0;
|
||||
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||
index = getColorIndex(i,j,k);
|
||||
sum += (histo[index] || 0);
|
||||
}
|
||||
}
|
||||
total += sum;
|
||||
partialsum[i] = total;
|
||||
}
|
||||
}
|
||||
else if (maxw == gw) {
|
||||
for (i = vbox.g1; i <= vbox.g2; i++) {
|
||||
sum = 0;
|
||||
for (j = vbox.r1; j <= vbox.r2; j++) {
|
||||
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||
index = getColorIndex(j,i,k);
|
||||
sum += (histo[index] || 0);
|
||||
}
|
||||
}
|
||||
total += sum;
|
||||
partialsum[i] = total;
|
||||
}
|
||||
}
|
||||
else { /* maxw == bw */
|
||||
for (i = vbox.b1; i <= vbox.b2; i++) {
|
||||
sum = 0;
|
||||
for (j = vbox.r1; j <= vbox.r2; j++) {
|
||||
for (k = vbox.g1; k <= vbox.g2; k++) {
|
||||
index = getColorIndex(j,k,i);
|
||||
sum += (histo[index] || 0);
|
||||
}
|
||||
}
|
||||
total += sum;
|
||||
partialsum[i] = total;
|
||||
}
|
||||
}
|
||||
partialsum.forEach(function(d,i) {
|
||||
lookaheadsum[i] = total-d;
|
||||
});
|
||||
function doCut(color) {
|
||||
var dim1 = color + '1',
|
||||
dim2 = color + '2',
|
||||
left, right, vbox1, vbox2, d2, count2=0;
|
||||
for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
|
||||
if (partialsum[i] > total / 2) {
|
||||
vbox1 = vbox.copy();
|
||||
vbox2 = vbox.copy();
|
||||
left = i - vbox[dim1];
|
||||
right = vbox[dim2] - i;
|
||||
if (left <= right)
|
||||
d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2));
|
||||
else d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2));
|
||||
// avoid 0-count boxes
|
||||
while (!partialsum[d2]) d2++;
|
||||
count2 = lookaheadsum[d2];
|
||||
while (!count2 && partialsum[d2-1]) count2 = lookaheadsum[--d2];
|
||||
// set dimensions
|
||||
vbox1[dim2] = d2;
|
||||
vbox2[dim1] = vbox1[dim2] + 1;
|
||||
// console.log('vbox counts:', vbox.count(), vbox1.count(), vbox2.count());
|
||||
return [vbox1, vbox2];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// determine the cut planes
|
||||
return maxw == rw ? doCut('r') :
|
||||
maxw == gw ? doCut('g') :
|
||||
doCut('b');
|
||||
}
|
||||
|
||||
function quantize(pixels, maxcolors) {
|
||||
maxcolors++;
|
||||
if (!pixels.length || maxcolors < 2 || maxcolors > 256) {return false;}
|
||||
|
||||
// XXX: check color content and convert to grayscale if insufficient
|
||||
var histo = getHisto(pixels),
|
||||
histosize = 1 << (3 * sigbits);
|
||||
|
||||
// check that we aren't below maxcolors already
|
||||
var nColors = 0;
|
||||
histo.forEach(function() { nColors++; });
|
||||
if (nColors <= maxcolors) {
|
||||
// XXX: generate the new colors from the histo and return
|
||||
}
|
||||
|
||||
// get the beginning vbox from the colors
|
||||
var vbox = vboxFromPixels(pixels, histo),
|
||||
pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()); });
|
||||
pq.push(vbox);
|
||||
|
||||
// inner function to do the iteration
|
||||
function iter(lh, target) {
|
||||
var ncolors = 1,
|
||||
niters = 0,
|
||||
vbox;
|
||||
while (niters < maxIterations) {
|
||||
vbox = lh.pop();
|
||||
if (!vbox.count()) { /* just put it back */
|
||||
lh.push(vbox);
|
||||
niters++;
|
||||
continue;
|
||||
}
|
||||
// do the cut
|
||||
var vboxes = medianCutApply(histo, vbox),
|
||||
vbox1 = vboxes[0],
|
||||
vbox2 = vboxes[1];
|
||||
|
||||
if (!vbox1) {
|
||||
// console.log("vbox1 not defined; shouldn't happen!");
|
||||
return;
|
||||
}
|
||||
lh.push(vbox1);
|
||||
if (vbox2) { /* vbox2 can be null */
|
||||
lh.push(vbox2);
|
||||
ncolors++;
|
||||
}
|
||||
if (ncolors >= target) return;
|
||||
if (niters++ > maxIterations) {
|
||||
// console.log("infinite loop; perhaps too few pixels!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// first set of colors, sorted by population
|
||||
iter(pq, fractByPopulations * maxcolors);
|
||||
|
||||
// Re-sort by the product of pixel occupancy times the size in color space.
|
||||
var pq2 = new PQueue(function(a,b) {
|
||||
return pv.naturalOrder(a.count()*a.volume(), b.count()*b.volume());
|
||||
});
|
||||
while (pq.size()) {
|
||||
pq2.push(pq.pop());
|
||||
}
|
||||
|
||||
// next set - generate the median cuts using the (npix * vol) sorting.
|
||||
iter(pq2, maxcolors - pq2.size());
|
||||
|
||||
// calculate the actual colors
|
||||
var cmap = new CMap();
|
||||
while (pq2.size()) {cmap.push(pq2.pop());}
|
||||
|
||||
return cmap;
|
||||
}
|
||||
|
||||
return {
|
||||
quantize: quantize
|
||||
};
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue