web-dev-qa-db-ja.com

アップロード時に異なる品質の画像フォーマットを作成する

私はWP adminで新しいアイテムをアップロードするときに生成された画像フォーマットが応答と高解像度の側面の両方をカバーする解決策を思い付くことを試みています。これらの要件を満たすべき一連のフォーマットをまとめました。

2560 x 1600の網膜デスクトップ( 'largex2'、カスタム)
1280 x 800デスクトップ(大)
1920 x 1200網膜タブレット( '中x 2'、カスタム)
960 x 600タブレット+網膜モバイル(中)
480×300モバイル(サムネイル)

私の問題は大きいサイズの画質にあります。高または高の品質設定でPhotoshopから画像をエクスポートすると、デフォルトのサイズでは適切な結果が得られますが、カスタムサイズについてはどうでしょうか。合理的なファイルサイズを維持するために、中または低の設定でエクスポートしたいと思います。

私の考えは、高品質で本当に大きな画像を1枚撮り、それをアップロードしてから、より大きなサイズがはるかに低い品質で生成されるように設定することは可能でしょうか。

任意の助けは大歓迎です!どのプラグインにも誘導しないでください。このための独自のソリューションを構築したいのです。

5
Staffan Estberg

1)WP_Image_Editor_Gdクラスを拡張することによる回避策

問題は、中間JPEG画像の品質を変更する前に画像サイズにアクセスする方法です。

image_resize() 関数は 非推奨 であることに注意してください。

抽象jpeg_qualityクラスのpublic get_qualityメソッドからWP_Image_Editorフィルタを使うことができます。

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

またはwp_editor_set_qualityフィルタ。

画像サイズ(幅/高さ)に基づいて画質を設定する方法の1つのアイデアがあります。

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

WP_Image_Editor_Gdクラスを拡張したところです。

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

カスタムのwpse_make_image_argumentsフィルタを紹介しました。

このようにして、品質設定を変更することができます、の前に中間ファイルが保存されます。

これが例です:

Example

PS:代わりにImagickライブラリを使った場合のケースをチェックしませんでしたが、WP_Image_Editor_Imagickを拡張することで同様のことができると思いますクラス。

2)更新 - 画像サイズ名ごとにJPEG品質を設定

これは画像サイズごとのjpeg品質を設定する別のバージョンです。

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

クロップ引数は0、false、または空になる可能性があることに気付いたので、確実にするために型キャストを行います。

ここでは、以下の新しいフィルタを紹介しました。

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

そして

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

うまくいけばあなたのニーズに合わせて調整することができます!

6
birgire

カントコメント、別のバージョンと一緒に投稿する必要があります。

問題点):

受け入れられた答えの更新2)画像サイズ名あたりのJPEG品質の設定が完了しているかどうかはわからない。 wp_get_additional_image_sizes()global $_wp_additional_image_sizesを返し、中、大、サムネイルなどのデフォルトサイズに関する情報は含まれていません。

これはフィルタでは動作しないかもしれません: 'large' => 2

https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes 以降は、カスタム関数ですべてのサイズを取得するためのカスタムコードで説明します。

私は正しいですか?

第二に、名前によるフィルタの異なる「サイズ」の考え方は難しいです。 _resize( $max_w, $max_h, $crop = false )は、一致した幅、高さ、トリミング値のみを理解し、解析します。そして、すべての一致は名前に一致すると仮定します。しかし多くの場合、名前は「別の」名前になります。

「shop_product」設定が等しい「中」画像設定は、そのうちの1つとしてこの機能を「訪問」するだけです。それから私達はそれが "ミディアム"サイズか "shop_product"サイズがフィルタリングされているかどうか知りません。なぜなら、ここでの目的は単なる画像の技術的なトリミングです。

Update 2)を使用したアイデアはより論理的な問題ですが、技術アーキテクチャーは存在しないことを恐れています。フィルタを構築する前にすべての登録された画像サイズを分析することは、意図が現在のテーマで正しい品質の画像プログラムを返すことを確実にするためにもっと発展的になります。

同じ設定のすべてのサイズ名は、サーバー上で同じイメージを共有するのと同じ新しい品質を共有します。

ですから、それでも update 2)に固執するならば、$sizes変数に値を設定するために別の関数を呼び出し、var_dump()によって$_wp_additional_image_sizesを分析する必要があると思います。

1)... による回避策はより論理的/意味的です。同じ拡張方法でこれを解決しましたが、代わりに動的フィルタを使用しました。

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

それぞれの個々の画像サイズをフィルタリングするために、我々はそれから使います:

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

この拡張バージョンと異なる点は、デフォルト値としてadd_filter('jpeg_quality' ...バージョンを使用していることです。

カスタムフィルタの他の例をいくつか示します。

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

開発者の注目

  • テーマ画像の設定後にShureフィルタを適用します。
  • is_admin()の中にラップしないで、ajax呼び出し、フロントエンド、リモート処理
    投稿された画像は噛まれません。

前述のように、crop値は0またはfalseのいずれかです。$condition = ($crop ? 'true' : 'false');を使用して(int)または(bool)を文字列に変換する必要があります。

テーマ開発者の注目

WPデフォルト圧縮はかなり進歩的です。 8099の間の値は、大きな違いまたはまったく表示されない結果を返す可能性があります。 100のような圧縮されていない値は、 "小さいサイズ"の場合は大きいファイルサイズを返し、 800 px imagesの場合はオリジナルの大きな 3000 px サイズのバージョン。

96年のマジックナンバーを発見して何年も経つと、ファイルサイズは小さくなりますが、100値圧縮の違いを見ることはできません。

高品質のフォトショップが店の画像を用意し、800px以上はWordpressのデフォルト82で問題ありません。しかし、iPhoneの "大きい" Eメール投稿画像はサムネイルのような小さいサイズでは本当に96の値が必要です。それらはWordpres圧縮で「ぼかしを和らげる」ようになります。

プロジェクト、ユーザー、またはテーマのシナリオを計画していない場合は、このトピックの解決策をやり過ぎてください。

最後の反省

Wordpressでは、この重要な問題は開発の優先事項では無視されていることに、本当に失望しています。

個々の圧縮に使用できる適切な場所にフィルタを配置することはできません。彼らはwp_editor_set_qualityに「名前を変更する」ことを煩わしく、そしてadd_filter('jpeg_quality' ...は現在非推奨です。 @birgireで言及されているように、これがずっと進んでいるとは思わず、if ( ! $this->quality )の1回限りのチェック方法を削除してください。

0
Jonas Lundman