Custom image sizes without add_image_size()

Docs, docBlocks and Codex …

Basically you have a very simple mistake: The $attributes array is the 2nd argument:

function the_post_thumbnail( $size="post-thumbnail", $attr="" ) {
    echo get_the_post_thumbnail( null, $size, $attr );
}

How it works internally

1)

The HTML itself gets built by wp_get_attachment_image().

2)

Later on, inside this function, the next relevant function call is

$image = wp_get_attachment_image_src( $attachment_id, $size, $icon );

3)

In there, image_downsize() gets called and this is the first point where you can jump in and short circuit the whole system and simply return a custom sized image:

if ( $out = apply_filters( 'image_downsize', false, $id, $size ) ) {
    return $out;
}

4)

If that does not happen, you can look further and the next function call is

// $size: One of the registered image sizes: medium, large, full, custom, etc.
$intermediate = image_get_intermediate_size( $id, $size )

// Or: Use 'thumbnail' and retrieve the size in a different way:
$thumb_file = wp_get_attachment_thumb_file( $id ) )
getimagesize( $thumb_file )

As long as anywhere in there, the image URl can be obtained by core, it will call image_constrain_size_for_editor() and this function is able to do two different things:

  • Return the width, depending on the User Settings via get_option( "{$size}_size_w" )
  • Return a custom size (this will be checked first)

Before the function returns, it runs everything through a filter:

list( $max_width, $max_height ) = apply_filters(
    'editor_max_image_size', 
    array( $max_width, $max_height ),
    $size,
    $context
);

which is the next chance to intercept the call. $context will be either display (for a theme) or edit for a call in the admin UI.

5)

Then the return value will be run through wp_constrain_dimensions() to calculate the final size.

If all that worked, you will get back into wp_get_attachment_image_src() and immediately return the value from image_downsize() there.

6) Finally…

…you can use wp_get_attachment_image() (the proper way) and intercept the call for width/height in a lot of stages, call underlying functions.

Plugin for the rescue

As it’s a pain to go trough all that again and again, I have written the

Dynamic Image Resize Plugin

which is freely available on GitHub and can be bundled with Themes or Plugins. It can be called directly with a filter in templates or can be used with a shortcode.