Mengubah kompresi JPEG tergantung pada ukuran gambar

8

Pendek. Saya ingin gambar 'besar' dikompresi oleh 90%, dan 'sedang' sebesar 60%. Sudah banyak yang Anda tahu, kadang-kadang gambar yang lebih besar menderita kompresi tinggi, tetapi gambar kecil lainnya tidak.

Fungsi ini memungkinkan untuk mengubah sampel semua gambar jpg

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

Bagaimana cara memfilter menurut ukuran gambar?

DarkGhostHunter
sumber

Jawaban:

11

Filter yang sangat istimewa

The jpeg_qualityFilter adalah benar-benar satu khusus: Ini akan digunakan dalam tiga kasus yang berbeda dan Anda sudah menggunakan argumen kedua untuk menentukan, jika Anda ingin menggunakan filter atau tidak.

Jangan biarkan itu melakukan segalanya

Masalah utama untuk filter khusus tersebut adalah, bahwa filter itu mungkin aktif untuk tindakan selanjutnya, jika Anda tidak menghapusnya - biarkan filter berjalan setelah pemeriksaan pertama. Jadi kita perlu memasukkan filter lain wp_save_image_file()untuk memeriksa apakah kita ingin mengubah kompresi atau tidak. Untuk menonaktifkannya untuk proses penyimpanan lain, kami menghapusnya tepat sebelum mengubah kompresi.

Anak kool

Yang benar-benar aneh adalah, WP itu menggunakan kompresi standar 90% (yang merupakan kualitas berkurang 10%) untuk setiap proses penyimpanan. Ini berarti, bahwa setiap kali Anda mengunggah / memotong / mengedit gambar, Anda mengurangi kualitasnya ... yang menyulitkan gambar yang bukan yang terbaik, ketika Anda mengunggahnya (mengujinya dengan gambar yang mengandung banyak warna merah) dengan latar belakang kontras tinggi). Tapi ... Yang benar-benar rapi adalah, Anda bisa mengubah perilaku ini. Jadi Anda ingin mengubah kompresi, tetapi dapatkan kualitas yang ditingkatkan - jauh lebih baik daripada core allow- pada saat yang sama.

/**
 * 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: Setelah diskusi singkat dengan @toscho, ia menunjukkan, bahwa seluruh panggilan balik dapat dikurangi menjadi sebagai berikut:

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

Ketika saya mengeluarkan kode dari sebuah plugin yang sedang saya kerjakan, saya perlu switchmenambahkan pengaturan. Saya juga harus mencatat, bahwa saya tidak menggunakan di globaldalam plugin saya, karena ini merupakan pendekatan OOP. Kode yang dapat Anda baca ↑ di atas, terutama dikurangi dan diubah kode dari plugin, yang memiliki beberapa kelebihan kiri kecil dan dimaksudkan untuk menjadi penjelasan bagi pembaca kemudian dan masih berfungsi. Jika Anda ingin menggunakannya sebagai plugin, Anda dapat melakukan beberapa optimasi tergantung pada kasus penggunaan pribadi Anda.


Catatan:

Dari beberapa penyelidikan pada tugas yang berbeda, ada, saya perhatikan, bahwa banyak $cases dipicu pada langkah-langkah berikut:

  • Putar: edit-image» image-resize(1 × lebih baru untuk ukuran apa pun yang Anda pilih - Gambar mini, dll.)
  • Cermin: edit-image» image-resize(-" -)

Ini berarti, bahwa callback filter untuk jpeq_qualityakan memicu 2 × untuk memutar / mirroring gambar dan + 1 × untuk ukuran tambahan apa pun yang Anda tambahkan. Jadi, jika Anda mendapat kurang dari 100%, itu akan mengurangi kualitas dua kali. Saya melakukan banyak penelitian tentang topik ini, tetapi saya masih tidak sepenuhnya yakin, apa fungsi sebenarnya yang menyebabkan perilaku ini.

kaisar
sumber
Sudah Anda mengerti, print_r / var_dump tidak berfungsi. Bagaimana saya bisa menampilkan itu?
DarkGhostHunter
Gunakan echo '<pre>'.var_export( $image, true ).'</pre>';. Letakkan exit;setelah itu, sehingga tidak bisa dilewati dengan memuat ulang halaman, dll.
kaiser
sial, tersesat di hutan - saya tidak bisa melihat di mana ia mencetak. Saya memiliki kode itu sebelum $ image kembali;
DarkGhostHunter
Tambahkan tepat di awal wpse58600_custom_jpg_compression()fungsi.
kaiser
1
mari kita lanjutkan diskusi ini dalam obrolan
DarkGhostHunter