Qualidade de imagem baseada no tamanho da imagem

13

É possível definir a qualidade da imagem com base no tamanho da imagem? Eu gostaria de ter uma melhor qualidade de imagem para imagens maiores (80) - e pior para miniaturas pequenas (30).

Eu estava esperando um parâmetro em add_size para controlar isso - mas não há nenhum.

Se é importante: estou usando o ImageMagick.

    
por Nils Riedemann 21.03.2014 / 14:23

2 respostas

14

A única hora em que a qualidade é realmente importante está correta antes que a imagem seja salva ou transmitida (para o editor). Ambos têm o filtro "image_editor_save_pre", passando a instância do editor de imagens. Então você pode usar isso para modificar a imagem da maneira que quiser, incluindo a configuração da qualidade.

Então, algo assim deve fazer o trabalho de maneira simples e fácil:

add_filter('image_editor_save_pre','example_adjust_quality');
function example_adjust_quality($image) {
    $size = $image->get_size();
    // Values are $size['width'] and $size['height']. Based on those, do what you like. Example:
    if ( $size['width'] <= 100 ) {
        $image->set_quality(30);
    }
    if ( $size['width'] > 100 && $size['width'] <= 300 ) {
        $image->set_quality(70);
    }
    if ( $size['width'] > 300 ) {
        $image->set_quality(80);
    }
    return $image;
}
    
por Otto 26.03.2014 / 17:57
5

Anotação inicial: A resposta abaixo não está finalizada e não foi testada, mas ainda não tenho tempo suficiente, então deixarei isso aqui como rascunho. O que provavelmente precisa de um segundo par de olhos é o método de qualidade e a interpretação de version_compare() .

Primeiro precisamos de um ponto de entrada. Depois de ler novamente as postagens , pensei que seria melhor antes que o Editor de Imagens salve a imagem recém-criada. Então aqui está um microcontrolador que intercepta durante um retorno de chamada conectado a image_editor_save_pre e carrega uma classe que percorre as configurações definidas dentro de um retorno de chamada para wpse_jpeg_quality . Ele simplesmente retorna diferentes taxas de compactação para o filtro jpeg_quality que é executado dentro do Editor de Imagens.

<?php

namespace WPSE;

/**
 * Plugin Name: (#138751) JPEG Quality Router
 * Author:      Franz Josef Kaiser
 * Author URI:  http://unserkaiser.com
 * License:     CC-BY-SA 2.5
 */

add_filter( 'image_editor_save_pre', 'WPSE\JPEGQualityController', 20, 2 );
/**
 * @param string $image
 * @param int $post_id
 * @return string
 */
function JPEGQualityController( $image, $post_id )
{
    $config = apply_filters( 'wpse_jpeg_quality', array(
        # Valid: <, lt, <=, le, >, gt, >=, ge, ==, =, eq
        'limit'      => 'gt',
        # Valid: h, w
        'reference'  => 'w',
        'breakpoint' => 50,

        'low'        => 80,
        'high'       => 100,
    ) );
    include_once plugin_dir_path( __FILE__ ).'worker.php';
    new \WPSE\JPEGQualityWorker( $image, $config );

    return $image;
}

O trabalhador real é a classe JPEGQualityWorker . Ele reside no mesmo diretório que o arquivo de plug-in principal acima e é denominado worker.php (ou você altera o controlador acima).

Recupera a imagem e suas configurações e adiciona retornos de chamada ao filtro jpeg_quality . O que é isso é

  • recuperando sua referência de imagem (largura ou altura)
  • questionando seu ponto de interrupção que decide onde alternar entre baixa e alta qualidade / taxa de compactação
  • recuperando o tamanho da imagem original
  • decidir qual qualidade será retornada

O ponto de interrupção e o limite é o que decide entre alto e baixo e, como mencionado acima, isso pode precisar de mais amor.

<?php

namespace WPSE;

/**
 * Class JPEGQualityWorker
 * @package WPSE
 */
class JPEGQualityWorker
{
    protected $config, $image;
    /**
     * @param string $image
     * @param array $config
     */
    public function __construct( Array $config, $image )
    {
        $this->config = $config;
        $this->image  = $image;

        add_filter( 'jpeg_quality', array( $this, 'setQuality' ), 20, 2 );
    }

    /**
     * Return the JPEG compression ratio.
     *
     * Avoids running in multiple context, as WP runs the function multiple
     * times per resize/upload/edit task, which leads to over compressed images.
     *
     * @param int $compression
     * @param string $context Context: edit_image/image_resize/wp_crop_image
     * @return int
     */
    public function setQuality( $compression, $context )
    {
        if ( in_array( $context, array(
            'edit_image',
            'wp_crop_image',
        ) ) )
            return 100;

        $c = $this->getCompression( $this->config, $this->image );

        return ! is_wp_error( $c )
            ? $c
            : 100;
    }

    /**
     * @param array $config
     * @param string $image
     * @return int|string|\WP_Error
     */
    public function getCompression( Array $config, $image )
    {
        $reference = $this->getReference( $config );
        if ( is_wp_error( $reference ) )
            return $reference;
        $size = $this->getOriginalSize( $image, $reference );
        if ( is_wp_error( $size ) )
            return $size;

        return $this->getQuality( $config, $size );
    }

    /**
     * Returns the quality set for the current image size.
     * If
     * @param array $config
     * @param int $size
     */
    protected function getQuality( Array $config, $size )
    {
        $result = version_compare( $config['breakpoint'], $size );
        return (
            0 === $result
            AND in_array( $config['limit'], array( '>', 'gt', '>=', 'ge', '==', '=', 'eq' ) )
            ||
            1 === $result
            AND in_array( $config['limit'], array( '<', 'lt', '<=', 'le', ) )
        )
            ? $config['high']
            : $config['low'];
    }

    /**
     * Returns the reference size (width or height).
     *
     * @param array $config
     * @return string|\WP_Error
     */
    protected function getReference( Array $config )
    {
        $r = $config['reference'];
        return ! in_array( $r, array( 'w', 'h', ) )
            ? new \WP_Error(
                'wrong-arg',
                sprintf( 'Wrong argument for "reference" in %s', __METHOD__ )
            )
            : $r;
    }

    /**
     * Returns the size of the original image (width or height)
     * depending on the reference.
     *
     * @param string $image
     * @param string $reference
     * @return int|\WP_Error
     */
    protected function getOriginalSize( $image, $reference )
    {
        $size = 'h' === $reference
            ? imagesy( $image )
            : imagesx( $image );

        # @TODO Maybe check is_resource() to see if we got an image
        # @TODO Maybe check get_resource_type() for a valid image
        # @link http://www.php.net/manual/en/resource.php

        return ! $size
            ? new \WP_Error(
                'image-failure',
                sprintf( 'Resource failed in %s', get_class( $this ) )
            )
            : $size;
    }
}
    
por kaiser 21.03.2014 / 17:57