Make WordPress Core


Ignore:
Timestamp:
08/30/2015 02:40:40 AM (11 years ago)
Author:
wonderboymusic
Message:

Improve the reliability of the crop returned by image_get_intermediate_size().

Add a bunch of unit tests to tests/image/intermediate_size.php.

Props joemcgill, ericlewis, kitchin, SergeyBiryukov, chipbennett.
Fixes #17626.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/media.php

    r33705 r33807  
    608608        // get the best one for a specified set of dimensions
    609609        if ( is_array($size) && !empty($imagedata['sizes']) ) {
    610                 $areas = array();
     610                $candidates = array();
    611611
    612612                foreach ( $imagedata['sizes'] as $_size => $data ) {
    613                         // already cropped to width or height; so use this size
    614                         if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
     613                        // If there's an exact match to an existing image size, short circuit.
     614                        if ( $data['width'] == $size[0] && $data['height'] == $size[1] ) {
    615615                                $file = $data['file'];
    616616                                list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    617617                                return compact( 'file', 'width', 'height' );
    618618                        }
    619                         // add to lookup table: area => size
    620                         $areas[$data['width'] * $data['height']] = $_size;
    621                 }
    622                 if ( !$size || !empty($areas) ) {
     619                        // If it's not an exact match but it's at least the dimensions requested.
     620                        if ( $data['width'] >= $size[0] && $data['height'] >= $size[1] ) {
     621                                $candidates[ $data['width'] * $data['height'] ] = $_size;
     622                        }
     623                }
     624
     625                if ( ! empty( $candidates ) ) {
    623626                        // find for the smallest image not smaller than the desired size
    624                         ksort($areas);
    625                         foreach ( $areas as $_size ) {
     627                        ksort( $candidates );
     628                        foreach ( $candidates as $_size ) {
    626629                                $data = $imagedata['sizes'][$_size];
    627                                 if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
    628                                         // Skip images with unexpectedly divergent aspect ratios (crops)
    629                                         // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
    630                                         $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
    631                                         // If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
    632                                         if ( 'thumbnail' != $_size && ( !$maybe_cropped || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] ) || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] ) ) )
    633                                                 continue;
    634                                         // If we're still here, then we're going to use this size
    635                                         $file = $data['file'];
    636                                         list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    637                                         return compact( 'file', 'width', 'height' );
     630
     631                                // Skip images with unexpectedly divergent aspect ratios (crops)
     632                                // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
     633                                $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
     634                                // If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
     635                                if ( 'thumbnail' != $_size &&
     636                                  ( ! $maybe_cropped
     637                                    || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] )
     638                                    || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] )
     639                                  ) ) {
     640                                  continue;
    638641                                }
     642                                // If we're still here, then we're going to use this size
     643                                $file = $data['file'];
     644                                list( $width, $height ) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
     645                                return compact( 'file', 'width', 'height' );
    639646                        }
    640647                }
Note: See TracChangeset for help on using the changeset viewer.