How to add multiple image sizes of the same size with add_image_size

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.

Solutions Collecting From Web of "How to add multiple image sizes of the same size with add_image_size"

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;
}