Ändern der JPEG-Komprimierung je nach Bildgröße

8

Kurz. Ich möchte, dass "große" Bilder um 90% und "mittlere" um 60% komprimiert werden. Hat viele af Sie wissen, manchmal leiden größere Bilder unter hoher Komprimierung, andere kleine Bilder jedoch nicht.

Mit dieser Funktion können Sie alle JPG-Bilder neu abtasten

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

Wie filtere ich nach Bildgröße?

DarkGhostHunter
quelle

Antworten:

11

Ein ganz besonderer Filter

Der jpeg_qualityFilter ist ein ganz besonderer: Er wird in drei verschiedenen Fällen verwendet und Sie müssen das zweite Argument verwenden, um zu bestimmen, ob Sie den Filter verwenden möchten oder nicht.

Lass es nicht alles machen

Das Hauptproblem für einen solchen speziellen Filter besteht darin, dass er möglicherweise für spätere Aktionen ausgelöst wird, wenn Sie ihn nicht entfernen. Lassen Sie ihn nach der ersten Überprüfung laufen. Wir müssen also einen weiteren Filter einbauen wp_save_image_file(), um zu überprüfen, ob wir die Komprimierung ändern möchten oder nicht. Um es für einen anderen Speichervorgang zu deaktivieren, entfernen wir es unmittelbar vor dem Ändern der Komprimierung.

Das coole Kind

Das wirklich Seltsame ist, dass WP für jeden Speichervorgang eine Standardkomprimierung von 90% (was einer um 10% reduzierten Qualität entspricht) verwendet. Dies bedeutet, dass Sie jedes Mal, wenn Sie ein Bild hochladen / zuschneiden / bearbeiten, dessen Qualität verringern. Dies ist ein Schmerz für Bilder, die beim Hochladen nicht die besten sind (testen Sie es mit einem Bild, das viel Rot enthält mit kontrastreichem Hintergrund). Aber ... Das wirklich nette ist, dass Sie dieses Verhalten ändern können. Sie möchten also die Komprimierung ändern, aber gleichzeitig eine höhere Qualität erzielen - viel besser als es der Kern zulässt.

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

EDIT: Nach einer kurzen Diskussion mit @toscho wies er darauf hin, dass der gesamte Rückruf auf Folgendes reduziert werden könne:

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

Da ich den Code aus einem Plugin gezogen habe, an dem ich gerade arbeite, musste ich die switchEinstellungen hinzufügen. Ich muss auch beachten, dass ich den globalin meinem Plugin nicht verwende , da es sich um einen OOP-Ansatz handelt. Der Code, den Sie oben ↑ lesen können, ist hauptsächlich reduzierter und geänderter Code aus dem Plugin, der einige kleinere Reste enthält und für spätere Leser erklärend sein soll und immer noch funktioniert. Wenn Sie es als Plugin verwenden möchten, können Sie je nach Ihrem persönlichen Anwendungsfall einige Optimierungen vornehmen.


Anmerkungen:

Bei einigen Untersuchungen zu den verschiedenen Aufgaben habe ich festgestellt, dass $casebei den folgenden Schritten mehrere s ausgelöst werden:

  • Drehen: edit-image» image-resize(das spätere 1 × für jede von Ihnen gewählte Größe - Miniaturbild usw.)
  • Spiegel: edit-image» image-resize(-" -)

Dies bedeutet, dass der Filterrückruf für jpeq_quality2 × zum Drehen / Spiegeln eines Bildes und + 1 × für jede zusätzliche Größe, die Sie hinzufügen, ausgelöst wird. Wenn Sie also weniger als 100% erhalten, wird die Qualität zweimal reduziert. Ich habe viel zu diesem Thema recherchiert, bin mir aber immer noch nicht ganz sicher, welche genauen Funktionen dieses Verhalten verursachen.

Kaiser
quelle
Ups du hast mich, print_r / var_dump funktioniert nicht. Wie kann ich das ausgeben?
DarkGhostHunter
Verwenden Sie echo '<pre>'.var_export( $image, true ).'</pre>';. Setzen Sie ein exit;nach, damit es nicht mit dem erneuten Laden der Seite usw. übersprungen wird
Kaiser
Verdammt, im Wald verloren - ich kann nicht sehen, wo es druckt. Ich habe diesen Code vor der Rückgabe $ image;
DarkGhostHunter
Fügen Sie es direkt am Anfang der wpse58600_custom_jpg_compression()Funktion hinzu.
Kaiser
1
Lassen Sie uns diese Diskussion im Chat fortsetzen
DarkGhostHunter