คุณภาพของภาพขึ้นอยู่กับขนาดของภาพ


15

เป็นไปได้หรือไม่ที่จะกำหนดคุณภาพของภาพตามขนาดของภาพ? ฉันต้องการคุณภาพของภาพที่ดีขึ้นสำหรับภาพขนาดใหญ่ (80) - และแย่กว่าสำหรับภาพขนาดเล็ก (30)

ฉันคาดหวังว่าพารามิเตอร์ที่add_sizeจะควบคุมนั้น - แต่ไม่มี

หากมีความสำคัญ: ฉันใช้ ImageMagick

คำตอบ:


15

การตั้งค่าเวลาคุณภาพเท่านั้นที่สำคัญจริงๆก่อนที่ภาพจะถูกบันทึกหรือสตรีม (สำหรับโปรแกรมแก้ไข) ทั้งสองอย่างนี้มีตัวกรอง "image_editor_save_pre" ที่นั่นส่งผ่านอินสแตนซ์ของเครื่องมือแก้ไขภาพ ดังนั้นคุณสามารถใช้สิ่งนั้นเพื่อแก้ไขภาพในแบบที่คุณต้องการรวมถึงการตั้งค่าคุณภาพ

ดังนั้นสิ่งนี้ควรทำงานได้อย่างง่ายดาย:

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

เหตุผลที่ฉันไม่ใช้สิ่งที่ตรงตามที่เป็น (+1) นี้คือฉันจำได้ว่าเมื่อแก้ไขรูปภาพ (การหมุนการครอบตัด ฯลฯ ) ทุกการกระทำถูกเรียกสองครั้งลดคุณภาพสองครั้ง ยังคง "เป็นตัวอย่างของWP_Image_Editor " ส่วนหนึ่งก็เป็นทางออกมากกว่าสิ่งที่ฉันเขียน
ไกเซอร์

1
คุณภาพเป็นค่าที่แน่นอนไม่ใช่เปอร์เซ็นต์ คุณสามารถตั้งค่าและรีเซ็ตทุกอย่างที่คุณต้องการจนกว่ามันจะบันทึก ตั้งค่าเป็น 10 ร้อยครั้งทิ้งไว้ที่ 10
Otto

ฉันคิดว่ามันจะช่วยในระหว่าง ขอบคุณสำหรับหัวขึ้น.
ไกเซอร์

มันดูเหมือนว่าฉันว่า image_editor_save_preจะไม่ได้รับการเรียก เมื่อฉันพยายามที่จะแสดงผลสิ่งที่ใช้error_log(ซึ่งใช้งานได้จริง) ฉันไม่ได้รับผลลัพธ์ใด ๆ : /
Nils Riedemann

1
การสร้างใหม่อาจทำงานได้เช่นกันหากบันทึกภาพไว้ ไม่มีรหัสใดที่จะเปลี่ยนแปลงไฟล์ที่มีอยู่ในระบบโดยที่คุณไม่ต้องดำเนินการเพื่อโหลดซ้ำและบันทึกใหม่
อ็อตโต

5

หมายเหตุล่วงหน้า: คำตอบด้านล่างยังไม่เสร็จและไม่ได้ทดสอบ แต่ฉันไม่มีเวลาเหลือดังนั้นฉันจะปล่อยให้นี่เป็นแบบร่าง version_compare()สิ่งที่อาจจะต้องมีคู่ที่สองของดวงตาเป็นวิธีการที่มีคุณภาพและการตีความของ

ก่อนอื่นเราต้องมีจุดเข้าใช้งาน หลังจากอ่านโพสต์ makeอีกครั้งฉันคิดว่าควรข้ามไปก่อนที่ Image Editor จะบันทึกรูปภาพที่สร้างขึ้นใหม่ ดังนั้นนี่คือไมโครคอนโทรลเลอร์ที่ดักในระหว่างการเรียกกลับไปติดยาเสพติดและโหลดระดับที่จากนั้นก็เดินผ่านการตั้งค่าของคุณกำหนดไว้ภายในการเรียกกลับไปยังimage_editor_save_pre wpse_jpeg_qualityมันจะส่งกลับอัตราส่วนการบีบอัดที่แตกต่างกันสำหรับjpeg_qualityตัวกรองที่ทำงานภายใน Image Editor

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

ผู้ปฏิบัติงานจริงคือJPEGQualityWorkerชั้นเรียน มันอยู่ในไดเรกทอรีเดียวกันกับไฟล์ปลั๊กอินหลักด้านบนและตั้งชื่อworker.php(หรือคุณเปลี่ยนคอนโทรลเลอร์ด้านบน)

มันดึงภาพและการตั้งค่าของคุณแล้วเพิ่มการเรียกกลับไปที่jpeg_qualityตัวกรอง มันคืออะไร

  • ดึงภาพอ้างอิงของคุณ (ความกว้างหรือความสูง)
  • การถามจุดพักของคุณที่ตัดสินใจว่าจะสลับระหว่างอัตราส่วนการบีบอัด / คุณภาพต่ำและสูง
  • การดึงขนาดภาพดั้งเดิม
  • ตัดสินใจว่าจะคืนคุณภาพอะไร

เบรกพอยต์และขีด จำกัด คือสิ่งที่ตัดสินใจระหว่างสูงกับต่ำและดังที่กล่าวไว้ข้างต้นสิ่งนี้อาจต้องการความรักมากกว่านี้

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

ยังทำงานกับมันอยู่หรือ? เท่าที่ฉันกังวลฉันชอบที่จะเห็นว่าเป็นปลั๊กอิน
Nils Riedemann

ขออภัย แต่ไม่ใช่ฉันไม่ได้ ฉันต้องการที่จะเห็นว่าเป็นปลั๊กอินเช่นกัน แต่ในขณะที่ฉันไม่ต้องการมันและไม่มีเวลามันก็จะไม่เกิดขึ้น อาจจะลองดูดูว่าคุณได้รับและจัดเก็บการแก้ไขหรือคำตอบแยกต่างหาก :)
kaiser

ไกเซอร์: คุณคิดว่ามันซับซ้อนเกินไปฉันคิดว่า $ image ที่ส่งไปยัง image_editor_save_pre เป็นอินสแตนซ์ของคลาส WP_Image_Editor มันมีฟังก์ชั่นเพื่อให้ได้ขนาดและกำหนดคุณภาพและทุกอย่างที่มีอยู่แล้ว สิ่งที่คุณต้องทำคือเรียกพวกเขา
อ็อตโต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.