Definir compactação JPEG para tamanhos de imagem personalizados específicos

8

Uso vários tamanhos de imagem personalizados (por add_image_size) e configurei minha compactação JPEG para 30% com este filtro:

function jpeg_quality_callback($arg) {
   return (int)30;
}
add_filter('jpeg_quality', 'jpeg_quality_callback');

Se não me engano, o código acima comprime todos os meus tamanhos de imagem personalizados com 30%. Agora, para dois dos meus tamanhos de imagem personalizados nomeados splash1e splash2, desejo definir a compactação para 80%. Como isso é possível?

Ou, como alternativa, exclua esses tamanhos de imagem do filtro de compressão de 30%.

Amanda Duke
fonte

Respostas:

9

As 'jpeg_quality'funções de gancho de filtro aceitam dois argumentos: $jpeg_qualitye $functionqual é a função de dentro do gancho de filtro é acionada e pode ser image_resizeou wp_crop_image. Portanto, não há como definir seletivamente a qualidade das .jpegimagens de acordo com o tamanho da imagem nesta função de gancho de filtro.

No entanto, você ainda pode conectar-se a um gancho de ação posterior no processo de upload de anexos e ajustar a .jpegqualidade da imagem nesse momento de acordo com o tamanho específico para atender às suas necessidades. Primeiro, defina o valor jpeg_qualitymáximo para preservar a qualidade da imagem original e, em seguida, ligue o gancho de added_post_metaação (que é acionado no final da inserção dos metadados do anexo ») para ajustar a qualidade, da seguinte maneira:

// set the quality to maximum
add_filter('jpeg_quality', create_function('$quality', 'return 100;'));

add_action('added_post_meta', 'ad_update_jpeg_quality', 10, 4);

function ad_update_jpeg_quality($meta_id, $attach_id, $meta_key, $attach_meta) {

    if ($meta_key == '_wp_attachment_metadata') {

        $post = get_post($attach_id);

        if ($post->post_mime_type == 'image/jpeg' && is_array($attach_meta['sizes'])) {

            $pathinfo = pathinfo($attach_meta['file']);
            $uploads = wp_upload_dir();
            $dir = $uploads['basedir'] . '/' . $pathinfo['dirname'];

            foreach ($attach_meta['sizes'] as $size => $value) {

                $image = $dir . '/' . $value['file'];
                $resource = imagecreatefromjpeg($image);

                if ($size == 'spalsh') {
                    // set the jpeg quality for 'spalsh' size
                    imagejpeg($resource, $image, 100);
                } elseif ($size == 'spalsh1') {
                    // set the jpeg quality for the 'splash1' size
                    imagejpeg($resource, $image, 30);
                } else {
                    // set the jpeg quality for the rest of sizes
                    imagejpeg($resource, $image, 10);
                }

                // or you can skip a paticular image size
                // and set the quality for the rest:
                // if ($size == 'splash') continue;

                imagedestroy($resource);
            }
        }
    }
}

O código acima afetará apenas as imagens recém-carregadas. Se você deseja atualizar a qualidade das imagens carregadas anteriormente, pode utilizar os register_activation_hookplug-ins. Crie um novo arquivo php no wp-content/pluginsdiretório e nomeie o que quiser ( update-jpeg-quality.phppor exemplo) e adicione o seguinte código:

<?php
/*
Plugin Name: Update JPEG Quality
Plugin URI: http://wordpress.stackexchange.com/questions/74103/set-jpeg-compression-for-specific-custom-image-sizes
Description: This plugin will change the jpeg image quality according to its size.
Author: Ahmad M
Version: 1.0
Author URI: http://wordpress.stackexchange.com/users/12961/ahmad-m
*/

register_activation_hook(__FILE__, 'ad_modify_jpeg_quality');

function ad_modify_jpeg_quality() {

    $attachments = get_posts(array(
        'numberposts' => -1,
        'post_type' => 'attachment',
        'post_mime_type' => 'image/jpeg'
    ));

    if (empty($attachments)) return;

    $uploads = wp_upload_dir();

    foreach ($attachments as $attachment) {

        $attach_meta = wp_get_attachment_metadata($attachment->ID);
        if (!is_array($attach_meta['sizes'])) break;

        $pathinfo = pathinfo($attach_meta['file']);
        $dir = $uploads['basedir'] . '/' . $pathinfo['dirname'];

        foreach ($attach_meta['sizes'] as $size => $value) {

            $image = $dir . '/' . $value['file'];
            $resource = imagecreatefromjpeg($image);

            if ($size == 'spalsh') {
                // set the jpeg quality for 'spalsh' size
                imagejpeg($resource, $image, 100);
            } elseif ($size == 'spalsh1') {
                // set the jpeg quality for the 'splash1' size
                imagejpeg($resource, $image, 30);
            } else {
                // set the jpeg quality for the rest of sizes
                imagejpeg($resource, $image, 10);
            }

            imagedestroy($resource);
        }
    }
}
?>

Agora, visite a sua página de Plugins e bater activatedo Update JPEG Qualityplugin. Isso percorrerá todas as .jpegimagens enviadas anteriormente e ajustará sua qualidade de acordo com os valores e condições especificados no plug-in. Em seguida, você pode desativar e excluir com segurança este plug-in. Teste primeiro o ambiente de teste antes de aplicar no local de produção .

Ahmad M
fonte
Esta é uma resposta muito interessante. Como faço para adicionar tanto 'splash1' e 'splash2' para a instrução IF ?: if ($ size == 'respingo') ...
Amanda Duke
1
@ AmandaDuke: Você pode estender a ifdeclaração por elseif. Veja minha atualização.
Ahmad M
2
@ Ahmad, existe um erro no seu código. Ao fazer upload de uma imagem, se é menor do que as dimensões do menor tamanho de imagem personalizado, então este erro: Invalid argument supplied for foreach(). Então, basicamente, quando nenhuma imagem personalizada é feita, o erro aparece. Você sabe como resolver esse problema?
Amanda Duke
1
@AmandaDuke Obrigado por apontar isso. Este erro ocorre porque $attach_meta['sizes']é esperado que seja uma matriz, enquanto neste caso não é. Na maioria dos casos, deveria e isso só pode acontecer se não tivermos tamanhos de imagem personalizados e não especificarmos os tamanhos de imagem padrão em Configurações -> Configurações de mídia . Para ser seguro e garantir que temos um array podemos adicionar uma verificação antes de passá-lo para o foreachloop: if (is_array($attach_meta['sizes'])). Por favor, veja o código atualizado.
Ahmad H
1
@ AmandaDuke: Ambos os blocos de código foram atualizados. O primeiro bloco foi antes: if ( $post->post_mime_type == 'image/jpeg' )e agora éif ( $post->post_mime_type == 'image/jpeg' && is_array($attach_meta['sizes']) )
Ahmad M