Skip to content

Instantly share code, notes, and snippets.

@olivierlesnicki
Created August 9, 2012 09:39
Show Gist options
  • Save olivierlesnicki/8dbdedc2f2b88f07e1c8 to your computer and use it in GitHub Desktop.
Save olivierlesnicki/8dbdedc2f2b88f07e1c8 to your computer and use it in GitHub Desktop.
Photoshop-like Contrast, Brightness and Levels for Filtrr2.js
var rgba2hsla = function(rgba) {
var r = rgba.r/255,
g = rgba.g/255,
b = rgba.b/255,
max = Math.max(r,g,b),
min = Math.min(r,g,b),
h, s, l = (max + min)/2;
if(max==min){
h = s = 0;
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {h:h,s:s,l:l,a:rgba.a};
};
var hsla2rgba = function(hsla) {
var h = hsla.h,
s = hsla.s,
l = hsla.l,
r, g, b;
if(s == 0){
r = g = b = l;
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return {r:r * 255, g:g * 255, b: b * 255, a: hsla.a};
};
// #### hue
Filtrr2.fx("hsl", function(h, s, l) {
h = Filtrr2.Util.clamp(h, -100, 100);
s = Filtrr2.Util.clamp(s, -100, 100);
l = Filtrr2.Util.clamp(l, -100, 100);
this.process(function(rgba) {
hsla = rgba2hsla(rgba);
hsla.h += h/100 * hsla.h;
hsla.s += s/100 * hsla.s;
hsla.l += l/100 * hsla.l;
newRgba = hsla2rgba(hsla);
rgba.r = newRgba.r;
rgba.b = newRgba.b;
rgba.g = newRgba.g;
});
});
// #### Contrast [-50, 100]
Filtrr2.fx("contrast", function(p) {
var p = Filtrr2.Util.normalize(p, -20, 40, -50, 100),
c1 = {x: 128 + p,y: 128 - p},
c2 = {x: 128 - p,y: 128 + p};
this.curves(
{x: 0, y: 0},
c1,
c2,
{x: 255, y: 255}
);
});
// #### Brightness [-150, 150]
Filtrr2.fx("brightness", function(p) {
var p = Filtrr2.Util.normalize(p, -70, 70, -150, 150),
c1 = {x: 185 - p, y: 185 + p},
c2 = {x: 185 - p, y: 185 + p };
this.curves(
{x: 0, y: 0},
c1,
c2,
{x: 255, y: 255}
);
});
// #### Levels
// channel [{rgb,r,g,b}]
// input black [0,255]
// input white [0,255]
// gamma [0.01, 9.99]
// output black [0,255]
// output white [0,255]
Filtrr2.fx("levels", function(channel, ib, iw, gm, ob, ow) {
var r = 0,
g = 0,
b = 0;
switch(channel){
case "rgb" : r=1; g=1; b=1; break;
case "r" : r=1; break;
case "g" : g=1; break;
case "b" : b=1; break;
}
ib = Filtrr2.Util.clamp(ib, 0, 255);
iw = Filtrr2.Util.clamp(iw, 0, 255);
gm = typeof gm !== 'undefined' ? Filtrr2.Util.clamp(gm, 0.01, 9.99) : 1;
ob = typeof ob !== 'undefined' ? Filtrr2.Util.clamp(ob, 0, 255) : 0;
ow = typeof ow !== 'undefined' ? Filtrr2.Util.clamp(ow, 0, 255) : 255;
this.process(function(rgba) {
if(r){rgba.r = Filtrr2.Util.normalize(255 * Math.pow(Filtrr2.Util.normalize(rgba.r, 0, 255, ib, iw)/255, 1/gm), ob, ow, 0, 255);}
if(g){rgba.g = Filtrr2.Util.normalize(255 * Math.pow(Filtrr2.Util.normalize(rgba.g, 0, 255, ib, iw)/255, 1/gm), ob, ow, 0, 255);}
if(b){rgba.b = Filtrr2.Util.normalize(255 * Math.pow(Filtrr2.Util.normalize(rgba.b, 0, 255, ib, iw)/255, 1/gm), ob, ow, 0, 255);}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment