1. negibouze

    No comment

    negibouze
Changes in body
Source | HTML | Preview
@@ -1,234 +1,233 @@
**!実施環境を見てもらえば分かると思いますが、いろいろ古いです。**
## 実施環境
* OS: Ubuntu 14.04.5 LTS
* php: 5.5.9
* php5-imagick: 3.1.2-1build1
## 本題
こんな感じのclassを作る(とりあえず雰囲気が伝われば幸いです)。
```php:ImagickHelper.php
<?php
-
class ImagickHelper {
private $imagick = null;
-
/**
*
* @param $file
* @return
* @throw Exception
*/
public function begin($file) {
if ($file === null) {
throw new Exception('$file must not be null.');
}
try {
if ($this->imagick === null) {
$this->imagick = new Imagick();
} else {
$this->imagick->clear();
}
$this->imagick->readImage($file);
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
* JPEG画像の回転補正(ExifのOrientation対応)
* @param $file
* @return
* @throw Exception
*/
public function adjustExifOrientation() {
$this->verify();
try {
if (strtolower($this->imagick->getImageFormat()) != 'jpeg') {
return $this;
}
$orientation = $this->imagick->getImageOrientation();
$isRotated = true;
switch($orientation) {
case Imagick::ORIENTATION_BOTTOMRIGHT:
$this->imagick->rotateimage('none', 180);
break;
case Imagick::ORIENTATION_RIGHTTOP:
$this->imagick->rotateimage('none', 90);
break;
case Imagick::ORIENTATION_LEFTBOTTOM:
$this->imagick->rotateimage('none', -90);
break;
default:
$isRotated = false;
}
if ($isRotated) {
$this->imagick->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
}
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
*
* @param
* @param
* @param
* @return
* @throw Exception
*/
public function reduce($width, $height, $aspectFit = true) {
$this->verify();
try {
// オリジナルの画像サイズ
$imgWidth = $this->imagick->getImageWidth();
$imgHeight = $this->imagick->getImageHeight();
// 画像が指定サイズより大きい場合
if ($imgWidth > $width || $imgHeight > $height) {
$newWidth = $width;
$newHeight = $height;
if ($aspectFit) {
if (($width / $height) > ($imgWidth / $imgHeight)) {
$newWidth = 0;
} else {
$newHeight = 0;
}
}
$this->imagick->resizeImage($newWidth, $newHeight, imagick::FILTER_LANCZOS, 1);
}
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
*
- * @param $maxBytes 画像サイズの上限
- * @param $quality 品質
+ * @param $fn 品質を返す関数(引数に画像サイズ(byte)を取る)
* @return
* @throw Exception
*/
- public function compress($maxBytes = 5000000, $quality = 80) {
+ public function compress(callable $fn = null) {
$this->verify();
try {
- if (!is_numeric($maxBytes) || !is_numeric($quality)) {
- throw new Exception('$maxBytes and $quality must be numeric.');
- }
- if ($this->imagick->getImageLength() <= $maxBytes) {
- return $this;
- }
-
+ $quality = is_callable($fn) ? call_user_func($fn, strlen($this->imagick->getImageBlob())) : 0;
+
$comp = call_user_func(function($format) {
switch($format) {
case 'jpeg':
return imagick::COMPRESSION_JPEG;
break;
default:
return imagick::COMPRESSION_UNDEFINED;
}
}, strtolower($this->imagick->getImageFormat()));
$this->imagick->setImageCompression($comp);
- $this->imagick->setImageCompressionQuality($quality);
-
+ if (!$this->imagick->setImageCompressionQuality($quality)) {
+ throw new Exception("Failed to set image compression quality. quality: {$quality}");
+ }
+
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
*
* @param $quality 品質
* @return
* @throw Exception
*/
public function cropThumbnail($width, $height) {
if ($width === null || $width === null) {
throw new Exception('$width and $height must not be null.');
}
$this->verify();
try {
- $this->imagick->cropThumbnailImage($width, $height.'aiueo');
-
+ if (!$this->imagick->cropThumbnailImage($width, $height)) {
+ throw new Exception("Failed to crop thumbnail image. wdith: {$width} height: {$height}");
+ }
+
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
*
* @param $output 出力先(ファイル名まで)
* @return
* @throw Exception
*/
public function write($output = null) {
$this->verify();
try {
$this->imagick->writeImage($output);
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
*
* @return
* @throw Exception
*/
public function clear() {
$this->verify();
try {
$this->imagick->clear();
return $this;
} catch(ImagickException $e) {
throw new Exception($e->getMessage().' file: '.basename(__FILE__).' line: '.__LINE__);
}
}
-
/**
- *
+ *
* @return $this
*/
public function discard() {
$this->imagick = null;
return $this;
}
-
/**
*
* @throw Exception
*/
private function verify() {
if ($this->imagick === null) {
throw new Exception('To start the imagick process, call begin() at first.');
}
}
}
```
使う側はこんな感じ。
```php
/**
* 画像の加工処理
*/
private function imageProcessing($file) {
$im = new ImagickHelper();
try {
// EXIF Orientationを調整して、縮小して、圧縮して書き出す
- $im->begin($file)->adjustExifOrientation()->reduce(1920, 1080)->compress()->write()->clear();
+ $im->begin($file)->adjustExifOrientation()
+ ->reduce($this->image_max_width, $this->image_max_height)
+ ->compress(function($imageLength) {
+ // 1MB以上だったら品質を80%に設定
+ switch ($imageLength) {
+ case 1000000 <= $imageLength:
+ return 80;
+ break;
+ default:
+ return 0;
+ }
+ })->write($file)->clear();
return true;
} catch(Exception $e) {
echo "An error occurred. {$e->getMessage()}";
return false;
} finally {
$im->discard();
}
}
```