J'ai une taille d'image personnaliséehello-image
:
add_image_size( 'hello-image', 700, 300, true );
Chaque fois qu'une image est téléchargée, je compresse l'image recadrée de taille hello-image
en 40%
compression JPEG. Cela fonctionne très bien dans tous les cas sauf ...
Si le width de l'image d'origine est plus grand que 700px
, cela fonctionne très bien. Mais si sa largeur est moins que 700px
, la compression passe à environ 0%
.
Téléchargez les deux images suivantes:
Ensuite, j'ai créé un plugin qui a tout le code approprié:
<?php
/*
Plugin Name: WPSE: custom image size and JPEG compression
Description: custom image size and JPEG compression
Author: WPSE
Version: 1.0
*/
// Set JPEG compression quality
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 == 'large') {
// set the jpeg quality for 'large' size
imagejpeg($resource, $image, 35);
} elseif ($size == 'medium') {
// set the jpeg quality for the 'medium' size
imagejpeg($resource, $image, 35);
} elseif ($size == 'hello-image') {
// set the jpeg quality for the 'hello-image' size
imagejpeg($resource, $image, 40);
} else {
// set the jpeg quality for the rest of sizes
imagejpeg($resource, $image, 35); // 38
}
imagedestroy($resource);
}
}
}
}
// add custom image sizes to media uploader
function my_insert_custom_image_sizes( $sizes ) {
// get the custom image sizes
global $_wp_additional_image_sizes;
// if there are none, just return the built-in sizes
if ( empty( $_wp_additional_image_sizes ) )
return $sizes;
// add all the custom sizes to the built-in sizes
foreach ( $_wp_additional_image_sizes as $id => $data ) {
// take the size ID (e.g., 'my-name'), replace hyphens with spaces,
// and capitalise the first letter of each Word
if ( !isset($sizes[$id]) )
$sizes[$id] = ucfirst( str_replace( '-', ' ', $id ) );
}
return $sizes;
}
// Which custom image size selected by default
function my_set_default_image_size () {
return 'hello-image';
}
function custom_image_setup () {
// custom image sizes
add_image_size( 'medium', 300, 9999 ); // medium
add_image_size( 'hello-image', 700, 300, true ); // custom
add_image_size( 'large', 700, 3000 ); // large
add_filter( 'image_size_names_choose', 'my_insert_custom_image_sizes' );
add_filter( 'pre_option_image_default_size', 'my_set_default_image_size' );
}
add_action( 'after_setup_theme', 'custom_image_setup' );
Maintenant, téléchargez l’image grande _ et voyez comment l’image hello-image
est correctement compressée. Ensuite, chargez l'image petite et voyez comment la même taille d'image est compressée terriblement. Donc, pour clarifier, voici les résultats:
700x300 = 40% compression
670x300 = 0% compression
Les deux sont générés via la même taille d'image personnalisée. Quelle est la cause de ceci et comment peut-on le réparer?
Je tiens à souligner que mon collègue a posté une question ici demandant comment éviter de créer cette taille d'image si la largeur est inférieure à 700px
... mais je suis un connaisseur de WordPress qui préférerait résoudre la cause du problème que d'ajouter un correctif hacky à cela.
Enfin, j'ai commencé à voir ce problème dans une récente mise à jour de WordPress. Il peut donc s'agir d'un bogue dans le noyau, par opposition à un problème dans mon code.
Edit : Lire le update .
Quelques suggestions:
Si vous voulez essayer le API de l'éditeur d'image, vous pouvez essayer de le remplacer.
imagejpeg( $resource, $image, 35 );
avec:
$editor = wp_get_image_editor( $image );
if ( ! is_wp_error( $editor ) )
{
$editor->set_quality( 35 );
$editor->save( $image );
}
unset( $editor );
Essayez également de tester par exemple ces parties:
$resource = imagecreatefromjpeg( $image );
if( false !== $resource )
{
imagejpeg( $resource, $image, 35 );
imagedestroy( $resource );
}
dans un script autonome PHP, pour vous assurer qu'il ne s'agit pas d'un problème lié à PHP ou à Gd.
PS: Voici une approche différente où nous essayons de modifier la qualité de l’image avant la taille de l’image est générée.
Test du plugin
Vérifions le plugin de la question principale.
Test d'installation
Voici la taille générée hello-image
(670x300), de l'image SMALL (670 × 377), à partir de la question, où nous avons défini la qualité sur 40:
imagejpeg( $resource, $image, 40 );
Voici la même chose mais avec la qualité définie sur 0:
imagejpeg( $resource, $image, 0 );
Il semble donc que nous ne obtenons pas le même comportement que celui décrit dans la question: lorsque la qualité est définie sur 40, elle devient 0 pour la taille hello-image
de l'image d'origine 670x377.
Intéressant, je l'ai essayé et la petite image s'affiche en 670x300 et la grande image 700x300. Il me semble que son logiciel fait exactement ce qu'il doit faire. Il recadre l'image si la hauteur ou la largeur sont au-dessus du type d'image (ou les deux).
Je comprends que vous souhaitiez recadrer l’image uniquement si la hauteur est plus élevée? Ensuite, utiliser ceci fonctionnerait:
add_image_size( 'hello-world', 700, 0, true );
Je ré-télécharge les images après cela et les petites images sont affichées 670 sur 377 et la grande image 700 sur 394. J'ai téléchargé une autre version plus petite (516x290) et elle n'est pas recadrée.
Bien que, lorsque vous téléchargez une image telle que 690x4000, elle n’obtient pas non plus de recadrage.