wake-up-neo.com

Erstellen Sie beim Hochladen Bildformate mit unterschiedlichen Qualitäten

Ich versuche, eine Lösung zu finden, bei der die generierten Bildformate sowohl reaktionsschnelle als auch hochauflösende Aspekte beim Hochladen eines neuen Elements im Admin-Bereich von WP berücksichtigen. Ich habe eine Reihe von Formaten zusammengestellt, die diese Anforderungen erfüllen sollten,

Retina-Desktop 2560 x 1600 ('largex2', benutzerdefiniert)
1280 x 800 Desktop (groß)
1920 x 1200 Retina-Tablette ("mediumx2", benutzerdefiniert)
960 x 600 Tablette + Retina Mobile (mittel)
480 x 300 Handy (Miniaturansicht)

Mein Problem liegt in der Bildqualität für die größeren Formate. Wenn Sie die Bilder aus Photoshop mit einer hohen oder sehr hohen Qualitätseinstellung exportieren, werden für die Standardgrößen faire Ergebnisse erzielt. Wie steht es jedoch mit den benutzerdefinierten Größen? Die exportiere ich lieber bei mittlerer oder niedriger Einstellung, um eine vernünftige Dateigröße zu erhalten.

Mein Gedanke ist - wäre es möglich, ein wirklich großes Bild mit hoher Qualität aufzunehmen, es hochzuladen und dann so einzustellen, dass die größeren Größen mit einer viel geringeren Qualität erzeugt werden?

Jede Hilfe wird geschätzt! Bitte leiten Sie mich nicht an irgendwelche Plugins weiter, ich möchte dafür meine eigene Lösung erstellen.

5
Staffan Estberg

1) Eine Problemumgehung durch Erweitern der Klasse WP_Image_Editor_Gd

Das Problem ist, wie Sie auf die Bildgrößen zugreifen können, bevor Sie die Qualität von Zwischenbildern und JPEG-Bildern ändern.

Beachten Sie, dass die Funktion image_resize()veraltet ist .

Wir können den jpeg_quality-Filter aus der öffentlichen get_quality-Methode der abstrakten WP_Image_Editor-Klasse verwenden:

$quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' );

oder der wp_editor_set_quality filter.

Hier ist eine Idee, wie Sie die Bildqualität basierend auf der Bildgröße (Breite/Höhe) einstellen können:

/**
 * Set image (jpeg) quality based on the image size (width/height)
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wpse_make_image_arguments', function( $arguments, $filename, $size, $function ) 
{   
    // Only target jpeg cases, i.e. with the quality set in $arguments[2]       
    if( ! isset( $size['height'] ) || ! isset( $size['width'] ) || ! isset( $arguments[2] ) )
        return $arguments;

    // Modify this part to your needs:
    if( $size['height'] <= 150  && $size['width'] <= 150 )
        $arguments[2] = 2; // very low quality for easy testing

    return $arguments;
}, 10, 4 );

wo wir die Klasse WP_Image_Editor_Gd erweitert haben:

/**
 * Extend the WP_Image_Editor_Gd to add the custom wpse_make_image_arguments filter.
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wp_image_editors', function( $editors ) 
{
    // Note that the WP_Image_Editor_Gd and WP_Image_Editor_Imagick classes
    // are included within this filter. So let's do the same for our extended class.

    // Our extended class that overrides the WP_Image_Editor_Gd::make_image() method

    if( ! class_exists( 'WPSE_Image_Editor_Gd' ) )
    {   
        class WPSE_Image_Editor_Gd extends WP_Image_Editor_Gd
        {
            protected function make_image( $filename, $function, $arguments ) 
            {
                // Add a custom filter      
                $arguments = apply_filters( 'wpse_make_image_arguments', $arguments, $filename, $this->size, $function );

                // Parent method
                return parent::make_image( $filename, $function, $arguments );
            }
        }
    }

    // Prepend the extended class to the array of image editors:    
    array_unshift( $editors, 'WPSE_Image_Editor_Gd' );

    return $editors;
} );

hier haben wir den benutzerdefinierten wpse_make_image_arguments-Filter eingeführt.

Auf diese Weise können wir die Qualitätseinstellungen ändern , bevor die Zwischendateien gespeichert werden.

Hier ist ein Beispiel:

Example

PS: Ich habe den Fall nicht überprüft, als stattdessen die Imagick Bibliothek verwendet wurde, aber ich denke, wir könnten etwas Ähnliches tun, indem wir den WP_Image_Editor_Imagick erweitern. Klasse.

2) Update - Legen Sie die JPEG-Qualität für den Namen der Bildgröße fest

Hier ist eine andere Version, in der wir die JPEG-Qualität für den Namen der Bildgröße festlegen:

/**
 * Extend the WP_Image_Editor_Gd to set quality per image size name.
 * 
 * @see http://wordpress.stackexchange.com/a/165241/26350
 */
add_filter( 'wp_image_editors', function( $editors ) 
{
    // Note that the WP_Image_Editor_Gd and WP_Image_Editor_Imagick classes
    // are included within this filter. So let's do the same for our extended class.

    // Our extended class that overrides the WP_Image_Editor_Gd::_resize() method
    if( ! class_exists( 'WPSE2_Image_Editor_Gd' ) )
    {   
        class WPSE2_Image_Editor_Gd extends WP_Image_Editor_Gd
        {
            protected function _resize( $max_w, $max_h, $crop = false )
            {
                $qualities = apply_filters( 'wpse_jpeg_qualities', [] );
                $default_quality = (int) apply_filters( 'wpse_default_jpeg_quality', 82 );                              
                $sizes = wp_get_additional_image_sizes();
                $this->set_quality( $default_quality );         
                foreach( (array) $qualities as $name => $quality )
                {
                    if( 
                        isset( $sizes[$name] ) 
                        && (int)  $sizes[$name]['width']  === (int)  $max_w
                        && (int)  $sizes[$name]['height'] === (int)  $max_h
                        && (bool) $sizes[$name]['crop']   === (bool) $crop  
                    )   
                        $this->set_quality( $quality );                 
                }

                // Parent method
                return parent::_resize( $max_w, $max_h, $crop );
            }
        }
    }

    // Prepend the extended class to the array of image editors:    
    array_unshift( $editors, 'WPSE2_Image_Editor_Gd' );

    return $editors;
} );

Mir ist aufgefallen, dass die crop-Argumente 0, falsch oder leer sein können, daher führen wir zur Sicherheit eine Typumwandlung durch.

Hier haben wir die folgenden neuen Filter eingeführt:

add_filter( 'wpse_jpeg_qualities', function( $qualities )
{ 
    return [ 'hello-image' => 2, 'medium' => 2, 'large' => 2 ];
} );

und

add_filter( 'wpse_default_jpeg_quality', function( $quality )
{ 
    return 82;
} );

das kann hoffentlich an deine bedürfnisse angepasst werden!

6
birgire

Kann nicht kommentieren, muss zusammen mit einer anderen Version gepostet werden.

Die Probleme):

Ich bin mir nicht sicher, ob das Update 2) JPEG-Qualität pro Bildgröße festlegen Name in der akzeptierten Antwort vollständig ist. wp_get_additional_image_sizes() gibt den global $_wp_additional_image_sizes zurück und enthält keine Informationen zu Standardgrößen als mittelgroß, groß oder als Miniaturansicht.

Dies funktioniert im Filter möglicherweise nicht: 'large' => 2

Ab https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes wird mit benutzerdefiniertem Code erläutert, um ALLE Größen mit einer benutzerdefinierten Funktion abzurufen.

Habe ich recht?

Zweitens ist die Idee, verschiedene "Größen" nach Namen zu filtern, schwierig. _resize( $max_w, $max_h, $crop = false ) versteht und analysiert nur die Werte für Breite, Höhe und Beschnitt, und für jede Übereinstimmung wird angenommen , dass sie einem Namen entspricht. Aber in vielen Fällen wird der Name "ein anderer" Name sein.

Eine "mittlere" Bildeinstellung mit der gleichen "shop_product" -Einstellung "besucht" diese Funktion nur als eine von ihnen. Dann wissen wir nicht, ob es sich um eine "mittlere" Größe oder eine "shop_product" Größe handelt, die gefiltert wird. Denn das Ziel ist hier nur ein technischer Ausschnitt eines Bildes.

Die Idee mit Update 2) ist logischer, aber ich befürchte, dass die technische Architektur nicht vorhanden ist. Das Analysieren aller registrierten Bildgrößen vor dem Erstellen des Filters wird weiterentwickelt, um sicherzustellen, dass das Bildprogramm mit der richtigen Qualität für das aktuelle Thema zurückgegeben wird.

Alle Größenbezeichnungen mit gleichen Einstellungen haben dieselbe neue Qualität wie das gleiche Bild auf dem Server.

Also, wenn Sie sich immer noch an das Update halten 2) Ich denke, Sie müssen eine andere Funktion aufrufen, um die Variable $sizes zu füllen, und durch var_dump () den $_wp_additional_image_sizes auf gleiche Einstellungen analysieren.

Der Ansatz in 1) Ein Workaround durch ... ist logischer/semantischer. Wir haben dies mit der gleichen Erweiterungsmethode gelöst, aber stattdessen mit einem dynamischen Filter:

add_filter('wp_image_editors', function($editors){

    if(!class_exists('ENTEX_Image_Editor_Gd')){   
        class ENTEX_Image_Editor_Gd extends WP_Image_Editor_Gd {
            private $wp_quality = null;
            protected function _resize($max_w, $max_h, $crop = false){
                $condition = ($crop ? 'true' : 'false');
                if($this->wp_quality === null) $this->wp_quality = $this->get_quality();
                $quality = apply_filters('wp_editor_set_quality_'. $max_w .'x'. $max_h .'_'. $condition, $this->wp_quality);                              
                $this->set_quality((int) $quality);
                return parent::_resize( $max_w, $max_h, $crop );
            }
        }
    }    
    array_unshift($editors, 'ENTEX_Image_Editor_Gd');
    return $editors;
});

Um jede einzelne Bildgröße zu filtern, verwenden wir dann:

add_filter('wp_editor_set_quality_160x160_true', function($quality){
    return 96;
});

Was sich auch von dieser erweiterten Version unterscheidet, ist, dass wir die add_filter('jpeg_quality' ...-Version als Standardwert verwenden/ausfüllen.

Hier sind einige andere Beispiele für benutzerdefinierte Filter:

function high_quality_on_medium_images(){
    $in = 'medium';
    $max_w = get_option($in.'_size_w');
    $max_h = get_option($in.'_size_h');
    $crop = get_option($in.'_crop');
    $condition = ($crop ? 'true' : 'false');
    add_filter('wp_editor_set_quality_'. $max_w .'x'. $max_h .'_'. $condition, 'my_theme_high_quality_images', 10, 1);
}
add_action('after_setup_theme', 'high_quality_on_medium_images', 99);

function my_theme_high_quality_images($quality){
    return (int) 82;
}

Entwickler Aufmerksamkeit

  • Stellen Sie sicher, dass die Filter nach dem Einrichten der Themenbilder angewendet werden.
  • Nicht in is_admin() wickeln, dann Ajax-Aufruf, Front-End, entfernt
    gepostete Bilder werden nicht beißen.

Wie bereits erwähnt, kann der Zuschneidewert entweder 0 oder false sein. Sie müssen (int) oder (bool) in einen String mit $condition = ($crop ? 'true' : 'false'); konvertieren.

Theme Entwickler Aufmerksamkeit

Die WP Standardkomprimierung ist ziemlich progressiv. Werte zwischen 80 und 99 können einen großen Unterschied oder ergeben, bei dem überhaupt kein Ergebnis sichtbar ist. Ein Wert ohne Komprimierung als 100 gibt wahrscheinlich eine größere Dateigröße bei "kleineren" 800 px Bildern dann die original große 3000 px Version.

Nach vielen Jahren haben wir eine magische Zahl von 96 gefunden, die Dateigröße wird kleiner, aber man kann den Unterschied zwischen einer 100-Wert-Komprimierung nicht erkennen.

Hochwertige, in Photoshop vorbereitete Shop-Bilder, die größer als 800 Pixel sind, sind in Wordpress-Standardeinstellung 82 in Ordnung. Für "große" E-Mail-Bilder auf dem iPhone ist jedoch ein Wert von 96 für KLEINE Größen wie Miniaturansichten erforderlich. Sie werden bei Wordpres-Komprimierungen zu "weichen Unschärfen".

Sie werden mit diesem Thema Lösungen zu viel tun, wenn Sie die Szenarien für Ihr Projekt, Benutzer oder Thema nicht planen.

Eine letzte Überlegung

Ich bin bei Wordpress wirklich enttäuscht, dass dieses wichtige Thema in der Priorität der Entwicklung vernachlässigt wird, da Bilder mehr denn je wichtig sind, um bei Belastung einzigartig effektiv zu sein.

Können wir nicht einfach einen Filter an der richtigen Stelle finden, der für die individuelle Komprimierung verwendet werden kann? Sie machen sich die Mühe, "den Namen zu ändern" in wp_editor_set_quality, und add_filter('jpeg_quality' ... ist jetzt veraltet. Warum denken Sie nicht, dass dies vollständig durchgedacht ist und entfernen Sie einfach die Methode if ( ! $this->quality ) only once, wie von @birgire erwähnt.

0
Jonas Lundman