1

The title pretty much says it all. I went through a number of jQuery plugins in order to turn an image black and white. But none of them provide the function that I have in mind. I would like the image to turn back into a coloured one when a specified element is hovered.

Here's the plugin I currently use:

(function ($) {
$.fn.extend({
    BlackAndWhite: function (options) {
        'use strict';
        var container = this,
            self = this,
            defaults = {
                hoverEffect: true,
                webworkerPath: false,
                responsive: true,
                invertHoverEffect: false,
                speed: 500
            };
            options = $.extend(defaults, options);
        //@public vars
        var hoverEffect = options.hoverEffect,
            webworkerPath = options.webworkerPath,
            invertHoverEffect = options.invertHoverEffect,
            responsive = options.responsive,
            fadeSpeedIn = $.isPlainObject(options.speed) ? options.speed.fadeIn : options.speed,
            fadeSpeedOut = $.isPlainObject(options.speed) ? options.speed.fadeOut : options.speed;
        //@private var
        var supportsCanvas = !!document.createElement('canvas').getContext,
            $window = $(window);
        /* Check if Web Workers are supported */
        var supportWebworker = (function () {
                return (typeof (Worker) !== "undefined") ? true : false;
            }());

        var isIE7 = $.browser.msie && +$.browser.version === 7;
        //@private methods
        //convert any image into B&W using HTML5 canvas
        var greyImages = function (img, canvas, width, height) {
            var ctx = canvas.getContext('2d'),
                currImg = img,
                i = 0,
                grey;

            ctx.drawImage(img, 0, 0, width, height);

            var imageData = ctx.getImageData(0, 0, width, height),
                px = imageData.data,
                length = px.length;

            // web worker superfast implementation
            if (supportWebworker && webworkerPath) {

                var BnWWorker = new Worker(webworkerPath + "BnWWorker.js");

                BnWWorker.postMessage(imageData);

                BnWWorker.onmessage = function (event) {
                    ctx.putImageData(event.data, 0, 0);
                };
            } else {

                // no webworker slow implementation
                for (; i < length; i += 4) {
                    grey = px[i] * 0.3 + px[i + 1] * 0.59 + px[i + 2] * 0.11;
                    px[i] = px[i + 1] = px[i + 2] = grey;
                }

                ctx.putImageData(imageData, 0, 0);
            }
        };

        var injectTags = function (pic, currImageWrapper) {

            var src = pic.src;

            if (supportsCanvas && (!($.browser.msie && $.browser.version == '9.0'))) {

                var currWidth = $(currImageWrapper).find('img').width(),
                    currHeight = $(currImageWrapper).find('img').height(),
                    realWidth = pic.width,
                    realHeight = pic.height;

                //adding the canvas
                $('<canvas width="' + realWidth + '" height="' + realHeight + '"></canvas>').prependTo(currImageWrapper);
                //getting the canvas
                var currCanvas = $(currImageWrapper).find('canvas');
                //setting the canvas position on the Pics
                $(currCanvas).css({
                    'position': 'absolute',
                    top: 0,
                    left: 0,
                    width: currWidth,
                    height: currHeight,
                    display: invertHoverEffect ? 'none' : 'block'
                });

                greyImages(pic, currCanvas[0], realWidth, realHeight);

                if (hoverEffect) {
                    $(currImageWrapper).mouseenter(function () {
                        if(!invertHoverEffect) {
                            $(this).find('canvas').stop(true, true).fadeOut(fadeSpeedOut);
                        } else {
                            $(this).find('canvas').stop(true, true).fadeIn(fadeSpeedIn);
                        }
                    });
                    $(currImageWrapper).mouseleave(function () {
                        if(!invertHoverEffect) {
                            $(this).find('canvas').stop(true, true).fadeIn(fadeSpeedIn);
                        } else {
                            $(this).find('canvas').stop(true, true).fadeOut(fadeSpeedOut);
                        }
                    });
                }
            } else {

                var ieWidth = $(currImageWrapper).find('img').prop('width');
                var ieHeight = $(currImageWrapper).find('img').prop('height');

                //adding the canvas
                $('<img src=' + src + ' width="' + ieWidth + '" height="' + ieHeight + '" class="ieFix" /> ').prependTo(currImageWrapper);
                $('.ieFix').css({
                    'position': 'absolute',
                    top: 0,
                    left: 0,
                    'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)',
                    display: invertHoverEffect ? 'none' : 'block'
                });

                if (hoverEffect) {
                    $(currImageWrapper).mouseenter(function () {
                        if(!invertHoverEffect) {
                            $(this).children('.ieFix').stop(true, true).fadeOut(fadeSpeedOut);
                        } else {
                            $(this).children('.ieFix').stop(true, true).fadeIn(fadeSpeedIn);
                        }
                    });
                    $(currImageWrapper).mouseleave(function () {
                        if(!invertHoverEffect) {
                            $(this).children('.ieFix').stop(true, true).fadeIn(fadeSpeedIn);
                        } else {
                            $(this).children('.ieFix').stop(true, true).fadeOut(fadeSpeedOut);
                        }
                    });
                }
            }
        };
        this.init = function (options) {

            $(container).each(function (index, currImageWrapper) {
                var pic = new Image();
                pic.src = $(currImageWrapper).find('img').prop("src");

                if (!pic.width) {
                    $(pic).on("load", function() {injectTags( pic, currImageWrapper);});
                } else {
                    injectTags( pic, currImageWrapper );
                }
            });


            if (responsive) {
                $window.on('resize orientationchange', container.resizeImages);
            }
        };

        this.resizeImages = function () {

            $(container).each(function (index, currImageWrapper) {
                var pic = $(currImageWrapper).find('img:not(.ieFix)');
                var currWidth,currHeight;
                if (isIE7) {
                    currWidth = $(pic).prop('width');
                    currHeight = $(pic).prop('height');
                } else {
                    currWidth = $(pic).width();
                    currHeight = $(pic).height();
                }

                $(this).find('.ieFix, canvas').css({
                    width: currWidth,
                    height: currHeight
                });

            });
        };

        return self.init(options);

    }

});
}(jQuery));
Ilya Karnaukhov
  • 3,838
  • 7
  • 31
  • 53
  • I'd say the cross-browser simple way to go is just using two images. – adeneo Oct 26 '12 at 23:14
  • possible duplicate of [Convert an image to grayscale in HTML/CSS](http://stackoverflow.com/questions/609273/convert-an-image-to-grayscale-in-html-css) – Neil Oct 27 '12 at 00:00
  • lol. not a duplicate. look at the author name :p – Ilya Karnaukhov Oct 27 '12 at 10:53
  • What does the author name have to do with it? Just because it was someone else who wanted an image to be grey scale unless it was hovered, doesn't mean it's not a duplicate. – Neil Oct 27 '12 at 23:38
  • Nevertheless. I'm trying to find a good jQuery plugin and not the css trick. – Ilya Karnaukhov Oct 28 '12 at 13:05

3 Answers3

2

I think you can do this by using CSS3 too . For making any image(lets say it has class "Image") to black and white , you can go with this :-

img.Image{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
filter: grayscale(100%);
}

and for turning it back into colored one on hover you can do this :-

img.Image:hover{
-webkit-filter: grayscale(0%);
-moz-filter: grayscale(0%);
filter: grayscale(0%);
}
Tushar Raj
  • 761
  • 6
  • 20
1

By Jquery ,the same thing can be achieved by doing this :-

for making an image to turn black and white , do this :-

if you want this on document ready ,then

$('document').ready(function(){
 $("img.Image").css({'-webkit-filter':'grayscale(100%)','-moz- filter':'grayscale(100%)','filter': 'grayscale(100%)'});    
});

After then what you require I think is this :-

$("img.Image").on('hover',function(){
$(this).css({'-webkit-filter':'grayscale(0%)','-moz-filter':'grayscale(0%)','filter':'grayscale(0%)'});
},function(){
$(this).css({'-webkit-filter':'grayscale(100%)','-moz-filter':'grayscale(100%)','filter': 'grayscale(100%)'});
}
);
Tushar Raj
  • 761
  • 6
  • 20
0

Convert an image to grayscale in HTML/CSS suggests greyscaling an image in Firefox by averaging its red, green and blue components. However this does not result in an image with the same luminance. You would get a better result by using the desaturating filter:

<svg xmlns="http://www.w3.org/2000/svg">
  <filter id="gray">
    <feColorMatrix type="saturate" values="0"/>
  </filter>
</svg>

Use filter: url(grayscale.svg#grayscale); in your CSS. (If your document is very simple then you can actually put the HTML, CSS and SVG in the same document.)

Community
  • 1
  • 1
Neil
  • 54,642
  • 8
  • 60
  • 72