Качество изображения в зависимости от размера изображения

15

Можно ли установить качество изображения в зависимости от размера изображения? Я хотел бы иметь лучшее качество изображения для больших изображений (80) - и хуже для небольших миниатюр (30).

Я ожидал, что параметр, add_sizeчтобы контролировать это - но нет ни одного.

Если это имеет значение: я использую ImageMagick.

Нильс Ридеманн
источник

Ответы:

15

Единственное время, когда настройка качества действительно имеет значение, это прямо перед сохранением или передачей изображения (для редактора). У обоих из них есть фильтр image_editor_save_pre, передающий ему экземпляр редактора изображений. Таким образом, вы можете использовать это для изменения изображения любым удобным вам способом, включая настройку качества.

Итак, что-то вроде этого должно делать работу просто и легко:

add_filter('image_editor_save_pre','example_adjust_quality');
function example_adjust_quality($image) {
    $size = $image->get_size();
    // Values are $size['width'] and $size['height']. Based on those, do what you like. Example:
    if ( $size['width'] <= 100 ) {
        $image->set_quality(30);
    }
    if ( $size['width'] > 100 && $size['width'] <= 300 ) {
        $image->set_quality(70);
    }
    if ( $size['width'] > 300 ) {
        $image->set_quality(80);
    }
    return $image;
}
эфирное масло
источник
Причина, по которой я не использовал нечто столь прямолинейное, как это (+1), заключается в том, что я смутно помню, что при редактировании какого-либо изображения (вращение, обрезка и т. Д.) Каждое действие вызывалось дважды, что в два раза снижает качество. Тем не менее, часть «является экземпляром WP_Image_Editor» является гораздо большим решением, чем то, что я написал.
Кайзер
1
Качество - это точное значение, а не процент. Вы можете установить и сбросить все, что вам нравится, пока он не сохранится. Установка в 10 сотен раз оставляет в 10.
Отто
Я предполагал, что это сэкономит между ними. Спасибо за внимание.
Кайзер
Мне кажется, что image_editor_save_preне позвонили. Когда я пытаюсь вывести материал, используя error_log(что определенно работает), я ничего не получаю. : /
Нильс Ридеманн
1
Регенерация тоже может работать, если она восстанавливает изображение. Никакой код не изменит существующие файлы в системе, если вы не предпримете действия для их перезагрузки и повторного сохранения.
Отто
5

Примечание заранее: приведенный ниже ответ не закончен и не проверен, но у меня недостаточно времени, поэтому я оставлю это здесь как черновик. То, что, вероятно, нуждается во второй паре глаз, является качественным методом и интерпретацией version_compare().

Сначала нам нужна точка входа. После повторного прочтения поста make я подумал, что лучше всего подключиться, прежде чем редактор изображений сохранит вновь созданное изображение. Итак, вот микроконтроллер, который перехватывает во время обратного вызова, подключенного к нему, image_editor_save_preи загружает класс, который затем просматривает ваши настройки, определенные внутри обратного вызова wpse_jpeg_quality. Он просто возвращает разные коэффициенты сжатия для jpeg_qualityфильтра, который работает внутри редактора изображений.

<?php

namespace WPSE;

/**
 * Plugin Name: (#138751) JPEG Quality Router
 * Author:      Franz Josef Kaiser
 * Author URI:  http://unserkaiser.com
 * License:     CC-BY-SA 2.5
 */

add_filter( 'image_editor_save_pre', 'WPSE\JPEGQualityController', 20, 2 );
/**
 * @param string $image
 * @param int $post_id
 * @return string
 */
function JPEGQualityController( $image, $post_id )
{
    $config = apply_filters( 'wpse_jpeg_quality', array(
        # Valid: <, lt, <=, le, >, gt, >=, ge, ==, =, eq
        'limit'      => 'gt',
        # Valid: h, w
        'reference'  => 'w',
        'breakpoint' => 50,

        'low'        => 80,
        'high'       => 100,
    ) );
    include_once plugin_dir_path( __FILE__ ).'worker.php';
    new \WPSE\JPEGQualityWorker( $image, $config );

    return $image;
}

Фактический рабочий JPEGQualityWorkerкласс. Он находится в том же каталоге, что и указанный выше основной файл плагина, и имеет имя worker.php(или смените контроллер выше).

Он извлекает изображение и ваши настройки, а затем добавляет обратные вызовы в jpeg_qualityфильтр. Что делает это

  • получение ссылки на изображение (ширина или высота)
  • ставить под сомнение вашу точку останова, которая решает, где переключаться между низким и высоким качеством / коэффициентом сжатия
  • получение исходного размера изображения
  • решая, какое качество вернуть

Точка останова и предел - это то, что определяет между высоким и низким, и, как упоминалось выше, это может потребовать больше любви.

<?php

namespace WPSE;

/**
 * Class JPEGQualityWorker
 * @package WPSE
 */
class JPEGQualityWorker
{
    protected $config, $image;
    /**
     * @param string $image
     * @param array $config
     */
    public function __construct( Array $config, $image )
    {
        $this->config = $config;
        $this->image  = $image;

        add_filter( 'jpeg_quality', array( $this, 'setQuality' ), 20, 2 );
    }

    /**
     * Return the JPEG compression ratio.
     *
     * Avoids running in multiple context, as WP runs the function multiple
     * times per resize/upload/edit task, which leads to over compressed images.
     *
     * @param int $compression
     * @param string $context Context: edit_image/image_resize/wp_crop_image
     * @return int
     */
    public function setQuality( $compression, $context )
    {
        if ( in_array( $context, array(
            'edit_image',
            'wp_crop_image',
        ) ) )
            return 100;

        $c = $this->getCompression( $this->config, $this->image );

        return ! is_wp_error( $c )
            ? $c
            : 100;
    }

    /**
     * @param array $config
     * @param string $image
     * @return int|string|\WP_Error
     */
    public function getCompression( Array $config, $image )
    {
        $reference = $this->getReference( $config );
        if ( is_wp_error( $reference ) )
            return $reference;
        $size = $this->getOriginalSize( $image, $reference );
        if ( is_wp_error( $size ) )
            return $size;

        return $this->getQuality( $config, $size );
    }

    /**
     * Returns the quality set for the current image size.
     * If
     * @param array $config
     * @param int $size
     */
    protected function getQuality( Array $config, $size )
    {
        $result = version_compare( $config['breakpoint'], $size );
        return (
            0 === $result
            AND in_array( $config['limit'], array( '>', 'gt', '>=', 'ge', '==', '=', 'eq' ) )
            ||
            1 === $result
            AND in_array( $config['limit'], array( '<', 'lt', '<=', 'le', ) )
        )
            ? $config['high']
            : $config['low'];
    }

    /**
     * Returns the reference size (width or height).
     *
     * @param array $config
     * @return string|\WP_Error
     */
    protected function getReference( Array $config )
    {
        $r = $config['reference'];
        return ! in_array( $r, array( 'w', 'h', ) )
            ? new \WP_Error(
                'wrong-arg',
                sprintf( 'Wrong argument for "reference" in %s', __METHOD__ )
            )
            : $r;
    }

    /**
     * Returns the size of the original image (width or height)
     * depending on the reference.
     *
     * @param string $image
     * @param string $reference
     * @return int|\WP_Error
     */
    protected function getOriginalSize( $image, $reference )
    {
        $size = 'h' === $reference
            ? imagesy( $image )
            : imagesx( $image );

        # @TODO Maybe check is_resource() to see if we got an image
        # @TODO Maybe check get_resource_type() for a valid image
        # @link http://www.php.net/manual/en/resource.php

        return ! $size
            ? new \WP_Error(
                'image-failure',
                sprintf( 'Resource failed in %s', get_class( $this ) )
            )
            : $size;
    }
}
кайзер
источник
Все еще работаю над этим? Насколько я понимаю, я бы хотел видеть это как плагин.
Нильс Ридеманн
Извините, но нет, я не. Я бы тоже хотел видеть это как плагин, но так как в данный момент он мне не нужен и у меня нет времени, этого пока не произойдет. Может быть, дать ему шанс, посмотреть, как далеко вы получите и подать редактирование или отдельный ответ? :)
kaiser
Кайзер: Я думаю, ты это слишком усложнил. Изображение $, отправленное на image_editor_save_pre, является экземпляром класса WP_Image_Editor. Он имеет функции, чтобы получить размер и установить качество и все остальное уже в нем. Все, что вам нужно сделать, это позвонить им.
Отто