<?php
/**
* Class PhotoCompressor 圖片壓縮
*
* @date 2018/4/30
* @author York <jason945119@gmail.com>
*/
class PhotoCompressor
{
// 裁切
const IS_CROP_MODE = 1;
const NO_CROP_MODE = 2;
// 預設寬高
const DEFAULT_W = 800;
const DEFAULT_H = 600;
// 預設品質
const DEFAULT_QUALITY = 80;
// 編輯核心
protected $imagick;
// 壓縮模式 1: 不裁切全圖 2:裁切至符合最大寬高
protected $mode;
// 品質預設 80
protected $quality;
// 以什麼為主 true: 寬 false:高
protected $main;
// 原始圖檔參數
protected $source_file;
protected $original_ratio;
protected $source_width;
protected $source_height;
// 輸出圖檔參數
protected $save_file;
protected $new_ratio;
protected $max_width;
protected $max_height;
protected function _init( string $source_file ) : self
{
// 設定編輯核心
self::_setCore( $source_file );
// 設定原始圖片寬高
self::_setSourceWH();
// 預設輸出品質
self::quality( self::DEFAULT_QUALITY );
// 預設輸出max寬高
self::maxWH( self::DEFAULT_W, self::DEFAULT_H );
// 預設輸出路徑
self::saveAs( $source_file );
return $this;
}
protected function _setCore( $source_file ) : void
{
$this->imagick = new \Imagick( $source_file );
}
protected function _setSourceWH() : void
{
$this->source_width = $this->imagick->getImageWidth();
$this->source_height = $this->imagick->getImageHeight();
}
protected function _setMain() : void
{
$this->new_ratio = $this->max_width / $this->max_height;
$this->original_ratio = $this->source_width / $this->source_height;
$this->main = ( $this->new_ratio > $this->original_ratio );
}
protected function _crop() : void
{
if( $this->main )
{
// 以寬為主
$cropWidth = $this->source_width;
$cropHeight = $this->source_width / $this->new_ratio;
$cropX = 0;
$cropY = ( $this->source_height - $cropHeight ) / 2;
}
else
{
// 以高為主
$cropWidth = $this->max_height * $this->new_ratio;
$cropHeight = $this->max_height;
$cropX = ( $this->source_width - $cropWidth ) / 2;
$cropY = 0;
}
$this->imagick->cropImage( $cropWidth, $cropHeight, $cropX, $cropY );
}
protected function _reduce() : void
{
if( $this->mode == self::IS_CROP_MODE )
{
if( $this->main )
{
// 以寬為主 寬設定到 max
$final_width = $this->max_width;
$final_height = $this->source_height * $this->max_width / $this->source_width;
}
else
{
// 以高為主 高設定到 max
$final_width = $this->source_width * $this->max_height / $this->source_height;
$final_height = $this->max_height;
}
}
if( $this->mode == self::NO_CROP_MODE )
{
$final_width = $this->max_width;
$final_height = $this->max_height;
}
$this->imagick->thumbnailImage( $final_width, $final_height );
}
/**
* saveAs 設定圖片產出路徑
*
* @param string $save_file
*
* @return PhotoCompressor
*
* @date 2018/4/26
* @author York <jason945119@gmail.com>
*/
public function saveAs( string $save_file ) : self
{
$this->save_file = $save_file;
return $this;
}
/**
* maxWH 設定最大寬高
*
* @param int $width
* @param int $height
*
* @return PhotoCompressor
*
* @date 2018/4/26
* @author York <jason945119@gmail.com>
*/
public function maxWH( int $width, int $height ) : self
{
$this->max_width = $width;
$this->max_height = $height;
return $this;
}
/**
* quality 設定品質
*
* @param int $quality
*
* @return PhotoCompressor
*
* @date 2018/4/26
* @author York <jason945119@gmail.com>
*/
public function quality( int $quality ) : self
{
$this->quality = $quality;
return $this;
}
/**
* compress 開始裁切縮放
*
* @param int $mode
*
* @date 2018/4/26
* @author York <jason945119@gmail.com>
*/
public function compress( $mode = self::IS_CROP_MODE ) : void
{
// 選定模式
$this->_setMain();
$this->mode = $mode;
//裁切
if( $this->mode == self::NO_CROP_MODE )
{
$this->_crop();
}
// 縮放
if( ( $this->source_width > $this->max_width ) || ( $this->source_height > $this->max_height ) || ( $this->mode === self::NO_CROP_MODE ) )
{
$this->_reduce();
}
$this->imagick->setImageFormat( 'jpg' );
$this->imagick->setCompressionQuality( $this->quality );
$this->imagick->writeImage( $this->save_file );
}
public static function instance( string $source_file ) : self
{
static $obj;
if( !isset( $obj ) )
{
$obj = new self();
}
$obj->source_file = $source_file;
return $obj->_init( $source_file );
}
}