8

I'm worried about too many files created when adding a new image size.

All uploaded files will generate the new size, I need a specific image size only for the file set as Fetured image, is there some way to do this?.

The thumbnail, medium, etc are ok, but there is no need to create the new size for every file.

I think this should work right after setting the Featured Image.

2
  • Out of curiosity, why are you worried? Too much limited resources on server? :.....: Maybe it's impossible, as upload occurs before setting the Featured Image...
    – brasofilo
    Commented Jul 3, 2012 at 23:26
  • Because There will be a lot of images and most of them never will be displayed?! I just thought any filter could do it.
    – Diana
    Commented Jul 3, 2012 at 23:30

3 Answers 3

4

Research

The question Filter For Featured Image lead to this answer: How to hook update_post_meta and delete_post_meta?.

Coupled with the a fine global variable ($_wp_additional_image_sizes) revealed here: How to get a list of all the possible thumbnail sizes set within a theme, bring us to the code that catches the "Use as featured image" action click.

enter image description here


Code

This code is fired at each "Use as featured image" click. It then goes through all Additional Image Sizes and deletes them, keeping the default WordPress ones (thumbnail, medium, large).
Test this code throughly before going LIVE.
GPL Code. No warranty granted. Check the comments.

/**
    DRAWBACK
    - Setting the Featured Image can be done ONLY ONCE
    -- When first setting the FI, all other attachments intermediate sizes will be deleted
    -- If swapping the FI, the first image's remaining intermediate will be deleted, and the second DON'T HAVE any additional intermediates!
    
    TODO: Restoring deleted intermediates
    - this post may have an answer: https://wordpress.stackexchange.com/a/8082/12615
*/

add_action( 'added_post_meta', 'wpse_57369_selective_delete_intermediates', 10, 4 );
add_action( 'updated_post_meta', 'wpse_57369_selective_delete_intermediates', 10, 4 );

/**
 * Catches the "Used as featured image" action
*/
function wpse_57369_selective_delete_intermediates( $meta_id, $post_id, $meta_key, $meta_value )
{
    if ( '_thumbnail_id' == $meta_key )
    {
        global $_wp_additional_image_sizes;

       /**
        * The global holds all additional image sizes and contains this:
        * 
           array(
           ['post-thumbnail'] => array(
               ['width'] => 1000
               ['height'] => 288
               ['crop'] => 1
           )
           ['large-feature'] => array(
               ['width'] => 1000
               ['height'] => 288
               ['crop'] => 1
           )
           ['small-feature'] => array(
               ['width'] => 500
               ['height'] => 300
               ['crop'] =>
           )
        )
       */

        // Populate a new array with single values based on the keys of the global
        $all_sizes = array();
        foreach ( $_wp_additional_image_sizes as $key => $value )
        {
            $all_sizes[] = $key;
        }
                
        // Retrieve all attachments of current post/page/cpt
        $all_attachs = get_children( array(
                'post_parent' => $post_id,
                'post_type' => 'attachment',
                'numberposts' => -1,
                'post_mime_type' => 'image'
            ));
        
        // Determine upload path
        $uploads   = wp_upload_dir();
        $path_pos  = strpos( $uploads['basedir'], 'wp-content/' ); // start position of the string
        $base_path = substr( $uploads['basedir'], 0, $path_pos);  // path before wp-content, e.g., /etc/public_html/

        // Loop through all attachments
        foreach ( $all_attachs as $key => $value )
        {
            // This is the featured image
            if ( $key == $meta_value)
            {
                wpse_57369_delete_files( $key, $all_sizes, $base_path, 'small-feature' );
            }
            // Rest of attached images
            else
            {
                wpse_57369_delete_files( $key, $all_sizes, $base_path, false );
            }
        }
    }
}

/**
 * Delete all custom intermediates files, except when $keep_size is defined
*/
function wpse_57369_delete_files( $ID, $all_sizes, $base_path, $keep_size=false )
{
    foreach ( $all_sizes as $intermediate )
    {
        /* We need to know the image url [0] and if it exists [3] */
        $the_url = wp_get_attachment_image_src( $ID, $intermediate );

        /* If additional image exist, go ahead */
        if( $the_url[3] )
        {
            // Path of the image to be deleted
            $url_pos  = strpos( $the_url[0], 'wp-content/' );
            $url_end  = substr( $the_url[0], $url_pos);

            // Delete all intermediates
            if ( !$keep_size )
            {
                // loga( $ID . ' - ' . $intermediate, 'delete-me');
                unlink( $base_path . $url_end );
            }
            
            // Featured image, Selective delete
            else
            {
                // Delete intermediate
                if ( $intermediate != $keep_size )
                {
                    // loga( $ID . ' - ' . $intermediate, 'delete-me');
                    unlink( $base_path . $url_end );                    
                }
                
                // Keep intermediate, no action needed
                // PROBABLY, RESTORING AN INEXISTENT IMAGE SIZE MUST BE DONE HERE
                else
                {
                    // loga( $ID . ' - ' . $intermediate, 'keep-me');
                }
            } 
        }
    }
}

function loga()
{
    // This is the FireBug FirePHP console call
    // http://www.firephp.org/HQ/Use.html
}

Result

Folder contents after uploading images, no Feature Image set yet
enter image description here

Folder contents after setting fondo-restauraciones as the Featured Image
enter image description here


Other Notes

For dealing with ALL extra image sizes (WordPress defaults and custom defined) use:

$all_sizes = get_intermediate_image_sizes();

/**
 * $all_images contains all intermediate image sizes, WordPress default and declared custom sizes:
 * 
    array(
        [0] => 'thumbnail'
        [1] => 'medium'
        [2] => 'large'
        [3] => 'post-thumbnail'
        [4] => 'large-feature'
        [5] => 'small-feature'
    )
*/
4
  • That seems nice! I will give a try for sure,
    – Diana
    Commented Jul 4, 2012 at 3:00
  • not sure if I'm using this right, when I send two files and set some as featured image, the code keeps the original and thumb only for that file. The other files are there.
    – Diana
    Commented Jul 7, 2012 at 4:51
  • @Diana - Oh, I misread your question... Am updating the answer.
    – brasofilo
    Commented Jul 7, 2012 at 8:29
  • thanks for your help, I just was thinking if your code can be used to delete a image size not longer in use by size in file name?! I will sort out a new question, thanks!
    – Diana
    Commented Jul 9, 2012 at 5:41
4

You can get the featured image src/source by using the following arguments on the core function (where $post, should be called with global $post in front):

wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'single-post-thumbnail' );

How-to use it

I wrote a free plugin available on GitHub, called "Dynamic Image Resize".

You can download & use it for free.

Short Code

Place [dynamic_image] in your content. The shortcode has four arguments:

  • src Full path to the image in your upload directory or the ID
  • width Integer value
  • height Integer value
  • classes Css classes – separated by a space

… but there's also a:

Template Tag

global $post;
// Use the template tag with ID *OR* full path
dynamic_image_resize( array(
     // The full path to the image in your uploads folder
     'src'     => wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'single-post-thumbnail' );
     // OR: the ID
     'src'     => get_post_thumbnail_id( $post->ID )

    ,'width'   => 60
    ,'height'  => 100
    ,'classes' => 'some classes to align and style the image'
) );

Just dump it in your template where you need it and finito.

Note: It's based on an idea/proposal by Konstantin Kovshenin.


Sidenote:

If you want to skip/disable default image sizes by default, just add 0 as width and height in the admin settings.

4
  • 1
    Thanks kaiser, this is very user-friendly, I will give a try.
    – Diana
    Commented Jul 4, 2012 at 3:04
  • This plugin can help in attached images?! I have slider that use things like: $imageArray = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'thumb-listings' );
    – Diana
    Commented Jul 7, 2012 at 5:02
  • I figured ou but it seems not working, I just activated and it shows: Warning: array_map() [function.array-map]: Argument #2 should be an array in ...wp-content\plugins\Image-Resize\dynamic_img_resize.php on line 105
    – Diana
    Commented Jul 7, 2012 at 5:28
  • The failure is on your side - wrong code. It just tells you, that you've to add the argument as array. If you haven't done so, the error message will pop up. I made an update to the plugin, so you will now get an easier to understand error message (but only if you're a) logged in b) allowed to edit posts and c) got WP_DEBUG defined and set to true in your wp-config.php file).
    – kaiser
    Commented Jul 7, 2012 at 11:06
0

There is now also a plugin solution available that can elegantly handle this issue. It's called Fly Dynamic Image Resizer, and dynamically creates the image when it is called for the first time, rather than when it is uploaded.

From the plugin's description:

With this plugin, you can create as many image sizes as you want without the guilt of unnecessary image sizes taking up your disk space!

The way it works is like this:

  • You set your image sizes;
  • You upload an image, there are no extra sizes generated;
  • A visitor calls a particular image-size for the first time, and now that size gets generated and stored;
  • A subsequent visitor gets the stored version of the image.

The plugin looks well supported at the time of writing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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