web-dev-qa-db-fra.com

Modification de la compression JPEG en fonction de la taille de l'image

Court. Je veux que les "grandes" images soient compressées à 90% et les "moyennes" à 60%. Beaucoup d’entre vous ont déjà vu des images de grande taille, mais beaucoup moins compressées.

Cette fonction permet de ré-échantillonner toutes les images jpg

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

Comment filtrer par taille d'image?

8
DarkGhostHunter

Un très spécial filtre

Le filtre jpeg_quality est un filtre vraiment spécial: il est utilisé dans trois cas différents et vous devez utiliser le deuxième argument pour déterminer, si vous souhaitez utiliser le filtre ou non.

Ne le laisse pas tout faire

Le principal problème d'un tel filtre special est qu'il peut se déclencher pour des actions ultérieures, si vous ne le supprimez pas - laissez-le s'exécuter après le premier contrôle. Il faut donc insérer un autre filtre dans wp_save_image_file() pour vérifier si nous voulons modifier la compression ou non. Pour le désactiver pour un autre processus de sauvegarde, nous le supprimons juste avant de modifier la compression.

Le kool kid

Ce qui est vraiment étrange, c’est que WP utilise une compression par défaut de 90% (ce qui correspond à une qualité réduite de 10%) pour le processus de sauvegarde de {tous. Cela signifie que chaque fois que vous téléchargez/recadrez/modifiez une image, vous réduisez sa qualité ... ce qui est gênant pour les images qui ne sont pas les meilleures, lorsque vous les téléchargez (testez-les avec une image contenant beaucoup de rouge avec un fond contrasté). Mais... La chose vraiment intéressante est que vous pouvez changer ce comportement. Donc, vous voulez changer la compression, mais améliorer la qualité - bien mieux que ce que permet le cœur - en même temps.

/**
 * 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:} _ Après une brève discussion avec @toscho, il a précisé que le rappel pouvait être réduit à la suivante:

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

Alors que je sortais le code d'un plugin sur lequel je travaille actuellement, j'avais besoin de la variable switch pour y ajouter des paramètres. Je dois également noter que je n'utilise pas la variable global dans mon plugin, car il s'agit d'un OOP approche. Le code que vous pouvez lire ↑ ci-dessus est principalement du code réduit et modifié du plugin, qui a quelques restes mineurs et qui est censé être explicatif pour les lecteurs ultérieurs et qui fonctionne toujours. Si vous souhaitez l’utiliser comme plug-in, vous pouvez procéder à une optimisation en fonction de votre cas d'utilisation personnel.


Remarques:

D'après certaines enquêtes sur les différentes tâches, j'ai constaté que plusieurs $cases sont déclenchés aux étapes suivantes:

  • Faire pivoter: edit-image "image-resize (le 1 × le plus tard pour n’importe quelle taille que vous choisissez - Vignette, etc.)
  • Miroir: edit-image "image-resize (-" -)

Cela signifie que le rappel du filtre pour jpeq_quality déclenchera 2 × pour faire pivoter/reproduire une image et + 1 × pour toute taille supplémentaire que vous ajoutez. Donc, si vous avez moins de 100%, la qualité sera réduite deux fois. J'ai fait beaucoup de recherches sur ce sujet, mais je ne suis toujours pas tout à fait sûr des fonctions exactes qui causent ce comportement.

11
kaiser