Qualità dell'immagine basata sulla dimensione dell'immagine


15

È possibile impostare la qualità dell'immagine in base alla dimensione dell'immagine? Mi piacerebbe avere una migliore qualità dell'immagine per immagini più grandi (80) - e peggio per le miniature piccole (30).

Mi aspettavo un parametro add_sizeper controllarlo, ma non ce n'è.

Se è importante: sto usando ImageMagick.

Risposte:


15

L'unica volta che l'impostazione della qualità conta davvero è prima che l'immagine venga salvata o trasmessa in streaming (per l'editor). Entrambi hanno il filtro "image_editor_save_pre" lì, passandogli l'istanza dell'editor di immagini. Quindi puoi usarlo per modificare l'immagine nel modo che preferisci, inclusa l'impostazione della qualità.

Quindi, qualcosa del genere dovrebbe fare il lavoro in modo semplice e facile:

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

Motivo per cui non ho usato qualcosa di dritto come questo (+1), che ricordo vagamente che durante la modifica di un'immagine (rotazione, ritaglio, ecc.), Ogni azione veniva chiamata due volte, riducendo la qualità due volte. Tuttavia la parte "è un'istanza di WP_Image_Editor" è una soluzione molto più di quella che ho scritto.
— Kaiser

1
La qualità è un valore esatto, non una percentuale. È possibile impostare e ripristinare tutto ciò che vuoi, fino a quando non salva. Impostandolo su 10 cento volte lo lascia a 10.
— Otto

Ho pensato che avrebbe risparmiato nel mezzo. Grazie per il testa a testa.
— Kaiser

Mi sembra che image_editor_save_prenon venga chiamato. Quando provo a produrre roba usando error_log(che sicuramente funziona) non ottengo alcun output. : /
— Nils Riedemann il

1
Anche la rigenerazione potrebbe funzionare se ripristina l'immagine. Nessun codice cambierà i file esistenti sul sistema senza che tu effettivamente esegua l'azione per ricaricarli e salvarli di nuovo.
— Otto

5

Nota in anticipo: la risposta di seguito non è terminata e non è stata testata, ma non mi rimane abbastanza tempo, quindi lascerò questo qui come bozza. Ciò che probabilmente ha bisogno di un secondo paio di occhi è il metodo di qualità e l'interpretazione di version_compare().

Per prima cosa abbiamo bisogno di un punto di accesso. Dopo aver letto di nuovo il post di make , ho pensato che sarebbe stato meglio saltare prima che Image Editor salvasse l'immagine appena creata. Quindi ecco un microcontrollore che intercetta durante un callback collegato image_editor_save_pree carica una classe che quindi passa attraverso le impostazioni definite all'interno di un callback a wpse_jpeg_quality. Restituisce semplicemente diversi rapporti di compressione per il jpeg_qualityfiltro che viene eseguito all'interno dell'editor di immagini.

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

Il vero lavoratore è la JPEGQualityWorkerclasse. Risiede nella stessa directory del file del plug-in principale sopra ed è chiamato worker.php(o si cambia il controller sopra).

Recupera l'immagine e le impostazioni e quindi aggiunge le richiamate al jpeg_qualityfiltro. Quello che fa è

  • recupero del riferimento dell'immagine (larghezza o altezza)
  • mettere in discussione il tuo punto di interruzione che decide dove passare tra il rapporto qualità / compressione basso e alto
  • recupero della dimensione originale dell'immagine
  • decidere quale qualità restituire

Il punto di interruzione e il limite è ciò che decide tra alto e basso e, come detto sopra, potrebbe essere necessario un po 'più di amore.

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

Ci sto ancora lavorando? Per quanto mi riguarda, mi piacerebbe vederlo come un plugin.
— Nils Riedemann,

Scusa, ma no, non lo sono. Mi piacerebbe vederlo anche come plugin, ma poiché al momento non ne ho bisogno e non ho tempo, non succederà finora. Forse provaci, vedi quanto lontano arrivi e invia una modifica o una risposta separata? :)
— Kaiser

Kaiser: L'hai complicato troppo, penso. $ Image inviata a image_editor_save_pre è un'istanza della classe WP_Image_Editor. Ha funzioni per ottenere le dimensioni e impostare la qualità e tutto il resto già presente. Tutto quello che devi fare è chiamarli.
— Otto
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.