Desaturate image and color on hover?

In WordPress how would be the best way to dynamically generate a sprite of the featured image where it had the desaturated and colored version?

JeffreyWay said

Mike -

Your other options are:

  • Use sprites
  • Dynamically create a sprite with your server-side language of choice
  • Use a JavaScript file, like excanvas, to bring canvas support to IE.

excanvas doesn’t seem to be working for me http://miketorosian.com/test/ in IE.

Yep, just 1 image for us. Is this what you are after (hover over the 3 buttons)

http://tf.dtbaker.com.au/wordpress/sport_grunge/?tempcolor=green

Not sure on IE support, welcome to test.

dtbaker said

Yep, just 1 image for us. Is this what you are after (hover over the 3 buttons)

http://tf.dtbaker.com.au/wordpress/sport_grunge/?tempcolor=green

Not sure on IE support, welcome to test.

For me it works in Firefox 4.01, and IE 8 but not Chrome 12.0.742.100 or Safari 5.0.5 all on a PC. However, I can’t see how you are accomplishing it, I don’t see the code that is actually doing the switch.

Bugger about Safari. Works here in chrome, odd.

setup your image


then run some JS to convert all “greyscale” classed images:

jQuery(function(){
   jQuery('.greyscale').each(function(){
        with({i:this}){
            setTimeout(function(){
                if(jQuery.browser.msie){
                    grayscaleImageIE(i);
                } else {
                    i.src = grayscaleImage(i);
                }
            },1000);
        }
    });
});


function grayscaleImageIE(imgObj) {
    imgObj.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)';
}

function grayscaleImage(imgObj) {
    var canvas = document.createElement('canvas');
    var canvasContext = canvas.getContext('2d');
    var imgW = imgObj.width;
    var imgH = imgObj.height;
    canvas.width = imgW;
    canvas.height = imgH;
    canvasContext.drawImage(imgObj, 0, 0);
    var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);
    for(var y = 0; y < imgPixels.height; y++){
        for(var x = 0; x < imgPixels.width; x++){
            var i = (y * 4) * imgPixels.width + x * 4;
            var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
            imgPixels.data[i] = avg;
            imgPixels.data[i + 1] = avg;
            imgPixels.data[i + 2] = avg;
        }
    }
    canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
    return canvas.toDataURL();
}

if that part works to satisfaction you can play with jQuery to duplicate the image, desaturate one copy, then fade between images on hover.

the other option would be to find some php code to create an image sprite on upload, ie: original image at the top, then a greyscale version of the image appended underneath.

The site is going to be powered by WordPress it looks like the sprite method is the safest for multiple browsers but I am uncertain as to how to handle sprite creation on images that are uploaded as featured images in WordPress.

Using php:

<?php
$image_path = 'mytest.png';
$input_image = imagecreatefrompng($image_path);
$image_info = getimagesize($image_path);
$output_image = imagecreatetruecolor($image_info[0], $image_info[1] * 2);
imagecopy ($output_image, $input_image, 0, 0, 0, 0, $image_info[0], $image_info[1]);
if(imagefilter($input_image, IMG_FILTER_GRAYSCALE)) {
    echo 'Image converted.';
    imagecopy ($output_image, $input_image, 0, $image_info[1], 0, 0, $image_info[0], $image_info[1]);
    imagepng($output_image, 'mytest.png');
} else {
    echo 'Conversion failed.';
}
imagedestroy($input_image);
imagedestroy($output_image);
?>


SportTipsWorld said

Using php:

<?php
$image_path = 'mytest.png';
$input_image = imagecreatefrompng($image_path);
$image_info = getimagesize($image_path);
$output_image = imagecreatetruecolor($image_info[0], $image_info[1] * 2);
imagecopy ($output_image, $input_image, 0, 0, 0, 0, $image_info[0], $image_info[1]);
if(imagefilter($input_image, IMG_FILTER_GRAYSCALE)) {
    echo 'Image converted.';
    imagecopy ($output_image, $input_image, 0, $image_info[1], 0, 0, $image_info[0], $image_info[1]);
    imagepng($output_image, 'mytest.png');
} else {
    echo 'Conversion failed.';
}
imagedestroy($input_image);
imagedestroy($output_image);
?>


I am a bit confused on how this would work with WordPress if a client were uploading a colored photo via the featured image option, how would you be able to make this all work together?

In your theme, link to a PHP script to output the image, instead of linking to the image directly.

eg: http://tf.dtbaker.com.au/wordpress/sport_grunge/wp-content/themes/kids_toys/dtbaker_grayscale.php?uri=uploads/2011/01/photo4_lg-130x130.jpg



if (!isset($_SERVER['REQUEST_URI'])){
	$_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],1);
	if (isset($_SERVER['QUERY_STRING'])){
		$_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING'];
	}
}
$this_folder = preg_replace('#/+#','/',preg_replace('#\\+#','/',preg_replace('#'.preg_quote('dtbaker_grayscale.php','#').'#','',dirname(preg_replace('/\?.*$/','',$_SERVER['REQUEST_URI'])).'/dtbaker_grayscale.php')));
// remove host
$uri = $_REQUEST['uri'];
if(preg_match('#^(\w+)://#',$uri)){
	$parts = parse_url($uri);
	if(isset($parts['path']) && $parts['path']){
		$uri = $parts['path'];
	}
}
$requested_file = trim(utf8_decode(iconv("UTF-8","UTF-8//IGNORE",$uri)));
if(!$requested_file || !$this_folder){
	die("Unable to launch");
}
$image_path = '';
// bump up a dir, if needed.
if($requested_file[0] == '/'){
	foreach(explode('/',trim($this_folder,'/')) as $slug){
		$image_path .= '../';
	}
	$image_path = rtrim($image_path,'/');
}
$image_path .= $requested_file;
$image_path = trim($image_path,'/');
if(is_file('../../'.$image_path)){
    $image_path = '../../'.$image_path;
}
if(is_file($image_path)){

    $image_info = getimagesize($image_path);
    switch($image_info[2]){
        case IMAGETYPE_JPEG:
            $input_image = imagecreatefromjpeg($image_path);
            break;
        case IMAGETYPE_GIF:
            $input_image = imagecreatefromgif($image_path);
            break;
        case IMAGETYPE_PNG:
            $input_image = imagecreatefrompng($image_path);
            break;
        default:
            exit;
    }
    $output_image = imagecreatetruecolor($image_info[0], $image_info[1] * 2);
    imagecopy ($output_image, $input_image, 0, 0, 0, 0, $image_info[0], $image_info[1]);
    if(imagefilter($input_image, IMG_FILTER_GRAYSCALE)) {
        imagecopy ($output_image, $input_image, 0, $image_info[1], 0, 0, $image_info[0], $image_info[1]);
        header('Content-type: image/jpeg');//.$image_info['mime']);
        imagejpeg($output_image);
    }
    imagedestroy($input_image);
    imagedestroy($output_image);
}

Can you please give an example of how you would link to the file to output an image in the code? I’m not quite sure what you mean by that.

In the code I am using the_post_thumbnail so how would I be able to run that through the PHP script first to make this work?