How to set the jpg image compression for specific thumbnail sizes?

This question was asked on Set JPEG compression for specific custom image sizes and answered very nicely by Ahmad M

I’d of course comment to that thread but I don’t have 50 point reputation…

The code I’m using is pretty much the same as in Ahmed’s answer, but the problem I’m still facing is if I’m using a specific thumbnail size in my theme.
For example I have a grid of smaller boxes in my frontpage and they have a 260px wide images. If the uploaded image is originally smaller than what the image would get resized to by the function by Ahmed, it of course won’t resize (nor should it) but also it doesn’t compress the image.

Example:

If I upload a 1200×800 image and use it in my front page, it gets resized to to smaller size (520px wide, which is 260px *2 for retina displays) and the quality is compressed. Nice!
But if I upload an image that is already let’s say 500px wide (less than 520px), it won’t get resized but it won’t get compressed either. Very quickly my clients web site has lots of images with big file size and loads slowly.

How should I change this function to always compress the images to whatever quality I want the thumbnails to be, regardless of their original dimensions?

Code:

    //featured-image support
    add_theme_support( 'post-thumbnails' ); 

    add_image_size( 'newsbox-thumb', 520, 9999 ); // masonry news box-images =260px (520 retina) and unlimited height
    add_image_size( 'fprelease-thumb', 112, 9999 ); // fprelese feed logo, 56px (112px retina)


    // https://wordpress.stackexchange.com/questions/74103/set-jpeg-compression-for-specific-custom-image-sizes
    // set the quality to maximum
    add_filter('jpeg_quality', create_function('$quality', 'return 100;'));

    add_action('added_post_meta', 'ad_update_jpeg_quality', 10, 4);

    function ad_update_jpeg_quality($meta_id, $attach_id, $meta_key, $attach_meta) {

    if ($meta_key == '_wp_attachment_metadata') {

        $post = get_post($attach_id);

        if ($post->post_mime_type == 'image/jpeg' && is_array($attach_meta['sizes'])) {

            $pathinfo = pathinfo($attach_meta['file']);
            $uploads = wp_upload_dir();
            $dir = $uploads['basedir'] . "https://wordpress.stackexchange.com/" . $pathinfo['dirname'];

            foreach ($attach_meta['sizes'] as $size => $value) {

                $image = $dir . "https://wordpress.stackexchange.com/" . $value['file'];
                $resource = imagecreatefromjpeg($image);

                if ($size == 'newsbox-thumb') {
                    // set the jpeg quality for 'newsbox-thumb' size
                    imagejpeg($resource, $image, 60);
                } elseif ($size == 'fprelease-thumb') {
                    // set the jpeg quality for the 'fprelease-thumb' size
                    imagejpeg($resource, $image, 85);
                } else {
                    // set the jpeg quality for the rest of sizes
                    imagejpeg($resource, $image, 80);
                }

                // or you can skip a paticular image size
                // and set the quality for the rest:
                // if ($size == 'splash') continue;

                imagedestroy($resource);
            }
        }
    }
}

1 Answer
1

One solution I found was to include the original image in the $sizes array. Like this, after all the conversions to others sizes the uploaded image will also be converted to its same size and some other given quality.

Please note that by doing this you’ll lose the original image, and if you add any other size after the image is first uploaded, then the following conversions will have their quality affected by this.

add_theme_support( 'post-thumbnails' ); 
add_image_size( 'newsbox-thumb', 520, 9999 ); // masonry news box-images =260px (520 retina) and unlimited height
add_image_size( 'fprelease-thumb', 112, 9999 ); // fprelese feed logo, 56px (112px retina)


add_filter( 'jpeg_quality', create_function( '$quality', 'return 100;' ) );
add_action( 'added_post_meta', 'ad_update_jpeg_quality', 10, 4 );

function ad_update_jpeg_quality( $meta_id, $attach_id, $meta_key, $attach_meta ) {

    if ( $meta_key != '_wp_attachment_metadata' )
        return false;

    if ( ! $post = get_post( $attach_id ) )
        return false;

    if ( 'image/jpeg' != $post->post_mime_type )
        return false;

    $original = array(
        'original' => array(
            'file' => $attach_meta['file'],
            'width' => $attach_meta['width'],
            'height' => $attach_meta['height']
        )
    );
    $sizes = !empty( $attach_meta['sizes'] ) && is_array( $attach_meta['sizes'] )
        ? $attach_meta['sizes']
        : array();
    $sizes = array_merge( $sizes, $original );

    $pathinfo = pathinfo( $attach_meta['file'] );
    $uploads = wp_upload_dir();
    $dir = $uploads['basedir'] . "https://wordpress.stackexchange.com/" . $pathinfo['dirname'];

    foreach ( $sizes as $size => $value ) {

        $image="original" == $size
            ? $uploads['basedir'] . "https://wordpress.stackexchange.com/" . $value['file']
            : $dir . "https://wordpress.stackexchange.com/" . $value['file'];
        $resource = imagecreatefromjpeg( $image );

        if ( $size == 'original' )
            $q = 70; // quality for the original image
        elseif ( $size == 'newsbox-thumb' )
            $q = 60;
        elseif ( $size == 'fprelease-thumb' )
            $q = 85;
        else
            $q = 80;

        imagejpeg( $resource, $image, $q );
        imagedestroy( $resource );

    }

}

And if you want to re-run the conversion to change the quality of the images in your client’s websites, you can try the Regenerate Thumbnails plugin.

Leave a Comment