web-dev-qa-db-ja.com

カスタム画像サイズのJPEG圧縮を設定することは特定のケースでは動作しません

私は カスタム画像サイズhello-imageを持っています:

add_image_size( 'hello-image', 700, 300, true );

画像がアップロードされるときはいつでも、私は切り取られたhello-imageサイズの画像を40% JPEG圧縮に圧縮します。それは除くすべてのケースで素晴らしい作品...

問題

元の画像の width 700pxよりもより大きいの場合、それは問題なく動作します。しかし、その幅が700pxよりもlessの場合、圧縮は0%前後になります。

テスト方法

次の2つの画像をダウンロードしてください。

BIG:784ピクセル×441ピクセル

小:670px×377px

それから私はすべての関連コードを持つプラグインを作成しました:

<?php
/*
Plugin Name: WPSE: custom image size and JPEG compression
Description: custom image size and JPEG compression
Author: WPSE
Version: 1.0
*/

// Set JPEG compression quality
add_filter('jpeg_quality', create_function('$quality', 'return 100;'));

add_action('added_post_meta', 'ad_update_jpeg_quality', 10, 4);

function ad_update_jpeg_quality($meta_id, $attach_id, $meta_key, $attach_meta) {

    if ($meta_key == '_wp_attachment_metadata') {

        $post = get_post($attach_id);

        if ($post->post_mime_type == 'image/jpeg' && is_array($attach_meta['sizes'])) {

            $pathinfo = pathinfo($attach_meta['file']);
            $uploads = wp_upload_dir();
            $dir = $uploads['basedir'] . '/' . $pathinfo['dirname'];

            foreach ($attach_meta['sizes'] as $size => $value) {

                $image = $dir . '/' . $value['file'];
                $resource = imagecreatefromjpeg($image);

                if ($size == 'large') {

                    // set the jpeg quality for 'large' size
                    imagejpeg($resource, $image, 35);

                } elseif ($size == 'medium') {

                    // set the jpeg quality for the 'medium' size
                    imagejpeg($resource, $image, 35);

                } elseif ($size == 'hello-image') {

                    // set the jpeg quality for the 'hello-image' size
                    imagejpeg($resource, $image, 40);

                } else {

                    // set the jpeg quality for the rest of sizes
                    imagejpeg($resource, $image, 35); // 38
                }

                imagedestroy($resource);
            }
        }
    }
}


// add custom image sizes to media uploader
function my_insert_custom_image_sizes( $sizes ) {
    // get the custom image sizes
    global $_wp_additional_image_sizes;
    // if there are none, just return the built-in sizes
    if ( empty( $_wp_additional_image_sizes ) )
        return $sizes;

    // add all the custom sizes to the built-in sizes
    foreach ( $_wp_additional_image_sizes as $id => $data ) {
        // take the size ID (e.g., 'my-name'), replace hyphens with spaces,
        // and capitalise the first letter of each Word
        if ( !isset($sizes[$id]) )
            $sizes[$id] = ucfirst( str_replace( '-', ' ', $id ) );
    }

    return $sizes;
}

// Which custom image size selected by default
function my_set_default_image_size () {
    return 'hello-image';
}

function custom_image_setup () {
    // custom image sizes
    add_image_size( 'medium', 300, 9999 ); //  medium
    add_image_size( 'hello-image', 700, 300, true ); // custom
    add_image_size( 'large', 700, 3000 ); //  large

    add_filter( 'image_size_names_choose', 'my_insert_custom_image_sizes' );
    add_filter( 'pre_option_image_default_size', 'my_set_default_image_size' );
}

add_action( 'after_setup_theme', 'custom_image_setup' );

それでは、big画像をアップロードして、hello-image画像がどのように圧縮されているか確認してください。それからsmall画像をアップロードして、同じ画像サイズがどのようにひどく圧縮されているかを確認します。明確にするために、これは結果です:

700x300 = 40% compression
670x300 = 0% compression

どちらもまったく同じカスタムイメージサイズで生成されます。この原因は何ですか?またどのように修正できますか?

幅が700px...よりも小さい場合、この画像サイズを作成しないようにする方法を尋ねる私の同僚がここに question を投稿しました。それに対するハックな修正。

最後に、私は最近のWordPressアップデートでこの問題に気づき始めたので、私のコードの問題とは対照的に、それはコアのバグかもしれません。

編集 update を読んでください。

6

いくつかの提案:

Image Editor APIを試してみたい場合は、置き換えることができます

imagejpeg( $resource, $image, 35 );

で:

$editor = wp_get_image_editor( $image );  
if ( ! is_wp_error( $editor ) )
{
    $editor->set_quality( 35 );
    $editor->save( $image  );
}
unset( $editor );

また、テストしてみてください。これらの部品:

$resource = imagecreatefromjpeg( $image );
if( false !== $resource )
{
    imagejpeg( $resource, $image, 35 );
    imagedestroy( $resource );
}

スタンドアロンのPHPスクリプトで、PHPまたはGd関連の問題ではないことを確認します。

PS: これは別のアプローチです 画質を変更しようとする場所before画像サイズが生成されます。

プラグインのテスト

メインの質問からプラグインを確認しましょう。

テストインストール

  • WordPressバージョン4.9-alpha-40917
  • PHP 7.0.19

Gdimagick

以下は、品質から40に設定した質問から生成されたSMALL(670×377)画像のhello-image(670x300)サイズです。

imagejpeg( $resource, $image, 40 );

q=40

これは同じですが、品質が0に設定されています。

imagejpeg( $resource, $image, 0 );

q=0

do n'tは、品質が40に設定されると、670x377オリジナルのhello-imageサイズに対して、品質が40に設定されたときに0になるという、質問で説明されているのと同じ動作を得るように見えます画像。

6
birgire

面白いことに、私はそれを試してみました、そして小さい画像は670x300と大きな画像700x300を表示されます。それがそれがする必要があることを丁度しているように私には思えます、高さか幅のどちらかが画像タイプ(または両方)の上にあるならば、それは画像を切り取ります。

私はあなたが高さがより高い場合だけあなたが画像を切り取ることを望むと理解しますか?それからこれを使うとうまくいくでしょう:

  add_image_size( 'hello-world', 700, 0, true );

その後、画像を再アップロードすると、小さい画像は670 x 377、大きい画像は700 x 394と表示されます。別の小さいバージョン(516 x 290)をアップロードしても、まったくトリミングされません。

あなたは690x4000のような画像をアップロードするときそれはまたトリミングされませんが。

0
berend