Якість зображення залежно від розміру зображення


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().

Спочатку нам потрібна точка входу. Прочитавши ще раз повідомлення про посту , я подумав, що найкраще буде зайти до того, як редактор зображень збереже новостворене зображення. Отже, ось мікроконтролер, який перехоплює під час зворотного дзвінка підключений 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;
    }
}

Ще над цим працюєте? Що стосується мене, я хотів би бачити це як плагін.
Нілс Рідеманн

Вибачте, але ні, ні. Я також хотів би бачити це як плагін, але, як на даний момент він мені не потрібен і не маю часу, це не відбудеться поки що. Може, сфотографуйте, подивіться, як далеко ви дістаєте і подайте редагування чи окрему відповідь? :)
кайзер

кайзер: Ви думаєте, що ви це ускладнювали. Зображення $, надіслане image_editor_save_pre, є екземпляром класу WP_Image_Editor. Він має функції для отримання розміру і встановлення якості та всього іншого, що вже є в ньому. Все, що вам потрібно зробити - це зателефонувати їм.
Отто
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.