4

I wonder if there is a way to scale down uploaded media exactly to 50%.

From what I see, with add_image_size you can only specify a width and a height in pixel.

The idea is to upload high resolution images for Retina displays and then let Wordpress generate a custom image size scaled down for standard displays.

The best would be apply this to both the original image as well as all the others custom thumbnail generated.

Thanks for the help.

1
  • It could be a way to do it but I am not sure that's the best way at all. In the media sizes, you actually want to set-up the "HTML" sizes or your elements. I think everything related to the support of Retina should be "hidden" by the system. Plus you would be delivering big images to all your users, and how many of them are using Retina displays? By any chance, did you try the WP Retina 2x? It should help a lot. I spend the last weeks working on it, and I think it resolves those issues nicely now :)
    – TigrouMeow
    Commented Aug 9, 2012 at 1:12

2 Answers 2

3

You can use image_downsize filter and to catch when WordPress wants a downscaled image and not original, and actually a size what doesn't exist.

add_filter( 'image_downsize', 'wpse_60890_retina_scale', 10, 3 );

function wpse_60890_retina_scale( $value, $id, $size ) {
    if ( $size == 'wpse_60890_retina_scaled' ) {
        if ( !is_array( $imagedata = wp_get_attachment_metadata( $id ) ) )
            return false;

        $img_url          = wp_get_attachment_url( $id );
        $img_url_basename = wp_basename( $img_url );

        if ( isset( $imagedata['sizes']['wpse_60890_retina_scaled'] ) ) {
            $intermediate = $imagedata['sizes']['wpse_60890_retina_scaled'];
            $url  = str_replace($img_url_basename, $intermediate['file'], $img_url);

            return array( $url, $data['width'], $data['height'] );
        }

        $file = get_attached_file( $id );
        $image = wp_load_image( $file );

        if ( !is_resource( $image ) )
            return new WP_Error( 'error_loading_image', $image, $file );

        $size = @getimagesize( $file );
        if ( !$size )
            return new WP_Error( 'invalid_image', __('Could not read image size'), $file );

        list( $orig_w, $orig_h, $orig_type ) = $size;

        $max_w = round( $orig_w / 2 );
        $max_h = round( $orig_h / 2 );

        $resized = image_make_intermediate_size( $file, $max_w, $max_h );

        $imagedata['sizes']['wpse_60890_retina_scaled'] = $resized;

        wp_update_attachment_metadata( $id, $imagedata );

        $url = str_replace($img_url_basename, $resized['file'], $img_url);

        return array( $url, $resized['width'], $resized['height'] );
    }

    return $value;
}

Now you have to determine where you need full size or scaled by 50%.

For example you have

   echo 'full size:' . wp_get_attachment_image( $attachment->ID, 'full' );
   echo 'scaled by 50%: ' . wp_get_attachment_image( $attachment->ID, 'wpse_60890_retina_scaled' );
0
3

I could not use @nvartolomei solution the way it was. It was not functional but still a good starting point.

Here is my final solution:

I add 3 new image sizes by doubling the original 3 sizes.

  • large_retina
  • medium_retina
  • thumbnail_retina

Then I put filter when you call them in PHP in order to replace with and height by their non retina equivalent (since it's not always about dividing by 2).

  • original : src=image.jpg width=4800 height=4000
  • large(600x600) : src=image-600x500.jpg width=600 height=500
  • large_retina(600x600) : src=image-1200x1000.jpg width=600 height=500

  • original : src=image.jpg width=900 height=750

  • large(600x600) : src=image-600x500.jpg width=600 height=500
  • large_retina(600x600) : src=image.jpg width=600 height=500

function.php:

add_action( 'init', 'cjg_register_sizes' );
add_filter( 'image_downsize', 'cjg_retina_scale', 10, 3 );

function cjg_register_sizes(){
    add_image_size( 'large_retina', get_option( 'large_size_w' ) * 2 , get_option( 'large_size_h' ) * 2 );
    add_image_size( 'medium_retina', get_option( 'medium_size_w' ) * 2 , get_option( 'medium_size_h' ) * 2 );
    add_image_size( 'thumbnail_retina', get_option( 'thumbnail_size_w' ) * 2 , get_option( 'thumbnail_size_h' ) * 2 );
}

function cjg_retina_scale( $value, $id, $size ) {

    if ( $size == 'large_retina' OR $size == 'medium_retina' OR $size == 'thumbnail_retina' ) {
        if ( !is_array( $imagedata = wp_get_attachment_metadata( $id ) ) )
            return false;

        if ( $size == 'large_retina')       $regular_size = 'large';
        elseif ( $size == 'medium_retina')  $regular_size = 'medium'; 
        else                                $regular_size = 'thumbnail';

        $img_url          = wp_get_attachment_url( $id );
        $img_url_basename = wp_basename( $img_url );

        if ( isset( $imagedata['sizes'][$regular_size] ) ) {

            $width = $imagedata['sizes'][$regular_size]['width'];
            $height = $imagedata['sizes'][$regular_size]['height'];

            if ( isset( $imagedata['sizes'][$size] ) )
                $url  = str_replace($img_url_basename, $imagedata['sizes'][$size]['file'], $img_url);
            else
                $url  = $img_url;

        }else{
            $url  = $img_url;
            $width = $imagedata['width'];
            $height = $imagedata['height'];
        }

        return array( $url, $width, $height );
    }

    return $value;
}

Now you can just call your images this way

wp_get_attachment_image( $attachment->ID, 'thumbnail_retina' );
wp_get_attachment_image( $attachment->ID, 'medium_retina' );
wp_get_attachment_image( $attachment->ID, 'large_retina' );

Important: after adding the 3 new sizes, I regenerated all thumbnails with the regenerate-thumbnails plugin

1
  • Though this does work (fully tried it), this may not always be necessary currently. With the srcset and sizes img attributes, retina screens are automatically "taken care of" by the browser. The "only" time they won't be is if there's an image bigger than the largest size WP provides, but that can be solved by adding another larger/2x/2.5x/3x size. Commented Jun 4, 2021 at 3:24

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.