Move color matrix code into ol.color.Matrix
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
// We can't use goog.color or goog.color.alpha because they interally use a hex
|
||||
// string representation that encodes each channel in a single byte. This
|
||||
// causes occasional loss of precision and rounding errors, especially in the
|
||||
// alpha channel.
|
||||
|
||||
goog.provide('ol.color');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.color');
|
||||
goog.require('goog.color.names');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.vec.Mat4');
|
||||
|
||||
|
||||
/**
|
||||
* A color represented as a short array [red, green, blue, alpha].
|
||||
* red, green, and blue should be integers in the range 0..255 inclusive.
|
||||
* alpha should be a float in the range 0..1 inclusive.
|
||||
* @typedef {Array.<number>}
|
||||
*/
|
||||
ol.Color;
|
||||
|
||||
|
||||
/**
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
* This RegExp matches # followed by 3, 4, 6, or 8 hex digits.
|
||||
*/
|
||||
ol.color.hexColorRe_ = /^#(?:[0-9a-f]{3,4}){1,2}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
* @see goog.color.rgbColorRe_
|
||||
*/
|
||||
ol.color.rgbColorRe_ =
|
||||
/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
* @see goog.color.alpha.rgbaColorRe_
|
||||
*/
|
||||
ol.color.rgbaColorRe_ =
|
||||
/^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.fromString = (function() {
|
||||
|
||||
// We maintain a small cache of parsed strings. To provide cheap LRU-like
|
||||
// semantics, whenever the cache grows too large we simply delete an
|
||||
// arbitrary 25% of the entries.
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
var MAX_CACHE_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* @type {Object.<string, ol.Color>}
|
||||
*/
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
var cacheSize = 0;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
function(s, opt_color) {
|
||||
var color;
|
||||
if (cache.hasOwnProperty(s)) {
|
||||
color = cache[s];
|
||||
} else {
|
||||
if (cacheSize >= MAX_CACHE_SIZE) {
|
||||
var i = 0;
|
||||
var key;
|
||||
for (key in cache) {
|
||||
if (i++ & 3 === 0) {
|
||||
delete cache[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
color = ol.color.fromStringInternal_(s);
|
||||
cache[s] = color;
|
||||
++cacheSize;
|
||||
}
|
||||
return ol.color.returnOrUpdate(color, opt_color);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @private
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.fromStringInternal_ = function(s) {
|
||||
|
||||
var isHex = false;
|
||||
if (goog.color.names.hasOwnProperty(s)) {
|
||||
s = goog.color.names[s];
|
||||
isHex = true;
|
||||
}
|
||||
|
||||
var r, g, b, a, color, match;
|
||||
if (isHex || (match = ol.color.hexColorRe_.exec(s))) { // hex
|
||||
var n = s.length - 1; // number of hex digits
|
||||
goog.asserts.assert(goog.array.indexOf([3, 4, 6, 8], n) != -1);
|
||||
var d = n < 6 ? 1 : 2; // number of digits per channel
|
||||
r = parseInt(s.substr(1 + 0 * d, d), 16);
|
||||
g = parseInt(s.substr(1 + 1 * d, d), 16);
|
||||
b = parseInt(s.substr(1 + 2 * d, d), 16);
|
||||
if (d == 1) {
|
||||
r = (r << 4) + r;
|
||||
g = (g << 4) + g;
|
||||
b = (b << 4) + b;
|
||||
}
|
||||
if ((n >> 1) & 1) {
|
||||
a = 1;
|
||||
} else { // has alpha channel
|
||||
a = parseInt(s.substr(1 + 3 * d, d), 16) / (d == 1 ? 15 : 255);
|
||||
}
|
||||
color = [r, g, b, a];
|
||||
goog.asserts.assert(ol.color.isValid(color));
|
||||
return color;
|
||||
} else if ((match = ol.color.rgbaColorRe_.exec(s))) { // rgba()
|
||||
r = Number(match[1]);
|
||||
g = Number(match[2]);
|
||||
b = Number(match[3]);
|
||||
a = Number(match[4]);
|
||||
color = [r, g, b, a];
|
||||
return ol.color.normalize(color, color);
|
||||
} else if ((match = ol.color.rgbColorRe_.exec(s))) { // rgb()
|
||||
r = Number(match[1]);
|
||||
g = Number(match[2]);
|
||||
b = Number(match[3]);
|
||||
color = [r, g, b, 1];
|
||||
return ol.color.normalize(color, color);
|
||||
} else {
|
||||
throw new Error(s + ' is not a valid color');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @return {boolean} Is valid.
|
||||
*/
|
||||
ol.color.isValid = function(color) {
|
||||
return 0 <= color[0] && color[0] < 256 &&
|
||||
0 <= color[1] && color[1] < 256 &&
|
||||
0 <= color[2] && color[2] < 256 &&
|
||||
0 <= color[3] && color[3] <= 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Clamped color.
|
||||
*/
|
||||
ol.color.normalize = function(color, opt_color) {
|
||||
var result = goog.isDef(opt_color) ? opt_color : [];
|
||||
result[0] = goog.math.clamp((color[0] + 0.5) | 0, 0, 255);
|
||||
result[1] = goog.math.clamp((color[1] + 0.5) | 0, 0, 255);
|
||||
result[2] = goog.math.clamp((color[2] + 0.5) | 0, 0, 255);
|
||||
result[3] = goog.math.clamp(color[3], 0, 1);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Color.
|
||||
*/
|
||||
ol.color.returnOrUpdate = function(color, opt_color) {
|
||||
if (goog.isDef(opt_color)) {
|
||||
opt_color[0] = color[0];
|
||||
opt_color[1] = color[1];
|
||||
opt_color[2] = color[2];
|
||||
opt_color[3] = color[3];
|
||||
return opt_color;
|
||||
} else {
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @return {string} String.
|
||||
*/
|
||||
ol.color.toString = function(color) {
|
||||
var r = color[0];
|
||||
if (r != (r | 0)) {
|
||||
r = (r + 0.5) | 0;
|
||||
}
|
||||
var g = color[1];
|
||||
if (g != (g | 0)) {
|
||||
g = (g + 0.5) | 0;
|
||||
}
|
||||
var b = color[2];
|
||||
if (b != (b | 0)) {
|
||||
b = (b + 0.5) | 0;
|
||||
}
|
||||
var a = color[3];
|
||||
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Color} color Color.
|
||||
* @param {goog.vec.Mat4.AnyType} transform Transform.
|
||||
* @param {ol.Color=} opt_color Color.
|
||||
* @return {ol.Color} Transformed color.
|
||||
*/
|
||||
ol.color.transform = function(color, transform, opt_color) {
|
||||
var result = goog.isDef(opt_color) ? opt_color : [];
|
||||
result = goog.vec.Mat4.multVec3(transform, color, result);
|
||||
goog.asserts.assert(goog.isArray(result));
|
||||
result[3] = color[3];
|
||||
return ol.color.normalize(result, result);
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
goog.provide('ol.color.Matrix');
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
ol.color.Matrix = function() {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.colorMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.brightness_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.brightnessMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.contrast_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.contrastMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.hue_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.hueMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.saturation_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.saturationMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Brightness value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeBrightness = function(matrix, value) {
|
||||
goog.vec.Mat4.makeTranslate(matrix, value, value, value);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Contrast value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeContrast = function(matrix, value) {
|
||||
goog.vec.Mat4.makeScale(matrix, value, value, value);
|
||||
var translateValue = (-0.5 * value + 0.5);
|
||||
goog.vec.Mat4.setColumnValues(matrix, 3,
|
||||
translateValue, translateValue, translateValue, 1);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Hue value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeHue = function(matrix, value) {
|
||||
var cosHue = Math.cos(value);
|
||||
var sinHue = Math.sin(value);
|
||||
var v00 = 0.213 + cosHue * 0.787 - sinHue * 0.213;
|
||||
var v01 = 0.715 - cosHue * 0.715 - sinHue * 0.715;
|
||||
var v02 = 0.072 - cosHue * 0.072 + sinHue * 0.928;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - cosHue * 0.213 + sinHue * 0.143;
|
||||
var v11 = 0.715 + cosHue * 0.285 + sinHue * 0.140;
|
||||
var v12 = 0.072 - cosHue * 0.072 - sinHue * 0.283;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - cosHue * 0.213 - sinHue * 0.787;
|
||||
var v21 = 0.715 - cosHue * 0.715 + sinHue * 0.715;
|
||||
var v22 = 0.072 + cosHue * 0.928 + sinHue * 0.072;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.vec.Mat4.Number} matrix Matrix.
|
||||
* @param {number} value Saturation value.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.makeSaturation = function(matrix, value) {
|
||||
var v00 = 0.213 + 0.787 * value;
|
||||
var v01 = 0.715 - 0.715 * value;
|
||||
var v02 = 0.072 - 0.072 * value;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - 0.213 * value;
|
||||
var v11 = 0.715 + 0.285 * value;
|
||||
var v12 = 0.072 - 0.072 * value;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - 0.213 * value;
|
||||
var v21 = 0.715 - 0.715 * value;
|
||||
var v22 = 0.072 + 0.928 * value;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number|undefined} brightness Brightness.
|
||||
* @param {number|undefined} contrast Contrast.
|
||||
* @param {number|undefined} hue Hue.
|
||||
* @param {number|undefined} saturation Saturation.
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.color.Matrix.prototype.getMatrix = function(
|
||||
brightness, contrast, hue, saturation) {
|
||||
var colorMatrixDirty = false;
|
||||
if (goog.isDef(brightness) && brightness !== this.brightness_) {
|
||||
ol.color.Matrix.makeBrightness(this.brightnessMatrix_, brightness);
|
||||
this.brightness_ = brightness;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(contrast) && contrast !== this.contrast_) {
|
||||
ol.color.Matrix.makeContrast(this.contrastMatrix_, contrast);
|
||||
this.contrast_ = contrast;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(hue) && hue !== this.hue_) {
|
||||
ol.color.Matrix.makeHue(this.hueMatrix_, hue);
|
||||
this.hue_ = hue;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (goog.isDef(saturation) && saturation !== this.saturation_) {
|
||||
ol.color.Matrix.makeSaturation(this.saturationMatrix_, saturation);
|
||||
this.saturation_ = saturation;
|
||||
colorMatrixDirty = true;
|
||||
}
|
||||
if (colorMatrixDirty) {
|
||||
var colorMatrix = this.colorMatrix_;
|
||||
goog.vec.Mat4.makeIdentity(colorMatrix);
|
||||
if (goog.isDef(contrast)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.contrastMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(brightness)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.brightnessMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(saturation)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.saturationMatrix_, colorMatrix);
|
||||
}
|
||||
if (goog.isDef(hue)) {
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.hueMatrix_, colorMatrix);
|
||||
}
|
||||
}
|
||||
return this.colorMatrix_;
|
||||
};
|
||||
Reference in New Issue
Block a user