Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm using a grayscale filter on all uploaded images in my WordPress installation. However I want both the gray scaled image and the colored image in my website (colored on hover). The way I tried to do this was to create a bunch of add_image_size()'s like so:

add_image_size( 'gho-small', 100, 0, true ); // Used for small images
add_image_size( 'gho-small-grayscale', 100, 0, true ); // Used for small grayscaled images
add_image_size( 'gho-medium', 200, 0, true ); // Used for medium images
add_image_size( 'gho-medium-grayscale', 200, 0, true ); // Used for medium grayscaled images
add_image_size( 'gho-large', 400, 0, true ); // Used for large images
add_image_size( 'gho-large-grayscale', 400, 0, true ); // Used for large grayscaled images

And then I'd do a filter on the images and only take the *-grayscale ID's and save them:

add_filter('wp_generate_attachment_metadata','gholumns_grayscale_filter');
function gholumns_grayscale_filter($meta)
{
    $dir = wp_upload_dir();
    $file = trailingslashit($dir['path']).$meta['sizes']['gho-large-grayscale']['file'];
    do_grayscale_filter($file);
    return $meta;
}

It would work fine, but apparently add_image_size() looks at the width and height arguments and when a size is already defined with that combination, the size is not added. I can understand that, since the function is to add new sizes, and if the size is a duplicate it normally is better not to add it again to save processing time. But now I want two images with the same size, but one with a filter applied to it and the other the original.

How can I achieve this?

I have tried to add another size which is just one pixel wider, like:

add_image_size( 'gho-small-grayscale', 101, 0, true ); // Used for small grayscaled images

And then resizing the image later on after the filter back to 100/200/400 whatever. But it does not feel right, and it also mess up get_the_post_thumbnail() calls as that one still thinks the image dimension is 101x$height. It also is not as simple as resizing the image back by one pixel horizontally and vertically as ratios could cause that the height is > 1px taller when you have a width + 1px.

share|improve this question
    
Coen, you should post your solution as an Answer. Check the FAQ and you'll see that is ok to answer your own questions. –  brasofilo May 28 '12 at 17:28
1  
@brasofilo yes I know but at the time I didn't have enough reputation to answer my own question within 24h of posting it. Normally I do that, don't worry. –  Coen May 29 '12 at 18:40
    
Woops... time for me to get back to the FAQ and read that reputation part. Great sample code in your Q&A and thanks for the kind feedback :) –  brasofilo May 29 '12 at 18:49

1 Answer 1

up vote 6 down vote accepted

Gee, I keep solving my own problems all the time. Here's how I solved it in the end. I discovered that add_image_size does not ignore the identical dimensions of the image size, but instead points the file name towards the same file in the uploads dir. Once I knew that, I could just save the grayscale image under a different name, return that name to the $meta array in my hook, and WP takes that as information to store in the database. All get_thumbnail() functions are still working as they should and I can just request the -grayscale ID.

add_filter('wp_generate_attachment_metadata','gholumns_grayscale_filter');
function gholumns_grayscale_filter($meta)
{
$file = $meta['sizes']['gho-large-grayscale']['file'];
$meta['sizes']['gho-large-grayscale']['file'] = do_grayscale_filter($file);
//do_resize($file, -1, -1); # No longer necessary!
$file = $meta['sizes']['gho-medium-grayscale']['file'];
$meta['sizes']['gho-medium-grayscale']['file'] = do_grayscale_filter($file);
//do_resize($file, -1, -1); # No longer necessary!
$file = $meta['sizes']['gho-small-grayscale']['file'];
$meta['sizes']['gho-small-grayscale']['file'] = do_grayscale_filter($file);
//do_resize($file, -1, -1); # No longer necessary!
return $meta;
}


function do_grayscale_filter($file)
{
$dir = wp_upload_dir();
$image = wp_load_image(trailingslashit($dir['path']).$file);
imagefilter($image, IMG_FILTER_GRAYSCALE);
return save_modified_image($image, $file, '-grayscale');
}

function save_modified_image($image, $filename, $suffix)
{
$dir = wp_upload_dir();
$dest = trailingslashit($dir['path']).$filename;

list($orig_w, $orig_h, $orig_type) = @getimagesize($dest);

$filename = str_ireplace(array('.jpg', '.jpeg', '.gif', '.png'), array($suffix.'.jpg', $suffix.'.jpeg', $suffix.'.gif', $suffix.'.png'), $filename);
$dest = trailingslashit($dir['path']).$filename;

switch ($orig_type)
{
    case IMAGETYPE_GIF:
        imagegif( $image, $dest );
        break;
    case IMAGETYPE_PNG:
        imagepng( $image, $dest );
        break;
    case IMAGETYPE_JPEG:
        imagejpeg( $image, $dest );
        break;
}

return $filename;
}
share|improve this answer
    
This is great, and exactly what I wanted to do as well but with a photoshop blend-mode multiply effect instead. I had the code for successfully making a multiply red image from another in regular PHP, but I couldn't figure out how to get it to apply to all of the current image sizes. –  Mike Kormendy Oct 9 at 2:14
    
One thing I noticed was that this doesn't quite work for image regenerators and images not stored in the current month for posts. –  Mike Kormendy Oct 10 at 7:32

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.