mirror of
https://github.com/konvajs/konva.git
synced 2025-10-14 03:24:54 +08:00
New HSL filter. HSV and HSL want values between -1.0 and +1.0 (was 0.5 to 2.0)
This commit is contained in:
@@ -16,6 +16,7 @@ module.exports = function(grunt) {
|
||||
'src/filters/Mask.js',
|
||||
'src/filters/RGB.js',
|
||||
'src/filters/HSV.js',
|
||||
'src/filters/HSL.js',
|
||||
'src/filters/Emboss.js',
|
||||
'src/filters/Enhance.js',
|
||||
'src/filters/Posterize.js',
|
||||
|
118
src/filters/HSL.js
Normal file
118
src/filters/HSL.js
Normal file
@@ -0,0 +1,118 @@
|
||||
(function () {
|
||||
|
||||
HSV = function (imageData) {
|
||||
var data = imageData.data,
|
||||
nPixels = data.length,
|
||||
v = Math.pow(2,this.value()),
|
||||
s = Math.pow(2,this.saturation()),
|
||||
h = Math.abs((this.hue()) + 360) % 360,
|
||||
i;
|
||||
|
||||
// Basis for the technique used:
|
||||
// http://beesbuzz.biz/code/hsv_color_transforms.php
|
||||
// V is the value multiplier (1 for none, 2 for double, 0.5 for half)
|
||||
// S is the saturation multiplier (1 for none, 2 for double, 0.5 for half)
|
||||
// H is the hue shift in degrees (0 to 360)
|
||||
// vsu = V*S*cos(H*PI/180);
|
||||
// vsw = V*S*sin(H*PI/180);
|
||||
//[ .299V+.701vsu+.168vsw .587V-.587vsu+.330vsw .114V-.114vsu-.497vsw ] [R]
|
||||
//[ .299V-.299vsu-.328vsw .587V+.413vsu+.035vsw .114V-.114vsu+.292vsw ]*[G]
|
||||
//[ .299V-.300vsu+1.25vsw .587V-.588vsu-1.05vsw .114V+.886vsu-.203vsw ] [B]
|
||||
|
||||
// Precompute the values in the matrix:
|
||||
var vsu = v*s*Math.cos(h*Math.PI/180),
|
||||
vsw = v*s*Math.sin(h*Math.PI/180);
|
||||
// (result spot)(source spot)
|
||||
var rr = 0.299*v+0.701*vsu+0.167*vsw,
|
||||
rg = 0.587*v-0.587*vsu+0.330*vsw,
|
||||
rb = 0.114*v-0.114*vsu-0.497*vsw;
|
||||
var gr = 0.299*v-0.299*vsu-0.328*vsw,
|
||||
gg = 0.587*v+0.413*vsu+0.035*vsw,
|
||||
gb = 0.114*v-0.114*vsu+0.293*vsw;
|
||||
var br = 0.299*v-0.300*vsu+1.250*vsw,
|
||||
bg = 0.587*v-0.586*vsu-1.050*vsw,
|
||||
bb = 0.114*v+0.886*vsu-0.200*vsw;
|
||||
|
||||
var r,g,b,a;
|
||||
|
||||
for (i = 0; i < nPixels; i += 4) {
|
||||
r = data[i+0];
|
||||
g = data[i+1];
|
||||
b = data[i+2];
|
||||
a = data[i+3];
|
||||
|
||||
data[i+0] = rr*r + rg*g + rb*b;
|
||||
data[i+1] = gr*r + gg*g + gb*b;
|
||||
data[i+2] = br*r + bg*g + bb*b;
|
||||
data[i+3] = a; // alpha
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'hue', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsv hue in degrees
|
||||
* @name hue
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} hue value between 0 and 359
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'saturation', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsv saturation
|
||||
* @name saturation
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} saturation 0 is no change, -1.0 halves the saturation, 1.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'value', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsv value
|
||||
* @name value
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} value 0 is no change, -1.0 halves the value, 1.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'luminance', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsl luminance
|
||||
* @name value
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} value 0 is no change, -1.0 halves the value, 1.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
/**
|
||||
* HSL Filter. Adjusts the hue, saturation and luminance (or lightness)
|
||||
* @function
|
||||
* @memberof Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @author ippo615
|
||||
*/
|
||||
|
||||
Kinetic.Filters.HSL = function (imageData) {
|
||||
// Hue stays the same but saturation, value and brightness will be
|
||||
// adjusted to match common photo-editing software's extreme values
|
||||
var oldSaturation = this.saturation(),
|
||||
oldBrightness = this.brightness(),
|
||||
oldValue = this.value();
|
||||
|
||||
this.saturation(oldSaturation);
|
||||
this.brightness(0.5*this.luminance());
|
||||
this.value(0.0);
|
||||
|
||||
HSV.call(this,imageData);
|
||||
Kinetic.Filters.Brighten.call(this,imageData);
|
||||
|
||||
this.saturation(oldSaturation);
|
||||
this.brightness(oldBrightness);
|
||||
this.value(oldValue);
|
||||
};
|
||||
})();
|
@@ -11,8 +11,8 @@
|
||||
Kinetic.Filters.HSV = function (imageData) {
|
||||
var data = imageData.data,
|
||||
nPixels = data.length,
|
||||
v = this.value(),
|
||||
s = this.saturation(),
|
||||
v = Math.pow(2,this.value()),
|
||||
s = Math.pow(2,this.saturation()),
|
||||
h = Math.abs((this.hue()) + 360) % 360,
|
||||
i;
|
||||
|
||||
@@ -67,60 +67,24 @@
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'saturation', 1, null, Kinetic.Factory.afterSetFilter);
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'saturation', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsv saturation
|
||||
* @name saturation
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} saturation 1 is no change, 0.5 halves the saturation, 2.0 doubles, etc..
|
||||
* @param {Number} saturation 0 is no change, -1.0 halves the saturation, 1.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'value', 1, null, Kinetic.Factory.afterSetFilter);
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'value', 0, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsv value
|
||||
* @name value
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} value 1 is no change, 0.5 halves the value, 2.0 doubles, etc..
|
||||
* @param {Number} value 0 is no change, -1.0 halves the value, 1.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'luminance', 1, null, Kinetic.Factory.afterSetFilter);
|
||||
/**
|
||||
* get/set hsl luminance
|
||||
* @name value
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} value 1 is no change, 0.5 halves the value, 2.0 doubles, etc..
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
/**
|
||||
* HSL Filter. Adjusts the hue, saturation and luminance (or lightness)
|
||||
* @function
|
||||
* @memberof Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @author ippo615
|
||||
*/
|
||||
|
||||
Kinetic.Filters.HSL = function (imageData) {
|
||||
// Hue stays the same but saturation, value and brightness will be
|
||||
// adjusted to match common photo-editing software's extreme values
|
||||
var oldSaturation = this.saturation(),
|
||||
oldBrightness = this.brightness(),
|
||||
oldValue = this.value();
|
||||
|
||||
this.saturation(oldSaturation*oldSaturation);
|
||||
this.brightness(0.5*(this.luminance()-1));
|
||||
this.value(1.0);
|
||||
|
||||
Kinetic.Filters.HSV.call(this,imageData);
|
||||
Kinetic.Filters.Brighten.call(this,imageData);
|
||||
|
||||
this.saturation(oldSaturation);
|
||||
this.brightness(oldBrightness);
|
||||
this.value(oldValue);
|
||||
};
|
||||
})();
|
||||
|
@@ -84,6 +84,7 @@
|
||||
<script src="unit/filters/Brighten-test.js"></script>
|
||||
<script src="unit/filters/RGB-test.js"></script>
|
||||
<script src="unit/filters/HSV-test.js"></script>
|
||||
<script src="unit/filters/HSL-test.js"></script>
|
||||
<script src="unit/filters/Invert-test.js"></script>
|
||||
<script src="unit/filters/Mask-test.js"></script>
|
||||
<script src="unit/filters/Grayscale-test.js"></script>
|
||||
|
135
test/unit/filters/HSL-test.js
Normal file
135
test/unit/filters/HSL-test.js
Normal file
@@ -0,0 +1,135 @@
|
||||
suite('HSL', function() {
|
||||
|
||||
|
||||
// ======================================================
|
||||
test('hue shift tween transparancy', function(done) {
|
||||
var stage = addStage();
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSL]);
|
||||
darth.hue(360);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
hue: 0,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
tween.play();
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
tween.reverse();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('HSL luminance tween transparancy', function(done) {
|
||||
var stage = addStage();
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSL]);
|
||||
darth.luminance(1.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
luminance: -1.0,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
tween.play();
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
tween.reverse();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('HSL saturation tween transparancy', function(done) {
|
||||
var stage = addStage();
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSL]);
|
||||
darth.saturation(1.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
saturation: -1.0,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
tween.play();
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
tween.reverse();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
});
|
||||
});
|
@@ -66,13 +66,13 @@ suite('HSV', function() {
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSV]);
|
||||
|
||||
darth.saturation(2);
|
||||
darth.saturation(1.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
saturation: 0,
|
||||
saturation: -1.0,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
@@ -110,13 +110,13 @@ suite('HSV', function() {
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSV]);
|
||||
darth.saturation(2.0);
|
||||
darth.saturation(1.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
saturation: 0.001,
|
||||
saturation: -1,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
@@ -154,13 +154,13 @@ suite('HSV', function() {
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSV]);
|
||||
darth.value(2.0);
|
||||
darth.value(1.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
value: 0.001,
|
||||
value: -1.0,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
@@ -178,91 +178,4 @@ suite('HSV', function() {
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('HSL luminance tween transparancy', function(done) {
|
||||
var stage = addStage();
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSL]);
|
||||
darth.luminance(2.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
luminance: 0.001,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
tween.play();
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
tween.reverse();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('HSL saturation tween transparancy', function(done) {
|
||||
var stage = addStage();
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
darth.cache();
|
||||
darth.filters([Kinetic.Filters.HSL]);
|
||||
darth.saturation(2.0);
|
||||
layer.draw();
|
||||
|
||||
var tween = new Kinetic.Tween({
|
||||
node: darth,
|
||||
duration: 1.0,
|
||||
saturation: 0.001,
|
||||
easing: Kinetic.Easings.EaseInOut
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
tween.play();
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
tween.reverse();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user