Cambiar la compresión JPEG según el tamaño de la imagen

8

Corto. Quiero imágenes "grandes" comprimidas en un 90% y "medianas" en un 60%. Tiene muchas cosas que sabes, a veces las imágenes más grandes sufren de alta compresión, pero otras imágenes pequeñas no.

Esta función permite volver a muestrear todas las imágenes jpg

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

¿Cómo filtrar por tamaño de imagen?

DarkGhostHunter
fuente

Respuestas:

11

Un filtro muy especial

El jpeg_qualityfiltro es realmente especial: se usa en tres casos diferentes y debe usar el segundo argumento para determinar si desea usar el filtro o no.

No dejes que haga todo

El principal problema para un filtro tan especial es que puede activarse para acciones posteriores, si no lo elimina, permita que se ejecute después de la primera verificación. Por lo tanto, necesitamos otro filtro wp_save_image_file()para verificar si queremos alterar la compresión o no. Para deshabilitarlo para otro proceso de guardado, lo eliminamos justo antes de alterar la compresión.

El niño kool

Lo realmente extraño es que WP utiliza una compresión predeterminada del 90% (que es un 10% de calidad reducida) para cada proceso de guardado. Esto significa que cada vez que carga / recorta / edita una imagen, reduce su calidad ... lo cual es un dolor para las imágenes que no son las mejores, cuando las carga (pruébelo con una imagen que contenga mucho rojo). con un fondo de alto contraste). Pero ... Lo realmente bueno es que puedes cambiar este comportamiento. Por lo tanto, desea cambiar la compresión, pero obtener una mayor calidad , mucho mejor de lo que permite el núcleo, al mismo tiempo.

/**
 * 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: Después de una breve discusión con @toscho, señaló, que toda la devolución de llamada podría reducirse a lo siguiente:

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

Cuando saqué el código de un complemento en el que estoy trabajando actualmente, necesitaba switchagregar la configuración. También tengo que tener en cuenta que no uso el globalen mi complemento, ya que es un enfoque OOP. El código que puede leer ↑ arriba, es principalmente un código reducido y alterado del complemento, que tiene algunos sobrantes menores y está destinado a ser explicativo para lectores posteriores y aún funciona. Si desea usarlo como complemento, puede hacer alguna optimización dependiendo de su caso de uso personal.


Notas:

De alguna investigación sobre las diferentes tareas, hay, noté, que $casese activan múltiples s en los siguientes pasos:

  • Rotar: edit-image» image-resize(el último 1 × para cualquier tamaño que elija - Miniatura, etc.)
  • Espejo: edit-image» image-resize(-" -)

Esto significa que la devolución de llamada del filtro jpeq_qualityactivará 2 × para girar / reflejar una imagen y + 1 × para cualquier tamaño adicional que agregue. Entonces, si obtuvo menos del 100%, reducirá la calidad dos veces. Investigué mucho sobre este tema, pero todavía no estoy completamente seguro de qué funciones exactas causan este comportamiento.

emperador
fuente
Ups me tienes, print_r / var_dump no funciona. ¿Cómo puedo sacar eso?
DarkGhostHunter
Uso echo '<pre>'.var_export( $image, true ).'</pre>';. Pon un exit;después, para que no se salte con la recarga de la página, etc.
kaiser
Maldición, perdido en el bosque. No puedo ver dónde se imprime. Tengo ese código antes de la devolución de $ imagen;
DarkGhostHunter
Agréguelo al principio de la wpse58600_custom_jpg_compression()función.
kaiser
1
vamos a continuar esta discusión en el chat
DarkGhostHunter