5

I want to differentiate the featured image from post images.

The plan is to give the Featured Image multiple sizes, but the images inside / connected to the post only needs the default sizes.

I know I can use intermediate_image_sizes to filter what Custom Post Types get assigned to what image sizes, like so:

/** Don't Make Extra Sizes **/
function post_type_sizes( $image_sizes ){
    $post_type_size_array = array('icon', 'med-thumb', 'large', 'full');
    $post_image_sizes = array('thumbnail', 'medium', 'large', 'full');

    if( isset($_REQUEST['post_id']) && 'cpt_test' === get_post_type($_REQUEST['post_id']) )
        return $post_type_size_array;
    else
        return $post_image_sizes;

    return $image_sizes;
}
add_filter('intermediate_image_sizes', 'post_type_sizes', 999 ); 

But I want to only give the Featured Image multiple custom sizes, and leave any post that gets uploaded into the TinyMCE Default Sizes (thumbnail, medium, large, full).

3
  • 1
    Differentiate in what context? On upload?
    – s_ha_dum
    Feb 21, 2014 at 15:22
  • Yeah, differentiate them on upload, so I can give the featured image multiple custom sizes, but leave the images in the tinyMCE (inside the post) left with the default ('thumbnail', 'medium', 'large', 'full'). I'll never need my custom image sizes applied to anything except that one featured image, so I don't want to create extra image sizes for the images inside the tinyMCE.
    – Howdy_McGee
    Feb 21, 2014 at 15:31
  • So you don't want WordPress to generate the same sizes for images uploaded using the Featured Image meta box as images uploaded using Add Media? Feb 27, 2014 at 5:17

2 Answers 2

4
+300

You could do this by filtering the meta value for _thumbnail_id.

add_filter( 'update_post_metadata', 'generate_featured_image_sizes', 10, 5 );
add_filter( 'add_post_metadata', 'generate_featured_image_sizes', 10, 5 );

function generate_featured_image_sizes( $check, $object_id, $meta_key, $meta_value, $unique_or_prev ) {
    if ( $meta_key == '_thumbnail_id' ) {

        // regenerate previous featured image thumbs if it exists
        if ( false !== ( $prev_thumb_id = get_post_meta( $object_id, '_thumbnail_id', true ) ) ) {
            $prev_new_metadata = wp_generate_attachment_metadata( $prev_thumb_id, get_attached_file( $prev_thumb_id ) );
            if ( ! is_wp_error( $prev_new_metadata ) )
                wp_update_attachment_metadata( $prev_thumb_id, $prev_new_metadata );
        }

                    // remove all normal image sizes before we add our filter
                    cleanup_attachment_images( $meta_value );

        // filter image sizes for featured
        add_filter( 'intermediate_image_sizes', 'featured_image_sizes', 9999 );

        // regenerate thumbnails for featured
        $new_metadata = wp_generate_attachment_metadata( $meta_value, get_attached_file( $meta_value ) );
        if ( ! is_wp_error( $new_metadata ) )
            wp_update_attachment_metadata( $meta_value, $new_metadata );

                    // remove featured sizes from previous featured image
                    if ( isset( $prev_thumb_id ) && $prev_thumb_id )
                        cleanup_attachment_images( $prev_thumb_id );

        // tidy up
        remove_filter( 'intermediate_image_sizes', 'featured_image_sizes', 9999 );
    }

    return $check;
}

function featured_image_sizes( $sizes ) {
    return array( 'large', 'featured', 'slider' );
}

function cleanup_attachment_images( $attachment_id ) {
    $uploadpath = wp_upload_dir();
    $intermediate_sizes = array();
    foreach ( get_intermediate_image_sizes() as $size ) {
        if ( $intermediate = image_get_intermediate_size( $attachment_id, $size ) )
            $intermediate_sizes[] = $intermediate;
    }
    // remove intermediate and backup images if there are any
    foreach ( $intermediate_sizes as $intermediate ) {
        /** This filter is documented in wp-admin/custom-header.php */
        $intermediate_file = apply_filters( 'wp_delete_file', $intermediate[ 'path' ] );
        @ unlink( path_join( $uploadpath[ 'basedir' ], $intermediate_file ) );
    }
}

Recreating the thumbnails is just a case of generating and updating the attachment metadata so by regenerating whenever the featured image is changed you should get the desired effect.

This will work on upload but also when the featured image is changed. In addition it will regenerate thumbs for the old thumbnail so it's like a normal image with the normal sizes again.

The reason for using the add_post_metadata and update_post_metadata hooks is so that we have access to the current value before it gets updated in the database.

NOTE There's no real difference between the add media popup for the featured image or the editor, those links just open the popup in a different state so there's no easy way to tell which state was requested (featured image or editor) when images are being uploaded, hence the approach I've shown above.

UPDATE I added a function that you could call to delete sets of generated thumbnails for an attachment. You'd call this before generating new attachment metadata. You could even filter the image sizes it removes or modify the function so you can pass them as an argument.

7
  • Did you have this working? I changed the featured_image_sizes array to just 'thumbnail' and ran intermediate_image_sizes so that posts only create 'medium' images. This just appends a new image size to featured image. What I'm looking for is to have a completely different set of image sizes for the featured image. Ideally featured image wouldn't have 'thumbnail', 'medium', 'large', 'full' but custom sizes, then images inside the tinyMCE would have those 4 image sizes without the custom featured image sizes. It's complex and i imagine needs some JS to get into the media library.
    – Howdy_McGee
    Feb 27, 2014 at 14:59
  • That being said, if there was a way to delete the extra image sizes, since this appends it then the next step would be just removing the excess image sizes, deleting them from the server. Looking into how to do that now.
    – Howdy_McGee
    Feb 27, 2014 at 15:07
  • Ah those will be generated on upload, setting the postmeta happens after. There must be a cleanup routine somewhere in wp. Are you that stuck for disk space? :) Feb 27, 2014 at 16:04
  • Not necessarily, I just want it to be more organized than it is. If I make a gallery of 100 images I don't want it to take the 5 Custom Sizes that only the featured image will use, then that's 900 images on my server just for that post alone ((5 custom sizes + 4 default sizes) * image ). What if I have more posts with bigger galleries? Just too much so I'm trying to find a way around it.
    – Howdy_McGee
    Feb 27, 2014 at 16:07
  • @Howdy_McGee I updated my answer with a function that will hopefully do what you need. It's based on the method used in the wp_delete_attachment() function. I've not tested it mind so let me know if you get PHP errors. Maybe run it a dev site first :) Feb 27, 2014 at 16:20
2

you can also try this

function post_type_sizes( $image_sizes ){

    $feature_image_sizes = array('thumbnail');

    // checking for feature image uploading or not
    if( isset($_REQUEST['post_id']) && 'post' === get_post_type($_REQUEST['post_id']) && get_post_meta( $_REQUEST['post_id'], 'feature_image_uploading', true ) ){
        update_post_meta( $_POST['post_id'],'feature_image_uploading', false );
        return $feature_image_sizes;
    }

    return $image_sizes;
}
add_filter('intermediate_image_sizes', 'post_type_sizes', 999 ); 

add_action('admin_footer', 'monksinc_notify_feature_image_event', 9999 );
function monksinc_notify_feature_image_event(){

    global $pagenow, $post;

    if( 'post.php' !== $pagenow && 'post' !== get_post_type( $post->ID ) )
        return;

    ?>
    <script>
        (function(){
            jQuery('#set-post-thumbnail').click(function(e){
                e.preventDefault();
                jQuery.post(
                    ajaxurl,
                    { action: 'set_post_thumbnail_notify', post_id: jQuery('#post_ID').val() },
                    function( response ){

                        console.log(response);
                    }
                );
            });
        })();
    </script>
    <?php
}

add_action( 'wp_ajax_set_post_thumbnail_notify', 'set_post_thumbnail_notify_callback' );
function set_post_thumbnail_notify_callback(){

    $result = array( 'status'=> 'fail'  );

    if( isset( $_POST ) && 'set_post_thumbnail_notify' === $_POST['action'] && '' !== $_POST['post_id'] ){
        update_post_meta( $_POST['post_id'],'feature_image_uploading', true );
        $result = array( 'status'=> 'success' );
    }

    echo json_encode($result);
    die();
}
  1. in this script, i'm adding a ajax call to feature image link which notify me that user is uploading a featured image
  2. i'm setting a post meta when user uploading featured image and using this post meta for conditional checking to generate specific sizes for featured image
4
  • @Howdy_McGee post type was set to post in my testing. Feb 27, 2014 at 22:38
  • thanks, that looks like it also works. Will this not work then in the highly unlikely case of Disabled JS?
    – Howdy_McGee
    Feb 27, 2014 at 22:41
  • i think that's rare, try it.it worked for me.let me know if there any error or problem Feb 27, 2014 at 22:43
  • What heppens if you upload multiple images after hitting set featured image? Also bear in mind users can click 'add media' by the editor then in the left hand bar choose to set the featured image so you'd have to register a click handler there too. Feb 28, 2014 at 10:13

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.