Alterando a compactação JPEG dependendo do tamanho da imagem

8

Curto. Eu quero imagens 'grandes' compactadas em 90% e 'médias' em 60%. Tem muitos af que você conhece, às vezes, imagens maiores sofrem de alta compressão, mas outras imagens pequenas não.

Esta função permite redimensionar todas as imagens jpg

function custom_jpg_compression($args) {
    return 90;
}
add_filter('jpeg_quality', 'custom_jpg_compression');

Como filtrar por tamanho de imagem?

    
por DarkGhostHunter 15.07.2012 / 23:14

1 resposta

11

Um filtro muito especial

O filtro jpeg_quality é um realmente especial: é usado em três casos diferentes e você usa o segundo argumento para determinar, se quiser para usar o filtro ou não.

Não deixe fazer tudo

O principal problema para esse filtro especial é que ele pode ser acionado para ações posteriores, se você não o remover - permita que ele seja executado após a primeira verificação. Portanto, precisamos obter outro filtro dentro de wp_save_image_file() para verificar se queremos alterar a compactação ou não. Para desativá-lo para outro processo de salvamento, nós o removemos antes de alterar a compactação.

O garoto de kool

O mais estranho é que o WP usa uma compactação padrão de 90% (que é 10% de qualidade reduzida) para cada processo de salvamento. Isto significa que, sempre que carregar / cortar / editar uma imagem, reduz a sua qualidade ... o que é um saco para imagens que não são as melhores, quando as carrega (teste-a com uma imagem que contém muito vermelho com um fundo de alto contraste). Mas ... O mais interessante é que você pode mudar esse comportamento. Então você quer mudar a compressão, mas obter maior qualidade - muito melhor do que o core permite - ao mesmo tempo.

/**
 * Alter the image compression, depending on case
 * 
 * @param  int $compression
 * @param  string $case
 * @return int $compression
 */
function wpse58600_custom_jpg_compression_cb( $compression, $case )
{
    global $size_switch;

    // Should only fire once - don't leave it in for later cases
    remove_filter( current_filter(), __FUNCTION__ );

    // Alter the compression, depending on the case
    switch ( $case )
    {
        case( 'edit_image' ) :
            // We only add the compression, if the switch triggered,
            // which means, that the size is smaller, than set in the main function.
            // 60 is the percentage value, that gets added as compression to the smaller images.
            $compression = $size_switch ? 60 : 100;
            break;

        case( 'image_resize' ) :
            // Better leave it on 100% for resize
            $compression = 100;
            break;

        case( 'wp_crop_image' ) :
            // Better leave it on 100% for crop
            // We already compressed it on the camera, the desktop/handheld device 
            // and the server previously. That's enough so far.
            $compression = 100;
            break;
    }

    return $compression;
}

/**
 * Alter the compression for JPEG mime type images
 * Checks for a specific min size of the image, before altering it
 * 
 * @param  string $image
 * @param  int $post_id 
 * @return string $image
 */
function wpse58600_custom_jpg_compression( $image, $post_id )
{
    global $size_switch;
    $size_switch = false;

    // Define the size, that stops adding a compression
    $trigger_size = 641;

    // Get the sizes
    $size_x = imagesx( $image );
    $size_y = imagesy( $image );

    // Add the filter only in case
    if ( $trigger_size < $size_x )
    {
        $size_switch = true;
    }
    add_filter( 'jpeg_quality', 'wpse58600_custom_jpg_compression_cb', 20, 2 );

    return $image;
}
add_filter( 'image_save_pre', 'wpse58600_custom_jpg_compression', 20, 2 );

EDITAR: Após uma breve discussão com @toscho, ele apontou que todo o retorno de chamada poderia ser reduzido ao seguinte:

function wpse58600_custom_jpg_compression_cb( $compression, $case )
{
    // Should only fire once - don't leave it in for later cases
    remove_filter( current_filter(), __FUNCTION__ );

    return ( $GLOBALS['size_switch'] && 'edit_image' === $case ) ? 60 : 100;
}

Ao retirar o código de um plug-in no qual estou trabalhando atualmente, precisei que o switch adicionasse configurações. Também preciso observar que não uso o global no meu plug-in, como é uma abordagem OOP. O código que você pode ler acima, é principalmente reduzido e alterado código do plugin, que tem algumas sobras menores e se destina a ser explicativo para os leitores posteriores e ainda funciona. Se você quiser usá-lo como plugin, você pode fazer alguma otimização, dependendo do seu caso de uso pessoal.

Notas:

A partir de algumas investigações sobre as diferentes tarefas, notei que vários $case s são acionados nas etapas a seguir:

  • Girar: edit-image » image-resize (mais tarde 1 × para qualquer tamanho que você escolher - Miniatura, etc.)
  • Espelho: edit-image » image-resize (-" -)

Isso significa que o retorno de chamada do filtro para jpeq_quality acionará 2 × para girar / espelhar uma imagem e + 1 × para qualquer tamanho adicional que você adicionar. Então, se você tiver menos de 100%, reduzirá a qualidade duas vezes. Fiz muita pesquisa sobre esse assunto, mas ainda não tenho certeza, quais funções exatas causam esse comportamento.

    
por kaiser 16.07.2012 / 00:54