Adicione tamanho da imagem onde o maior tamanho proporcional possível é gerado

8

Gostaria de adicionar um tamanho de imagem em que a imagem resultante tenha o maior tamanho possível, mantendo uma proporção de 4: 3.

Suponha que eu adicionei um tamanho de imagem da seguinte forma:

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

Por padrão, o WP criará apenas uma imagem com esse tamanho se a imagem em tamanho maior for maior que essas dimensões.

Mas suponha que minha imagem em tamanho real tenha apenas 1000 px de largura. Eu ainda gostaria de ter uma imagem cortada na maior proporção possível de 4: 3, que nesse caso seria de 1000x750.

Isso pode ser feito?

Chris Montgomery
fonte

Respostas:

11

A abordagem

Eu acho que a melhor abordagem é criar um tamanho de imagem "on the fly", pouco antes de as imagens serem redimensionadas.

Você pode fazer isso usando o 'intermediate_image_sizes_advanced'gancho de filtro. Isso permite que você edite o tamanho a ser gerado, mas esteja ciente do tamanho da imagem atual, que é armazenada na matriz $metadatapassada pelo filtro como segundo argumento.

A matemática

Antes de tudo, vamos escrever uma classe que retorne os maiores tamanhos para uma proporção específica.

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 );
  }

}

Uso de classe

O uso da classe é bastante fácil:

$ratio = new ImageRatio(4, 3)

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

Em ação

Nesse ponto, podemos usar a classe para calcular rapidamente um novo tamanho de imagem, com base na imagem que está sendo carregada

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 );

Usando o novo tamanho

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

Nota

Obviamente, isso funciona para todas as imagens que você carrega após o código estar em vigor. Para imagens mais antigas, você deve gerar novamente as miniaturas rapidamente, quando usadas, ou em massa usando um dos plug-ins disponíveis na Web.

gmazzap
fonte
Isso funciona muito bem, obrigado! Uma pequena correção que eu faria: acho desnecessário definir uma taxa padrão no construtor, pois eu poderia usá-la para outras taxas no futuro. Faz sentido sempre fornecer a proporção desejada na instanciação.
Chris Montgomery
Os argumentos no construtor são apenas o padrão. Você pode passar a proporção que desejar, o padrão será usado apenas se você não passar nada
gmazzap