Created
April 21, 2010 00:08
-
-
Save paulirish/373253 to your computer and use it in GitHub Desktop.
jquery invert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// jquery invert plugin | |
// by paul irish | |
// some (bad) code from this css color inverter | |
// http://plugins.jquery.com/project/invert-color | |
// some better code via Opera to inverse images via canvas | |
// http://dev.opera.com/articles/view/html-5-canvas-the-basics/#insertingimages | |
// and some imagesLoaded stuff from me | |
// http://gist.github.com/268257 | |
// the code is still pretty shit. | |
// needs better hex -> rgb conversion.. | |
// it could use color caching and image caching and also some perf-y skip elements type stuff. | |
(function ($) { | |
$.fn.invert = function () { | |
$(this).find('*').andSelf().each(function () { | |
var t = $(this); | |
change_part('color', t); | |
change_part('backgroundColor', t); | |
$.each(['right', 'bottom', 'left', 'top'], function (i, val) { | |
change_part('border-' + val + '-color', t); | |
}); | |
changeImage(t); | |
}); | |
return this; | |
}; | |
function change_part(prop, t) { | |
var c = to_rgb(t.css(prop)); | |
if (c != 'transparent' && c.substring(0, 4) != 'rgba') { | |
var rgb = /rgb\((.+),(.+),(.+)\)/.exec(c); | |
t.css(prop, 'rgb(' + (255 - rgb[1]) + ',' + (255 - rgb[2]) + ',' + (255 - rgb[3]) + ')'); | |
} | |
} | |
function to_rgb(c) { | |
if (c.substring(0, 3) == 'rgb' || c == 'transparent') return c; | |
if (c.substring(0, 1) == '#') { | |
if (c.length == 4) { | |
c = '#' + c.substring(1, 2) + c.substring(1, 2) + c.substring(2, 3) + c.substring(2, 3) + c.substring(3, 4) + c.substring(3, 4) | |
} | |
return 'rgb(' + parseInt(c.substring(1, 3), 16) + ',' + parseInt(c.substring(3, 5), 16) + ',' + parseInt(c.substring(5, 7), 16) + ')'; | |
} | |
var name = ['black', 'white', 'red', 'yellow', 'gray', 'blue', 'green', 'lime', 'fuchsia', 'aqua', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'], | |
replace = ['(0, 0, 0)', '(255, 255, 255)', '(255, 0, 0)', '(255, 255, 0)', '(128, 128, 128)', '(0, 0, 255)', '(0,128,0)', '(0, 255, 0)', '(255, 0, 255)', '(0, 255, 255)', '(128, 0, 0)', '(0, 0, 128)', '(128, 128, 0)', '(128, 0, 128)', '(192, 192, 192)', '(0, 128, 128)']; | |
c = replace[$.inArray(c, name)] || c; | |
return 'rgb' + c; | |
} | |
function changeImage(t) { | |
// only operate on img tags and backgroundImages in dataurl or url form. | |
if (!(t.is('img') || /^(data|url)/.test(t.css('backgroundImage')))) return; | |
var img = new Image(); | |
$(img).bind('load', function () { | |
var elem = document.createElement('canvas'); | |
elem.width = img.width; | |
elem.height = img.height; | |
var context = elem.getContext('2d'), | |
x = 0, | |
y = 0, | |
result; | |
try { | |
// Draw the image on canvas. | |
context.drawImage(img, x, y); | |
// Get the pixels. | |
var imgd = context.getImageData(x, y, img.width, img.height); | |
var pix = imgd.data; | |
// Loop over each pixel and invert the color. | |
for (var i = 0, n = pix.length; i < n; i += 4) { | |
pix[i] = 255 - pix[i]; // red | |
pix[i + 1] = 255 - pix[i + 1]; // green | |
pix[i + 2] = 255 - pix[i + 2]; // blue | |
// i+3 is alpha (the fourth element) | |
} | |
// Draw the ImageData object. | |
context.putImageData(imgd, x, y); | |
result = elem.toDataURL(); | |
} | |
catch (e) { | |
// image is on a different domain. | |
} | |
if (t.is('img')) t.attr('src', result) | |
else t.css('backgroundImage', 'url(' + result + ')'); | |
}).each(function () { | |
// cached images don't fire load sometimes, so we reset src. | |
if (this.complete || this.complete === undefined) { | |
var src = this.src; | |
this.src = '#'; | |
this.src = src; | |
} | |
}); | |
var match = t.css('backgroundImage').match(/url\((.*?)\)/), | |
bg = match && match[1]; | |
// img src, url bg, datauri background. | |
img.src = t[0].src || bg || t.css('backgroundImage'); | |
} | |
})(jQuery); |
Thanks you, i was looking for a solution to invert Soundcloud waveform images
Here a playable demo optimised for images
http://jsfiddle.net/molokoloco/WCL5w/ :)
I had success with this in IE7/8
body {
filter: progid:DXImageTransform.Microsoft.BasicImage(invert=1);
zoom: 1;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Someone asked me if this is the best way to invert a page... Here's how i think the lay of the land is today...
In newer webkit browsers you have CSS filters so you can do:
In oldIE you can hypothetically use the DXImageTransform.Microsoft.Invert() filter.. Though my quick attempt to get that going fails, but I'm sure there's a way..
Lea's invert approach is slick and probably better than my css/canvas iteration...
So that'd leave a robust and fast invert function as:
-webkit-filter: invert(1);
And hopefully as more browsers add support for CSS filters, they can shift to that approach.