Automatické doostření obrázků ve WordPressu

Jak jistě víte, WordPress vytváří různé náhledové velikosti obrázků, které se pak používají pro zobrazení na různých místech webu tak, aby se obrázky nenačítaly zbytečně velké pokud to není potřeba. Pro generování obrázků používá WP buďte knihovnu GD Image, nebo v lepším případě knihovnu Imagick – pro tu musí být na serveru zapnuta podpora, ale většina i sdílených hostingů knihovnu podporuje.

Při generování náhledových obrázků ale dojde ke ztrátě kvality – patrné to je především u zmenšování velkých obrázků na malé velikosti.

Existuje způsob, jak zajistit, aby byly obrázky zmenšené kvalitnější, a to doostření obrázku po zmenšení. Dá se to zařídit pomocí výměny implementace Imagick Editoru. Následující metoda thumbnail_image je víceméně kopií originální implementace, kde jsem vyměnil metodu unsharpMaskImage za sharpenImage.

<?php

namespace WPP;

use Imagick;
use WP_Image_Editor_Imagick;

class Editor extends WP_Image_Editor_Imagick{
    protected function thumbnail_image( $dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true ) {
        $allowed_filters = array(
            'FILTER_POINT',
            'FILTER_BOX',
            'FILTER_TRIANGLE',
            'FILTER_HERMITE',
            'FILTER_HANNING',
            'FILTER_HAMMING',
            'FILTER_BLACKMAN',
            'FILTER_GAUSSIAN',
            'FILTER_QUADRATIC',
            'FILTER_CUBIC',
            'FILTER_CATROM',
            'FILTER_MITCHELL',
            'FILTER_LANCZOS',
            'FILTER_BESSEL',
            'FILTER_SINC',
        );

        /**
         * Set the filter value if '$filter_name' name is in the allowed list and the related
         * Imagick constant is defined or fall back to the default filter.
         */
        if ( in_array( $filter_name, $allowed_filters, true ) && defined( 'Imagick::' . $filter_name ) ) {
            $filter = constant( 'Imagick::' . $filter_name );
        } else {
            $filter = defined( 'Imagick::FILTER_TRIANGLE' ) ? Imagick::FILTER_LANCZOS : false;
        }

        //$filter = \Imagick::FILTER_LANCZOS;

        /**
         * Filters whether to strip metadata from images when they're resized.
         *
         * This filter only applies when resizing using the Imagick editor since GD
         * always strips profiles by default.
         *
         * @since 4.5.0
         *
         * @param bool $strip_meta Whether to strip image metadata during resizing. Default true.
         */
        if ( apply_filters( 'image_strip_meta', $strip_meta ) ) {
            $this->strip_meta(); // Fail silently if not supported.
        }

        try {
            /*
             * To be more efficient, resample large images to 5x the destination size before resizing
             * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
             * unless we would be resampling to a scale smaller than 128x128.
             */
            if ( is_callable( array( $this->image, 'sampleImage' ) ) ) {
                $resize_ratio  = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
                $sample_factor = 5;

                if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
                    $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
                }
            }

            /*
             * Use resizeImage() when it's available and a valid filter value is set.
             * Otherwise, fall back to the scaleImage() method for resizing, which
             * results in better image quality over resizeImage() with default filter
             * settings and retains backward compatibility with pre 4.5 functionality.
             */
            if ( is_callable( array( $this->image, 'resizeImage' ) ) && $filter ) {
                $this->image->setOption( 'filter:support', '2.0' );
                $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 );
            } else {
                $this->image->scaleImage( $dst_w, $dst_h );
            }

            // Set appropriate quality settings after resizing.
            if ( 'image/jpeg' === $this->mime_type ) {
                if ( is_callable( array( $this->image, 'unsharpMaskImage' ) ) ) {
                    //$this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 );
                    $this->image->sharpenImage(0, 1.2);
                }

                //$this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
            }

            if ( 'image/png' === $this->mime_type ) {
                $this->image->setOption( 'png:compression-filter', '5' );
                $this->image->setOption( 'png:compression-level', '9' );
                $this->image->setOption( 'png:compression-strategy', '1' );
                $this->image->setOption( 'png:exclude-chunk', 'all' );
            }

            /*
             * If alpha channel is not defined, set it opaque.
             *
             * Note that Imagick::getImageAlphaChannel() is only available if Imagick
             * has been compiled against ImageMagick version 6.4.0 or newer.
             */
            if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) )
                 && is_callable( array( $this->image, 'setImageAlphaChannel' ) )
                 && defined( 'Imagick::ALPHACHANNEL_UNDEFINED' )
                 && defined( 'Imagick::ALPHACHANNEL_OPAQUE' )
            ) {
                if ( $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) {
                    $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE );
                }
            }

            // Limit the bit depth of resized images to 8 bits per channel.
            if ( is_callable( array( $this->image, 'getImageDepth' ) ) && is_callable( array( $this->image, 'setImageDepth' ) ) ) {
                if ( 8 < $this->image->getImageDepth() ) {
                    $this->image->setImageDepth( 8 );
                }
            }

            if ( is_callable( array( $this->image, 'setInterlaceScheme' ) ) && defined( 'Imagick::INTERLACE_NO' ) ) {
                $this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
            }
        } catch ( Exception $e ) {
            return new WP_Error( 'image_resize_error', $e->getMessage() );
        }
    }
}

Pak stačí nový editor zaregistrovat:

add_filter('wp_image_editors', [$this,'image_editors'], 10000);

public function image_editors(  ) {
        require_once(__DIR__ . '/class.editor.php');
        return array('\WPP\Editor');
    }

Výsledek je: původní obrázek / doostřený obrázek

Pokud potřebujete pomoci s obrázky ve WordPressu nebo s vytvořením pluginu na WordPress a WooCommerce, neváhejte se na mě obrátit.

Přidat komentář