Изменение сжатия JPEG в зависимости от размера изображения


8

Короткий. Я хочу, чтобы «большие» изображения были сжаты на 90%, а «средние» - на 60%. Имеет много, как вы знаете, иногда большие изображения страдают от высокого сжатия, а другие маленькие изображения нет.

Эта функция позволяет пересчитать все изображения JPG

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

Как отфильтровать по размеру изображения?

Ответы:


11

Очень специальный фильтр

jpeg_qualityФильтр является действительно особенным: он привыкает в трех различных случаях , и вы , чтобы использовать второй аргумент , чтобы определить, если вы хотите использовать фильтр или нет.

Не позволяй этому делать все

Основная проблема такого специального фильтра заключается в том, что он может сработать для последующих действий, если вы его не удалите - разрешите ему работать после первой проверки. Таким образом, нам нужен еще один фильтр, wp_save_image_file()чтобы проверить, хотим ли мы изменить сжатие или нет. Чтобы отключить его для другого процесса сохранения, мы удаляем его непосредственно перед изменением сжатия.

Малыш Кул

Действительно странно то, что WP использует сжатие по умолчанию 90% (что на 10% снижает качество) для каждого процесса сохранения. Это означает, что каждый раз, когда вы загружаете / обрезаете / редактируете изображение, вы снижаете его качество ... что является болью для изображений, которые не самые лучшие, когда вы загружаете их (проверьте это с изображением, содержащим много красного с высококонтрастным фоном). Но ... Самое интересное в том, что вы можете изменить это поведение. Таким образом, вы хотите изменить сжатие, но в то же время получить более высокое качество - намного лучше, чем позволяет ядро.

/**
 * 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 );

РЕДАКТИРОВАТЬ: После короткого обсуждения с @toscho, он указал, что весь обратный вызов может быть уменьшен до следующего:

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

Когда я вытащил код из плагина, над которым я сейчас работаю, мне нужно switchбыло добавить настройки. Я также должен отметить, что я не использую globalв своем плагине, так как это ООП подход. Код, который вы можете прочитать выше, в основном сокращен и изменен из плагина, который имеет некоторые незначительные остатки и предназначен для пояснения для более поздних читателей и все еще работает. Если вы хотите использовать его как плагин, вы можете провести некоторую оптимизацию в зависимости от вашего личного использования.


Ноты:

Из некоторых исследований различных задач я заметил, что множественные $cases запускаются на следующих шагах:

  • Повернуть: edit-image» image-resize(позднее 1 × для любого размера, который вы выберете - миниатюра и т. Д.)
  • Зеркало: edit-image» image-resize(-" -)

Это означает, что обратный вызов фильтра для jpeq_qualityсработает 2 × для поворота / зеркального отображения изображения и + 1 × для любого добавляемого вами дополнительного размера. Так что если вы получили менее 100%, это снизит качество в два раза. Я провел много исследований на эту тему, но я все еще не совсем уверен, какие именно функции вызывают такое поведение.


Ups вы меня поняли, print_r / var_dump не работает. Как я могу вывести это?
DarkGhostHunter

Использование echo '<pre>'.var_export( $image, true ).'</pre>';. Поставьте exit;после него, чтобы оно не пропускалось при перезагрузке страницы и т. Д.
kaiser

блин, потерялся в лесу - я не вижу, где он печатается. У меня есть этот код до возврата $ image;
DarkGhostHunter

Добавьте его прямо в начале wpse58600_custom_jpg_compression()функции.
Кайзер

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.