vinnizworld
5/15/2012 - 10:23 AM

jquery invert

jquery invert

// 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);