Pregunta

Estoy tratando de encontrar una solución en la que los formatos de imagen generados cubran aspectos tanto responsivos como de alta resolución al cargar un nuevo elemento en el administrador de WP.He reunido un conjunto de formatos que deberían cumplir con estos requisitos,

Escritorio retina de 2560 x 1600 ('largex2', personalizado)
Escritorio de 1280 x 800 (grande)
Tableta retina de 1920 x 1200 ('medianax2', personalizada)
Tableta 960 x 600 + móvil retina (mediano)
480 x 300 móvil (miniatura)

Mi problema radica en la calidad de la imagen para los tamaños más grandes.Exportar las imágenes desde Photoshop con una configuración de calidad alta o muy alta producirá resultados justos para los tamaños predeterminados, pero ¿qué pasa con las personalizadas?Aquellos que prefiero exportar en una configuración media o baja para mantener un tamaño de archivo razonable.

Mi pensamiento es: ¿sería posible tomar una imagen realmente grande con alta calidad, cargarla y luego configurarla para que los tamaños más grandes se generen con una calidad mucho menor?

¡Cualquier ayuda es apreciada!No me dirija a ningún complemento. Quiero crear mi propia solución para esto.

¿Fue útil?

Solución

1) Una solución alternativa ampliando el WP_Image_Editor_GD clase

El problema es cómo acceder a los tamaños de imagen antes de cambiar la calidad del intermedio. jpeg imágenes.

Tenga en cuenta que el image_resize() la función es obsoleto.

Podemos usar el jpeg_quality filtrar del público get_quality método del resumen WP_Image_Editor clase:

$quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' );

o el wp_editor_set_quality filtrar.

Aquí hay una idea de cómo configurar la calidad de la imagen según el tamaño de la imagen (ancho/alto):

/**
 * Set image (jpeg) quality based on the image size (width/height)
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wpse_make_image_arguments', function( $arguments, $filename, $size, $function ) 
{   
    // Only target jpeg cases, i.e. with the quality set in $arguments[2]       
    if( ! isset( $size['height'] ) || ! isset( $size['width'] ) || ! isset( $arguments[2] ) )
        return $arguments;

    // Modify this part to your needs:
    if( $size['height'] <= 150  && $size['width'] <= 150 )
        $arguments[2] = 2; // very low quality for easy testing

    return $arguments;
}, 10, 4 );

donde hemos extendido el WP_Image_Editor_GD clase:

/**
 * Extend the WP_Image_Editor_GD to add the custom wpse_make_image_arguments filter.
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wp_image_editors', function( $editors ) 
{
    // Note that the WP_Image_Editor_GD and WP_Image_Editor_Imagick classes
    // are included within this filter. So let's do the same for our extended class.

    // Our extended class that overrides the WP_Image_Editor_GD::make_image() method

    if( ! class_exists( 'WPSE_Image_Editor_GD' ) )
    {   
        class WPSE_Image_Editor_GD extends WP_Image_Editor_GD
        {
            protected function make_image( $filename, $function, $arguments ) 
            {
                // Add a custom filter      
                $arguments = apply_filters( 'wpse_make_image_arguments', $arguments, $filename, $this->size, $function );

                // Parent method
                return parent::make_image( $filename, $function, $arguments );
            }
        }
    }

    // Prepend the extended class to the array of image editors:    
    array_unshift( $editors, 'WPSE_Image_Editor_GD' );

    return $editors;
} );

donde introdujimos la costumbre wpse_make_image_arguments filtrar.

De esta forma podremos modificar la configuración de calidad, antes Los archivos intermedios se guardan.

He aquí un ejemplo:

Example

PD: No revisé el caso cuando el Imágico En su lugar se utiliza la biblioteca, pero supongo que podríamos hacer algo similar extendiendo el WP_Image_Editor_Imagick clase.

2) Actualización: establezca la calidad jpeg por nombre de tamaño de imagen

Aquí hay otra versión en la que configuramos la calidad jpeg por nombre de tamaño de imagen:

/**
 * Extend the WP_Image_Editor_GD to set quality per image size name.
 * 
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wp_image_editors', function( $editors ) 
{
    // Note that the WP_Image_Editor_GD and WP_Image_Editor_Imagick classes
    // are included within this filter. So let's do the same for our extended class.

    // Our extended class that overrides the WP_Image_Editor_GD::_resize() method
    if( ! class_exists( 'WPSE2_Image_Editor_GD' ) )
    {   
        class WPSE2_Image_Editor_GD extends WP_Image_Editor_GD
        {
            protected function _resize( $max_w, $max_h, $crop = false )
            {
                $qualities = apply_filters( 'wpse_jpeg_qualities', [] );
                $default_quality = (int) apply_filters( 'wpse_default_jpeg_quality', 82 );                              
                $sizes = wp_get_additional_image_sizes();
                $this->set_quality( $default_quality );         
                foreach( (array) $qualities as $name => $quality )
                {
                    if( 
                        isset( $sizes[$name] ) 
                        && (int)  $sizes[$name]['width']  === (int)  $max_w
                        && (int)  $sizes[$name]['height'] === (int)  $max_h
                        && (bool) $sizes[$name]['crop']   === (bool) $crop  
                    )   
                        $this->set_quality( $quality );                 
                }

                // Parent method
                return parent::_resize( $max_w, $max_h, $crop );
            }
        }
    }

    // Prepend the extended class to the array of image editors:    
    array_unshift( $editors, 'WPSE2_Image_Editor_GD' );

    return $editors;
} );

Noté que los argumentos de recorte pueden ser 0, falsos o vacíos, por lo que encasillamos un poco para estar seguros.

Aquí hemos introducido los siguientes filtros nuevos:

add_filter( 'wpse_jpeg_qualities', function( $qualities )
{ 
    return [ 'hello-image' => 2, 'medium' => 2, 'large' => 2 ];
} );

y

add_filter( 'wpse_default_jpeg_quality', function( $quality )
{ 
    return 82;
} );

¡Eso, con suerte, se puede ajustar a sus necesidades!

Otros consejos

No puedo comentar, tengo que publicarlo junto con otra versión.

Los problemas):

No estoy seguro si el Actualización 2) Establecer calidad jpeg por nombre de tamaño de imagen en la respuesta aceptada está completa. wp_get_additional_image_sizes() devuelve el global $_wp_additional_image_sizes y no contiene ninguna información sobre los tamaños predeterminados como mediano, grande o miniatura.

Es posible que esto no funcione en el filtro:'grande' => 2

A partir de https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes explica con código personalizado para recuperar TODOS los tamaños con una función personalizada.

¿Estoy en lo cierto?

En segundo lugar, la idea de filtrar diferentes "tamaños" por nombre es complicada. _resize( $max_w, $max_h, $crop = false ) solo comprende y analiza el ancho, la altura y el valor de recorte coincidentes, y cada coincidencia suponer para coincidir con un nombre.Pero en muchos casos el nombre será "otro" nombre.

Una configuración de imagen "media" que tenga una configuración igual a "shop_product" sólo "visitará" esta función como una de ellas.Entonces no sabremos si lo que se está filtrando es el tamaño "mediano" o el tamaño "shop_product".Porque el objetivo aquí es sólo un recorte técnico de una imagen.

la idea con Actualización 2) Es un manejo más lógico, pero me temo que la arquitectura técnica no está ahí.Analizar todos los tamaños de imágenes registrados antes de construir el filtro, se vuelve más desarrollado para asegurarse de que la intención devuelva la calidad correcta del programa de imagen en el tema actual.

Todos los nombres de tamaño con configuraciones iguales compartirán la misma calidad nueva que comparten la misma imagen en el servidor.

Entonces, si aún te apegas a la actualización 2) Creo que necesitas llamar a otra función para completar el $sizes variable y analizar mediante var_dump() la $_wp_additional_image_sizes para ajustes iguales.

El enfoque en 1) Una solución alternativa por... Es más lógico/semántico.Resolvimos esto con el mismo método de extensión, pero usando un filtro dinámico en su lugar:

add_filter('wp_image_editors', function($editors){

    if(!class_exists('ENTEX_Image_Editor_GD')){   
        class ENTEX_Image_Editor_GD extends WP_Image_Editor_GD {
            private $wp_quality = null;
            protected function _resize($max_w, $max_h, $crop = false){
                $condition = ($crop ? 'true' : 'false');
                if($this->wp_quality === null) $this->wp_quality = $this->get_quality();
                $quality = apply_filters('wp_editor_set_quality_'. $max_w .'x'. $max_h .'_'. $condition, $this->wp_quality);                              
                $this->set_quality((int) $quality);
                return parent::_resize( $max_w, $max_h, $crop );
            }
        }
    }    
    array_unshift($editors, 'ENTEX_Image_Editor_GD');
    return $editors;
});

Para filtrar cada tamaño de imagen individual utilizamos:

add_filter('wp_editor_set_quality_160x160_true', function($quality){
    return 96;
});

Lo que también es diferente de esta versión extendida es que usamos/completamos el add_filter('jpeg_quality' ... versión como valor predeterminado.

A continuación se muestran algunos otros ejemplos de filtros personalizados:

function high_quality_on_medium_images(){
    $in = 'medium';
    $max_w = get_option($in.'_size_w');
    $max_h = get_option($in.'_size_h');
    $crop = get_option($in.'_crop');
    $condition = ($crop ? 'true' : 'false');
    add_filter('wp_editor_set_quality_'. $max_w .'x'. $max_h .'_'. $condition, 'my_theme_high_quality_images', 10, 1);
}
add_action('after_setup_theme', 'high_quality_on_medium_images', 99);

function my_theme_high_quality_images($quality){
    return (int) 82;
}

Atención a los desarrolladores

  • Asegúrese de que los filtros se apliquen después de configurar las imágenes del tema.
  • No envolver por dentro is_admin() luego llamada ajax, front-end, remota
    Las imágenes publicadas no muerden.

Como se mencionó, el valor del recorte podría ser 0 o falso, debe convertir (int) o (bool) en una cadena con $condition = ($crop ? 'true' : 'false');

Atención a los desarrolladores de temas.

La compresión predeterminada de WP es bastante progresiva.Valores entre 80 y 99 podría devolver una gran diferencia o ningún resultado visible en absoluto.Un valor sin compresión como 100, probablemente devuelve un tamaño de archivo más grande en "tamaño más pequeño" 800 píxeles imágenes, entonces el grande original 3000 píxeles versión de tamaño.

Después de muchos años encontramos un número mágico de 96, el tamaño del archivo se hace más pequeño pero no se puede ver la diferencia entre un 100 compresión de valores.

Imágenes de tienda preparadas con Photoshop de alta calidad, más grandes que 800 px están bien con el valor predeterminado de Wordpress 82.Pero la imagen publicada por correo electrónico "grande" del iPhone realmente necesita un valor 96 en tamaños PEQUEÑOS, como miniaturas.Se vuelven "suavemente borrosos" en las compresiones de Wordpres.

Se superará con este tema soluciones si no planea los escenarios para su proyecto, usuarios o tema.

Una última reflexión

Estoy realmente decepcionado con Wordpress porque este importante tema se descuida en la prioridad del desarrollo, ya que es más importante que nunca que las imágenes sean únicas y efectivas en la carga.

¿Por qué no podemos simplemente colocar un filtro en el lugar correcto que pueda usarse para compresión individual?Se molestan en "cambiar el nombre" a wp_editor_set_quality, y add_filter('jpeg_quality' ... ahora está en desuso.¿Por qué no pensar en esto completamente y simplemente eliminar el if ( ! $this->quality ) Verifique solo el método una vez como lo menciona @birgire.

Licenciado bajo: CC-BY-SA con atribución
scroll top