7 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
9 * @package Magic3 Framework
10 * @author 平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
11 * @copyright Copyright 2006-2013 Magic3 Project.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
13 * @version SVN: $Id: imageManager.php 6148 2013-07-01 01:11:14Z fishbone $
14 * @link http://www.magic3.org
16 require_once(M3_SYSTEM_INCLUDE_PATH . '/common/core.php');
18 class ImageManager extends Core
20 const CONTENT_DIR = '/etc/';
21 const THUMBNAIL_DIR = '/thumb';
22 const SITE_LOGO_DIR = '/etc/site/thumb/'; // サイトロゴ格納ディレクトリ
23 const AVATAR_DIR = '/etc/avatar/'; // アバター格納ディレクトリ
24 const DEFAULT_THUMB_DIR = '/etc/default/thumb/'; // デフォルトサムネールディレクトリ
25 const DEFAULT_AVATAR_BASE = 'default_'; // デフォルトのアバターファイル名ヘッド部
26 const DEFAULT_THUMBNAIL_EXT = 'png';
27 const DEFAULT_THUMBNAIL_SIZE = 72;
28 const DEFAULT_THUMBNAIL_TYPE = '72c';
29 const CF_SITE_LOGO_FILENAME = 'site_logo_filename'; // サイトロゴファイル
30 const CF_THUMB_FORMAT = 'thumb_format'; // サムネールフォーマット
31 const CF_AVATAR_FORMAT = 'avatar_format'; // アバターフォーマット
32 const CF_OGP_THUMB_FORMAT = 'ogp_thumb_format'; // OGPサムネールフォーマット
33 const NOT_AVAILABLE_HEAD = 'notavailable_'; // 設定画像がない場合の表示画像のファイル名ヘッダ部
38 function __construct()
41 parent::__construct();
44 * システム共通のデフォルトのサムネールを作成
46 * @param string $contentType コンテンツタイプ
47 * @param int $deviceType デバイスタイプ(0=PC、1=携帯、2=スマートフォン)
48 * @param string $contentId コンテンツID
49 * @param string $path 元の画像ファイル
50 * @param array $destFilename 作成した画像のファイル名
51 * @param string $destDir 作成した画像のディレクトリ
52 * @param string $destDirUrl 作成した画像のディレクトリURL
53 * @return bool true=作成,false=作成失敗
55 function createSystemDefaultThumb($contentType, $deviceType, $contentId, $path, &$destFilename, &$destDir = NULL, &$destDirUrl = NULL)
57 global $gSystemManager;
60 if (strlen($contentId) == 0) return false;
62 $destFilename = array(); // 画像ファイル名
65 $thumbDir = $this->getSystemThumbPath($contentType, $deviceType);
66 if (!file_exists($thumbDir)) mkdir($thumbDir, M3_SYSTEM_DIR_PERMISSION, true/*再帰的*/);
67 if (!is_null($destDir)) $destDir = $thumbDir;
70 if (!is_null($destDirUrl)) $destDirUrl = $this->getSystemThumbUrl($contentType, $deviceType);
73 $formatArray = explode(';', $gSystemManager->getSystemConfig(self::CF_THUMB_FORMAT));
75 for ($i = 0; $i < count($formatArray); $i++){
76 $format = trim($formatArray[$i]);
77 $ret = preg_match('/(\d+)(.*)\.(gif|png|jpg|jpeg|bmp)$/i', $format, $matches);
79 $thumbSize = $matches[1];
80 $thumbAttr = strtolower($matches[2]);
81 $ext = strtolower($matches[3]);
83 $imageType = IMAGETYPE_JPEG;
87 $imageType = IMAGETYPE_JPEG;
90 $imageType = IMAGETYPE_GIF;
93 $imageType = IMAGETYPE_PNG;
96 $imageType = IMAGETYPE_BMP;
99 $thumbFilename = $contentId . '_' . $format;
100 $thumbPath = $thumbDir . DIRECTORY_SEPARATOR . $thumbFilename;
103 if ($thumbAttr == 'c'){ // 切り取りサムネールの場合
104 //$ret = $this->gInstance->getImageManager()->createThumb($path, $thumbPath, $thumbSize, $imageType, true);
105 $ret = $this->createThumb($path, $thumbPath, $thumbSize, $imageType, true);
107 //$ret = $this->gInstance->getImageManager()->createThumb($path, $thumbPath, $thumbSize, $imageType, false);
108 $ret = $this->createThumb($path, $thumbPath, $thumbSize, $imageType, false);
111 $destFilename[] = $thumbFilename;
120 * システム共通のデフォルトのサムネールを削除
122 * @param string $contentType コンテンツタイプ
123 * @param int $deviceType デバイスタイプ(0=PC、1=携帯、2=スマートフォン)
124 * @param array $filename ファイル名
125 * @return bool true=成功,false=失敗
127 function delSystemDefaultThumb($contentType, $deviceType, $filename)
129 global $gSystemManager;
132 $thumbDir = $this->getSystemThumbPath($contentType, $deviceType);
135 for ($i = 0; $i < count($filename); $i++){
136 $thumbnailPath = $thumbDir . DIRECTORY_SEPARATOR . $filename[$i];
137 if (!@unlink($thumbnailPath)) $ret = false;
142 * システム共通のサムネール画像のURLを取得
144 * @param string $contentType コンテンツタイプ
145 * @param int $deviceType デバイスタイプ(0=PC、1=携帯、2=スマートフォン)
146 * @param string $filename ファイル名(空のときは格納ディレクトリを返す)
147 * @param string $notAvailableFileType ファイルが見つからない場合の代替ファイルのタイプ(ogp=OGP用サムネール)
148 * @return string 画像URL
150 function getSystemThumbUrl($contentType, $deviceType, $filename = '', $notAvailableFileType = '')
154 switch ($deviceType){
167 $destUrl = $gEnvManager->getResourceUrl() . self::CONTENT_DIR . $contentType . $deviceDir . self::THUMBNAIL_DIR; // 画像格納用のディレクトリ
169 if (empty($notAvailableFileType)){
170 if (empty($filename)){
173 return $destUrl . '/' . $filename;
175 } else { // 画像が見つからない場合の画像タイプが指定されているとき
177 $destDir = $gEnvManager->getResourcePath() . self::CONTENT_DIR . $contentType . $deviceDir . self::THUMBNAIL_DIR; // 画像格納用のディレクトリ
178 $path = $destDir . DIRECTORY_SEPARATOR . $filename;
179 if (!is_dir($path) && is_readable($path)){
180 return $destUrl . '/' . $filename;
182 return $this->getNotAvailableImageUrl($notAvailableFileType);
187 * システム共通のサムネール画像のパスを取得
189 * @param string $contentType コンテンツタイプ
190 * @param int $deviceType デバイスタイプ(0=PC、1=携帯、2=スマートフォン)
191 * @param string $filename ファイル名(空のときは格納ディレクトリを返す)
192 * @param string $notAvailableFileType ファイルが見つからない場合の代替ファイルのタイプ(ogp=OGP用サムネール)
193 * @return string 画像パス
195 function getSystemThumbPath($contentType, $deviceType, $filename = '', $notAvailableFileType = '')
199 switch ($deviceType){
212 $destDir = $gEnvManager->getResourcePath() . self::CONTENT_DIR . $contentType . $deviceDir . self::THUMBNAIL_DIR; // 画像格納用のディレクトリ
214 if (empty($notAvailableFileType)){
215 if (empty($filename)){
218 return $destDir . DIRECTORY_SEPARATOR . $filename;
220 } else { // 画像が見つからない場合の画像タイプが指定されているとき
222 $path = $destDir . DIRECTORY_SEPARATOR . $filename;
223 if (!is_dir($path) && is_readable($path)){
224 return $destDir . DIRECTORY_SEPARATOR . $filename;
226 return $this->getNotAvailableImagePath($notAvailableFileType);
233 * @param string $contentType コンテンツタイプ
234 * @param string $contentId コンテンツID
235 * @param string $path 元の画像ファイル
236 * @return bool true=作成,false=作成失敗
238 function createDefaultThumb($contentType, $contentId, $path)
243 $destPath = $gEnvManager->getResourcePath() . self::CONTENT_DIR . $contentType . self::THUMBNAIL_DIR . DIRECTORY_SEPARATOR . $contentId . '_' . self::DEFAULT_THUMBNAIL_TYPE . '.' . self::DEFAULT_THUMBNAIL_EXT;
246 $destDir = dirname($destPath);
247 if (!file_exists($destDir)) mkdir($destDir, M3_SYSTEM_DIR_PERMISSION, true/*再帰的*/);
249 $ret = $this->createThumb($path, $destPath, self::DEFAULT_THUMBNAIL_SIZE, IMAGETYPE_PNG);
255 * @param string $contentType コンテンツタイプ
256 * @param string $contentId コンテンツID
257 * @return string 画像URL
259 function getDefaultThumbUrl($contentType, $contentId)
263 return $gEnvManager->getResourceUrl() . self::CONTENT_DIR . $contentType . self::THUMBNAIL_DIR . '/' . $contentId . '_' . self::DEFAULT_THUMBNAIL_TYPE . '.' . self::DEFAULT_THUMBNAIL_EXT;
268 * @param string $contentType コンテンツタイプ
269 * @param string $contentId コンテンツID
270 * @return string 画像パス
272 function getDefaultThumbPath($contentType, $contentId)
276 return $gEnvManager->getResourcePath() . self::CONTENT_DIR . $contentType . self::THUMBNAIL_DIR . DIRECTORY_SEPARATOR . $contentId . '_' . self::DEFAULT_THUMBNAIL_TYPE . '.' . self::DEFAULT_THUMBNAIL_EXT;
281 * @param string $path 元の画像ファイル
282 * @param string $destPath サムネールファイルパス
283 * @param int,array $size サムネールの縦横サイズ(縦横異なる場合は連想配列(width,height))
284 * @param int $type サムネールの画像タイプ
285 * @param bool $useCrop 画像切り取りありかどうか
286 * @param string $bgColor 背景色。設定しない場合は空文字列
287 * @param int $imageQuality 画像品質
288 * @return bool true=作成,false=作成失敗
290 function createThumb($path, $destPath, $size, $type, $useCrop = true, $bgColor = '#FFFFFF', $imageQuality = 100)
292 $imageSize = @getimagesize($path);
294 $imageType = $imageSize[2];
302 $imageObj = @imagecreatefromgif($path);
305 $imageObj = @imagecreatefromjpeg($path);
308 $imageObj = @imagecreatefrompng($path);
319 $width = imagesx($imageObj);
320 $height = imagesy($imageObj);
321 if (is_array($size)){
322 $destWidth = $size['width']; // サムネールの幅
323 $destHeight = $size['height']; // サムネールの高さ
325 $destWidth = $size; // サムネールの幅
326 $destHeight = $size; // サムネールの高さ
328 if ($useCrop){ // 画像切り取りありのとき
329 if (is_array($size)){
330 if ($height / $destHeight < $width / $destWidth){
331 $newHeight = $destHeight;
332 $newWidth = round($destHeight * $width / $height);
333 $x = ceil(($newWidth - $destWidth) / 2);
336 $newWidth = $destWidth;
337 $newHeight = round($destWidth * $height / $width);
339 $y = ceil(($newHeight - $destHeight) / 2);
342 if ($width > $height){
344 $newWidth = round($size * $width / $height);
346 $x = ceil(($width - $height) / 2);
350 $newHeight = round($size * $height / $width);
353 $y = ceil(($height - $width) / 2);
357 if ($width > $height){
358 $newHeight = $height * ($size / $width);
361 $newWidth = $width * ($size / $height);
367 if ($newWidth < $size) $newX = round(($size - $newWidth) / 2);
368 if ($newHeight < $size) $newY = round(($size - $newHeight) / 2);
372 //$thumbObj = imagecreatetruecolor($size, $size);
373 $thumbObj = imagecreatetruecolor($destWidth, $destHeight);
376 if (!$useCrop){ // 切り取りなしのとき
378 $bgColorR = intval(substr($bgColor, 1, 2), 16);
379 $bgColorG = intval(substr($bgColor, 3, 2), 16);
380 $bgColorB = intval(substr($bgColor, 5, 2), 16);
383 // $thumbObj = imagecreatetruecolor($size, $size);
384 $bgcolor = imagecolorallocate($thumbObj, $bgColorR, $bgColorG, $bgColorB); // 背景色設定
385 imagefill($thumbObj, 0, 0, $bgcolor);
389 // imagecopyresampledの方がimagecopyresizedよりも画質が良いのでこちらを使用
390 if (function_exists("imagecopyresampled")){
391 if (!imagecopyresampled($thumbObj, $imageObj, $newX, $newY, $x, $y, $newWidth, $newHeight, $width, $height)){
392 if (!imagecopyresized($thumbObj, $imageObj, $newX, $newY, $x, $y, $newWidth, $newHeight, $width, $height)) return false;
395 if (!imagecopyresized($thumbObj, $imageObj, $newX, $newY, $x, $y, $newWidth, $newHeight, $width, $height)) return false;
401 $ret = @imagegif($thumbObj, $destPath, $imageQuality);
404 $ret = @imagejpeg($thumbObj, $destPath, $imageQuality);
407 //$ret = @imagepng($thumbObj, $destPath, $imageQuality); // PNGでは$imageQualityを使用すると画像が0サイズで作成される
408 $ret = @imagepng($thumbObj, $destPath);
412 $ret = imagedestroy($imageObj);
413 $ret = imagedestroy($thumbObj);
420 * @param string $path 元の画像ファイル
421 * @param string $destPath 出力画像ファイルパス
422 * @param int,array $size 画像縦横最大サイズ(intの場合は縦横が収まる最大サイズ、arrayの場合は縦横の最大サイズ(width,height))
423 * @param int $type 出力画像タイプ
424 * @param array destSize 作成画像の縦横
425 * @param int $imageQuality 画像品質
426 * @return bool true=作成,false=作成失敗
428 function createImage($path, $destPath, $size, $type, &$destSize, $imageQuality = 100)
430 $imageSize = @getimagesize($path);
432 $imageType = $imageSize[2];
433 $srcWidth = $imageSize[0];
434 $srcHeight = $imageSize[1];
442 $imageObj = @imagecreatefromgif($path);
445 $imageObj = @imagecreatefromjpeg($path);
448 $imageObj = @imagecreatefrompng($path);
450 default: // 処理不可の画像タイプの場合は終了
455 if (is_array($size)){ // 配列の場合は縦横サイズ指定
456 $destWidth = $size['width'];
457 $destHeight = $size['height'];
459 $destWidth = $srcWidth;
460 $destHeight = $srcHeight;
461 if ($srcWidth > $srcHeight){
462 if ($srcWidth > $size){
464 $destHeight = round($srcHeight * ($size / $srcWidth));
467 if ($srcHeight > $size){
468 $destWidth = round($srcWidth * ($size / $srcHeight));
475 $destImageObj = imagecreatetruecolor($destWidth, $destHeight);
478 if (function_exists("imagecopyresampled")){
479 if (!imagecopyresampled($destImageObj, $imageObj, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight)){
480 if (!imagecopyresized($destImageObj, $imageObj, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight)) return false;
483 if (!imagecopyresized($destImageObj, $imageObj, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight)) return false;
489 $ret = @imagegif($destImageObj, $destPath, $imageQuality);
492 $ret = @imagejpeg($destImageObj, $destPath, $imageQuality);
495 //$ret = @imagepng($destImageObj, $destPath, $imageQuality); // PNGでは$imageQualityを使用すると画像が0サイズで作成される
496 $ret = @imagepng($destImageObj, $destPath);
500 $ret = imagedestroy($imageObj);
501 $ret = imagedestroy($destImageObj);
504 $destSize = array('width' => $destWidth, 'height' => $destHeight);
510 * @param string $html 検索コンテンツ
511 * @return string 画像パス(取得できない場合は空文字列)
513 function getFirstImagePath($html)
517 $exp = '/<img[^<]*?src\s*=\s*[\'"]+(.+?)[\'"]+[^>]*?>/si';
518 $ret = preg_match($exp, $html, $matches);
520 $path = $gEnvManager->getMacroPath($matches[1]); // 画像URL
521 $path = str_replace(M3_TAG_START . M3_TAG_MACRO_ROOT_URL . M3_TAG_END, $gEnvManager->getSystemRootPath(), $path);// マクロ変換
522 if (is_readable($path)) return $path;
529 * @return string 画像URL
531 function getSiteLogoUrl()
534 global $gSystemManager;
536 $siteLogoFiles = explode(';', $gSystemManager->getSystemConfig(self::CF_SITE_LOGO_FILENAME)); // サイトロゴファイル名
537 $path = $gEnvManager->getResourcePath() . self::SITE_LOGO_DIR . $siteLogoFiles[count($siteLogoFiles) -1];
539 if (is_readable($path)) $url = $gEnvManager->getResourceUrl() . self::SITE_LOGO_DIR . $siteLogoFiles[count($siteLogoFiles) -1];
545 * @param string $filename 画像ファイル名。空の場合はデフォルトアバター画像。
546 * @return string 画像URL。存在しない場合はデフォルト画像URLを取得
548 function getAvatarUrl($filename = '')
552 if (empty($filename)){
553 $filename = self::DEFAULT_AVATAR_BASE . $this->getDefaultAvatarFormat();
555 $path = $gEnvManager->getResourcePath() . self::AVATAR_DIR . $filename;
556 if (!is_readable($path)) $filename = self::DEFAULT_AVATAR_BASE . $this->getDefaultAvatarFormat();
558 $url = $gEnvManager->getResourceUrl() . self::AVATAR_DIR . $filename;
564 * @param string $filename 画像ファイル名。空の場合はデフォルトアバター画像。
565 * @return string 画像パス
567 function getAvatarPath($filename = '')
571 if (empty($filename)) $filename = self::DEFAULT_AVATAR_BASE . $this->getDefaultAvatarFormat();
572 $path = $gEnvManager->getResourcePath() . self::AVATAR_DIR . $filename;
578 * @return string フォーマット
580 function getDefaultAvatarFormat()
582 global $gSystemManager;
584 $formats = explode(';', $gSystemManager->getSystemConfig(self::CF_AVATAR_FORMAT)); // アバターフォーマット
585 $format = $formats[count($formats) -1]; // 最後(最大)の画像
589 * OGP用サムネールデフォルトフォーマットを取得
591 * @return string フォーマット
593 function getDefaultOGPThumbFormat()
595 global $gSystemManager;
597 $format = $gSystemManager->getSystemConfig(self::CF_OGP_THUMB_FORMAT); // OGPサムネールフォーマット
603 * @param string $path 元の画像ファイル
604 * @param string $formats 作成する画像フォーマット(複数の場合は「;」区切り)
605 * @param string $destDir 作成する画像のディレクトリ
606 * @param string $destFilenameBase 作成する画像ファイル名基本部。ファイル名は「基本部_フォーマット」で作成。
607 * @param array $destFilename 作成した画像のファイル名
608 * @return bool true=作成,false=作成失敗
610 function createImageByFormat($path, $formats, $destDir, $destFilenameBase, &$destFilename)
613 if (empty($formats)) return false;
615 $destFilename = array(); // 画像ファイル名
618 $formatArray = explode(';', $formats);
620 for ($i = 0; $i < count($formatArray); $i++){
621 $format = $formatArray[$i];
622 $ret = $this->parseImageFormat($format, $imageType, $imageAttr, $imageSize);
624 $newFilename = $destFilenameBase . '_' . $format;
625 $newPath = $destDir . DIRECTORY_SEPARATOR . $newFilename;
628 if ($imageAttr == 'c'){ // 切り取りサムネールの場合
629 //$ret = $this->gInstance->getImageManager()->createThumb($path, $newPath, $imageSize, $imageType, true);
630 $ret = $this->createThumb($path, $newPath, $imageSize, $imageType, true);
632 //$ret = $this->gInstance->getImageManager()->createThumb($path, $newPath, $imageSize, $imageType, false);
633 $ret = $this->createThumb($path, $newPath, $imageSize, $imageType, false);
636 $destFilename[] = $newFilename;
647 * フォーマットから画像サイズ、画像タイプを取得
649 * @param string $format 画像フォーマット
650 * @param string $imageType 画像タイプ
651 * @param string $imageAttr 画像属性(c=切り取りあり)
652 * @param string,array $imageSize 画像サイズ(縦横異なる場合は連想配列(width,height))
653 * @return bool true=取得成功、false=取得失敗
655 function parseImageFormat($format, &$imageType, &$imageAttr, &$imageSize)
657 $format = trim($format);
658 //$ret = preg_match('/(\d+)(.*)\.(gif|png|jpg|jpeg|bmp)$/i', $format, $matches);
659 $ret = preg_match('/(\d+)([xX]?)(\d*)(.*)\.(gif|png|jpg|jpeg|bmp)$/i', $format, $matches); // 「MMxNNc.jpg」タイプのフォーマットを解析
661 $imageSize = $matches[1];
662 $height = intval($matches[3]);
664 $imageSize = array('width' => $imageSize, 'height' => $height);
666 //$imageAttr = strtolower($matches[2]);
667 //$ext = strtolower($matches[3]);
668 $imageAttr = strtolower($matches[4]);
669 $ext = strtolower($matches[5]);
671 $imageType = IMAGETYPE_JPEG;
675 $imageType = IMAGETYPE_JPEG;
678 $imageType = IMAGETYPE_GIF;
681 $imageType = IMAGETYPE_PNG;
684 $imageType = IMAGETYPE_BMP;
691 * 画像未設定時に表示する画像のURLを取得
693 * @param string $type 画像のタイプ(ogp=OGP用サムネール)
694 * @return string 画像URL
696 function getNotAvailableImageUrl($type)
702 $url = $gEnvManager->getResourceUrl() . self::DEFAULT_THUMB_DIR . self::NOT_AVAILABLE_HEAD . $this->getDefaultOGPThumbFormat();
708 * 画像未設定時に表示する画像のパスを取得
710 * @param string $type 画像のタイプ(ogp=OGP用サムネール)
711 * @return string 画像URL
713 function getNotAvailableImagePath($type)
719 $path = $gEnvManager->getResourcePath() . self::DEFAULT_THUMB_DIR . self::NOT_AVAILABLE_HEAD . $this->getDefaultOGPThumbFormat();
727 * @param string $path 画像ファイル
728 * @param int $width 画像幅
729 * @param int $height 画像高さ
730 * @return bool true=取得,false=取得失敗
732 function getImageInfo($path, &$width, &$height)
734 $imageSize = @getimagesize($path);
736 $imageType = $imageSize[2];
737 $width = $imageSize[0];
738 $height = $imageSize[1];