Make WordPress images work like Drupal images: resize on the fly

11th April 2016 8:27 pm

A WordPress site I’m working on is going to have a ton of images being uploaded into it, and unfortunately that means that a bunch of resized images – many of which will never get used – will also be created.

This takes up disk space, and differs from the way Drupal does it: where each image is resized on the fly, only if and when required, with the resized version being saved for future use so it doesn’t have to be done again.

There’s a plugin that adds this functionality – in part – to WordPress: Fly Dynamic Image Resizer.

The plugin allows you to define your own custom image sizes “on the fly” as you code, preventing every image from automatically being resized to your custom size – unless you actually use it.

However I thought I’d take the concept of this plugin a bit further and see if I could get it to automatically take over all of WordPress’ image resizing – the built in image sizes, as well as any custom image sizes that other plugins and/or themes also create.

Here’s what I came up with. This works for me, but I haven’t fully tested it in all scenarios, so as usual, use at your own risk šŸ™‚ And of course, you’ll need to install Fly Dynamic Image Resizer first!

All code is to be placed in your theme’s functions.php file.

Step 1:

Copy the get_image_sizes() and get_image_size() functions fromĀ this codex pageĀ into your functions.php. These are some helper functions that we’ll use to get the dimensions from built-in image sizes.

Step 2:

We need to prevent WordPress from resizing images when new images are uploaded. To do this, we override the sizes that are used on image uploads, and return… nothing:

add_filter("intermediate_image_sizes_advanced", function($sizes){ return array(); });

Step 3:

This is the main bulk of the code. At this point we’re going to hook intoĀ wp_get_attachment_image_src, which WordPress will be running each time it grabs an image, and we’ll return the result of Fly’s resizing:

add_filter("wp_get_attachment_image_src", "my_fly_wp_integration", 10, 3);

if(!function_exists("my_fly_wp_integration")){
  function my_fly_wp_integration($image, $attachment_id, $size){

    if($size != "full" && $size != "original"){

      // we only do this if the image isn't already at full size

      if(!is_array($size)){

        // we've likely been given a string, which is probably an image size name
        // so, we need to get the dimensions that are set for this image size

          $_size = get_image_size($size);

      }else{

        // we've been given an array, which should contain a width, height, and optionally, a crop setting
        // we need to put it into the format Fly will expect from us

        $_size = array(
          "width" => $size[0],
          "height" => $size[1],
          "crop" => isset($size[2]) ? $size[2] : false,
        );

      }

      // resize the image!

        $fly_image = fly_get_attachment_image_src($attachment_id, array($_size["width"], $_size["height"]), $_size["crop"]);

      // put the image array back into the format WordPress expects

      $image = array(
        $fly_image["src"],
        $fly_image["width"],
        $fly_image["height"],
        true, // is_intermediate is set to true, as we're returning a resized image
      );

    }

    return $image;

  }
}

We’re almost done – just oneĀ more quick step to coverĀ an extra scenario that the filter above doesn’t already.

Step 4:

In addition to the previous steps, we need to also catch the URLs that WordPress returns to the media library via AJAX. Add the following to your functions.php:

add_filter("wp_prepare_attachment_for_js", "my_prepare_attachments");

if(!function_exists("my_prepare_attachments")){
  function my_prepare_attachments($response){

    foreach($response["sizes"] as $size_key => $size_data){

      // loop through each size that each image attempts to return, and resize it through fly

      if($size_key == "medium" || $size_key == "thumbnail"){ // should catch most needed sizes and not take too long

        $fly_image = fly_get_attachment_image_src($response["id"], array($size_data["width"], $size_data["height"]));
        $size_data["url"] = $fly_image["src"];
        $response["sizes"][$size_key] = $size_data;

      }
    }

    return $response;

  }
}

Let me know how this goes for you – particularly if you run into any issues! Don’t forget to test it well – I haven’t tested this in all situations and other issues may well crop up.

This post is also available at the WordPress.org plugin support forums.