Добавьте размер изображения, где генерируется максимально возможный пропорциональный размер

8

Я хотел бы добавить размер изображения, при котором полученное изображение будет иметь максимально возможный размер при сохранении соотношения сторон 4: 3.

Предположим, я добавил размер изображения примерно так:

add_image_size( 'cover-image', 2048, 1536, true );

По умолчанию WP создает изображение только с таким размером, если полноразмерное изображение больше этих размеров.

Но предположим, что мое полноразмерное изображение имеет ширину всего 1000 пикселей. Я все еще хотел бы обрезать изображение до максимально возможного соотношения 4: 3, которое в этом случае будет 1000x750.

Можно ли это сделать?

Крис Монтгомери
источник

Ответы:

11

Подход

Я думаю, что лучший подход - это создать размер изображения «на лету», непосредственно перед изменением размера изображения.

Вы можете сделать это, используя 'intermediate_image_sizes_advanced'фильтр Hook. Это позволяет вам редактировать размер, который будет сгенерирован, но с учетом текущего размера изображения, который сохраняется в массиве, $metadataпередаваемом фильтром в качестве второго аргумента.

Математика

Прежде всего давайте напишем класс, который возвращает самые большие размеры для определенного соотношения.

class ImageRatio {

  private $ratio;

  function __construct($ratioW = 4, $ratioH = 3) {
    $this->ratio = array($ratioW, $ratioH);
  }

  function getLargestSize($imgW, $imgH) {
    $inverse = false;
    // let's try to keep width and calculate new height  
    $newSize = round(($this->ratio[1] * $imgW) / $this->ratio[0]);
    if ($newSize > $imgH) {
       $inverse = true;
       // if the calculated height is bigger than actual size
       // let's keep current height and calculate new width
       $newSize = round(($this->ratio[0] * $imgH) / $this->ratio[1]);
    }

    return $inverse ? array( $newSize, $imgH ) : array( $imgW, $newSize );
  }

}

Использование класса

Использование класса довольно просто:

$ratio = new ImageRatio(4, 3)

$ratio->getLargestSize(1000, 500); // return: array(667, 500)
$ratio->getLargestSize(1000, 800); // return: array(1000, 750)

В действии

На этом этапе мы можем использовать класс для вычисления на лету нового размера изображения, основываясь на загружаемом изображении.

add_filter( 'intermediate_image_sizes_advanced', function( $sizes, $metadata ) {

   if (! empty( $metadata['width'] ) && ! empty( $metadata['height'] ) ) {
      // calculate the max width and height for the ratio
      $ratio = new ImageRatio( 4, 3 );
      list($width, $height) = $ratio->getLargestSize( 
         $metadata['width'],
         $metadata['height']
      );
      // let's add our custom size
      $sizes['biggest-4-3'] = array(
        'width'  => $width,
        'height' => $height,
        'crop'   => true
      );
   }

   return $sizes;

}, 10, 2 );

Используя новый размер

$image = wp_get_attachment_image( $attachment_id, 'biggest-4-3' );

Запись

Конечно, это работает для всех изображений, которые вы загружаете после установки кода. Для старых изображений вы должны заново сгенерировать миниатюры, на лету, когда они используются, или навалом, используя один из плагинов, доступных в Интернете.

Gmazzap
источник
Это прекрасно работает, спасибо! Одно небольшое исправление, которое я хотел бы сделать: я думаю, что нет необходимости устанавливать коэффициент по умолчанию в конструкторе, так как я мог бы использовать его для других коэффициентов в будущем. Имеет смысл всегда предоставлять желаемое соотношение при создании экземпляра.
Крис Монтгомери
Аргументы в конструкторе просто по умолчанию. Вы можете передать любое соотношение, которое хотите, по умолчанию используются, только если вы ничего не передаете
gmazzap