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

8

Baixo. Quero imagens 'grandes' compactadas em 90% e 'média' em 60%. Você já sabe que muitas vezes as imagens maiores sofrem com alta compactação, mas outras imagens pequenas não.

Esta função permite reamostrar todas as imagens jpg

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

Como filtrar pelo tamanho da imagem?

DarkGhostHunter
fonte

Respostas:

11

Um filtro muito especial

O jpeg_qualityfiltro é realmente especial: é usado em três casos diferentes e você deve usar o segundo argumento para determinar se deseja ou não usar o filtro.

Não deixe fazer tudo

O principal problema desse 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 inserir outro filtro 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 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. Isso significa que, toda vez que você faz upload / recorta / edita uma imagem, reduz a qualidade ... o que é uma dor para as imagens que não são as melhores quando você faz o upload delas (teste-a com uma imagem contendo muito vermelho com um fundo de alto contraste). Mas ... O mais interessante é que você pode mudar esse comportamento. Então, você deseja alterar a compactação, mas obter maior qualidade - muito melhor do que o núcleo 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 );

EDIT: Após uma breve discussão com @toscho, ele apontou que todo o retorno de chamada poderia ser reduzido para o 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;
}

Como retirei o código de um plug-in no qual estou trabalhando, eu precisava switchadicionar configurações. Também tenho que observar que não uso o globalplug-in, pois é uma abordagem OOP. O código que você pode ler ↑ acima, é principalmente código reduzido e alterado do plug-in, que tem algumas sobras menores e serve para explicar os leitores posteriores e ainda funciona. Se você quiser usá-lo como plug-in, poderá fazer alguma otimização dependendo do seu caso de uso pessoal.


Notas:

De alguma investigação sobre as diferentes tarefas, notei que vários $cases são acionados nas seguintes etapas:

  • Girar: edit-image» image-resize(o último 1 × para qualquer tamanho que você escolher - miniatura, etc.)
  • Espelho: edit-image» image-resize(-" -)

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

kaiser
fonte
Ups você me pegou, print_r / var_dump não funciona. Como posso produzir isso?
DarkGhostHunter
Use echo '<pre>'.var_export( $image, true ).'</pre>';. Coloque um exit;depois dele, para que ele não fique ignorado com recarregar a página, etc.
kaiser
maldita, perdida na floresta - não consigo ver onde ela imprime. Eu tenho esse código antes do retorno $ image;
DarkGhostHunter
Adicione-o logo no início da wpse58600_custom_jpg_compression()função.
Kaiser
1
vamos continuar essa discussão no chat
DarkGhostHunter 17/07/2012