Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 16384 bytes) in /home/the-leaf/www/the-leaf.jp/code/lib/Tool/Trim.php on line 291

Debug Information (Developer Only) by Application::shutdownHandler()

Error File: /home/the-leaf/www/the-leaf.jp/code/lib/Tool/Trim.php
Error Line: 291
Error Message: Allowed memory size of 134217728 bytes exhausted (tried to allocate 16384 bytes)
1: <?php
2: /**
3: * Tool_Trimクラス
4: *
5: * 画像のリサイズ・トリミングを行うクラス
6: *
7: * @access public
8: * @author Lionheart Co., Ltd.
9: * @version 1.0.1
10: */
11: class Trim
12: {
13: private $_common = array(),
14: $org_data = NULL,
15: $org_image = NULL,
16: $org_mode = NULL,
17: $cnv_image = NULL,
18: $cnv_mode = NULL,
19: $org_path = NULL,
20: $cnv_path = NULL,
21: $exif = array(),
22: $jpeg_quality = 90;
23:
24: /**
25: * コンストラクタ
26: */
27: function __construct()
28: {
29: }
30:
31: /**
32: * 画像情報取得
33: *
34: * @param string $org_path
35: * @param string $cnv_path
36: */
37: function setImage( $org_path, $cnv_path )
38: {
39: if(! file_exists( $org_path ) ) {
40: exit( 'Not File' );
41: }
42:
43: // ファイルパスを変数に格納
44: $this->cnv_path = $cnv_path;
45: $this->cnv_mode = strtolower( pathinfo( $cnv_path, PATHINFO_EXTENSION ) );
46: $this->org_path = $org_path;
47:
48: // 変換タイプ、変換形式の整合性確認
49: if(
50: ! preg_match( '/jpg|gif|png/i', $this->cnv_mode )
51: ) {
52: exit( 'Error Extension' );
53: }
54:
55: // 画像サイズを取得
56: $this->org_data = array();
57: $info = getimagesize( $this->org_path, $finfo );
58: list( $this->org_data['width'], $this->org_data['height'] ) = $info;
59: $this->org_data['type'] = $info['mime'];
60:
61: switch( $this->org_data['type'] ) {
62: case "image/jpg":
63: case "image/jpe":
64: case "image/jpeg":
65: case "image/pjpeg":
66: $this->org_image = imagecreatefromjpeg( $this->org_path );
67: $this->org_mode = 'jpg';
68:
69: // Exif情報を取得しておく
70: if ( function_exists( 'exif_read_data' ) ) {
71: $this->exif = @exif_read_data( $this->org_path );
72: }
73: break;
74: case "image/gif":
75: $this->org_image = imagecreatefromgif( $this->org_path );
76: $this->org_mode = 'gif';
77: break;
78: case "image/png":
79: $this->org_image = imagecreatefrompng( $this->org_path );
80: $this->org_mode = 'png';
81: break;
82: default:
83: die( "NotImage" );
84: break;
85: }
86:
87: // Exif情報に回転情報が入っている場合は回転する
88: if( isset( $this->exif['Orientation'] ) ) {
89: switch( $this->exif['Orientation'] ) {
90: case 2:
91: // 水平反転
92: flip_horizontal( $this->org_image );
93: break;
94: case 3:
95: // 180度回転
96: $this->org_image = imagerotate( $this->org_image, 180, 0 );
97: break;
98: case 4:
99: // 180度回転して水平反転
100: $this->org_image = imagerotate( $this->org_image, 180, 0 );
101: flip_horizontal( $this->org_image );
102: break;
103: case 5:
104: // 時計回りに90度回転して水平反転
105: $this->org_image = imagerotate( $this->org_image, 270, 0 );
106: flip_horizontal( $this->org_image );
107: $tmpWidth = $this->org_data['width'];
108: $this->org_data['width'] = $this->org_data['height'];
109: $this->org_data['height'] = $tmpWidth;
110: break;
111: case 6:
112: // 時計回りに90度回転
113: $this->org_image = imagerotate( $this->org_image, 270, 0 );
114: $tmpWidth = $this->org_data['width'];
115: $this->org_data['width'] = $this->org_data['height'];
116: $this->org_data['height'] = $tmpWidth;
117: break;
118: case 7:
119: // 時計回りに270度回転して水平反転
120: $this->org_image = imagerotate( $this->org_image, 90, 0 );
121: flip_horizontal( $this->org_image );
122: $tmpWidth = $this->org_data['width'];
123: $this->org_data['width'] = $this->org_data['height'];
124: $this->org_data['height'] = $tmpWidth;
125: break;
126: case 8:
127: // 時計回りに270度回転
128: $this->org_image = imagerotate( $this->org_image, 90, 0 );
129: $tmpWidth = $this->org_data['width'];
130: $this->org_data['width'] = $this->org_data['height'];
131: $this->org_data['height'] = $tmpWidth;
132: break;
133: case 1:
134: default:
135: // そのまま
136: break;
137: }
138: }
139: }
140:
141:
142: /**
143: * 比率を保持してリサイズ
144: *
145: * @param integer $w
146: * @param integer $h
147: */
148: public function resize( $w, $h )
149: {
150: $w = $w > 0 ? $w : $this->org_data["width"];
151: $h = $h > 0 ? $h : $this->org_data["height"];
152:
153: $sw = $w/$this->org_data["width"];
154: $sh = $h/$this->org_data["height"];
155: if( $sw < 1 || $sh < 1 ) {
156: if( $sw <= $sh ) {
157: $h = $this->org_data["height"]*$sw;
158: } else {
159: $w = $this->org_data["width"]*$sh;
160: }
161: } else {
162: $w = $this->org_data["width"];
163: $h = $this->org_data["height"];
164: }
165:
166: $this->_makeThumbnail( $w, $h, $w, $h, $this->org_data["width"], $this->org_data["height"] );
167: }
168:
169: /**
170: * 比率を保持してリサイズ(足りない部分は透明 or 白に)
171: *
172: * @param integer $w
173: * @param integer $h
174: */
175: public function resizeFill( $w, $h )
176: {
177: $w = $w > 0 ? $w : $this->org_data["width"];
178: $h = $h > 0 ? $h : $this->org_data["height"];
179:
180: $sw = $w/$this->org_data["width"];
181: $sh = $h/$this->org_data["height"];
182:
183: if( $sw < 1 || $sh < 1 ) {
184: if( $sw <= $sh ) {
185: $iw = $w;
186: $ih = $this->org_data["height"]*$sw;
187: } else {
188: $iw = $this->org_data["width"]*$sh;
189: $ih = $h;
190: }
191: } else {
192: $iw = $this->org_data["width"];
193: $ih = $this->org_data["height"];
194: }
195:
196: $pos[0] = ( $w-$iw ) /2;
197: $pos[1] = ( $h-$ih ) /2;
198:
199: $this->_makeThumbnail( $w, $h, $iw, $ih, $this->org_data["width"], $this->org_data["height"], $pos[0], $pos[1] );
200: }
201:
202: /**
203: * 比率を無視してリサイズ
204: *
205: * @param integer $w
206: * @param integer $h
207: */
208: public function resizeForce( $w, $h )
209: {
210: $w = $w > 0 ? $w : $this->org_data["width"];
211: $h = $h > 0 ? $h : $this->org_data["height"];
212:
213: $this->_makeThumbnail( $w, $h, $w, $h, $this->org_data["width"], $this->org_data["height"] );
214: }
215:
216: /**
217: * リサイズして指定位置でトリミング
218: *
219: * @param integer $w
220: * @param integer $h
221: */
222: public function resizeTrim( $w, $h, $cp )
223: {
224: $w = $w > 0 ? $w : $this->org_data["width"];
225: $h = $h > 0 ? $h : $this->org_data["height"];
226:
227: $sw = $w/$this->org_data["width"];
228: $sh = $h/$this->org_data["height"];
229:
230: $scale = $sw <= $sh ? $sh : $sw;
231:
232: $cpW = floor( $w / $scale );
233: $cpH = floor( $h / $scale );
234:
235: $rightX = $this->org_data["width"]-$cpW;
236: $centerX = $rightX - ( $this->org_data["width"]-$cpW )/2;
237: $bottomY = $this->org_data["height"]-$cpH;
238: $centerY = $bottomY - ( $this->org_data["height"]-$cpH )/2;
239:
240: switch( $cp ) {
241: case 't':
242: $pos = array( $centerX, 0 );
243: break;
244: case 'rt':
245: $pos = array( $rightX, 0 );
246: break;
247: case 'l':
248: $pos = array( 0, $centerY );
249: break;
250: case 'm':
251: $pos = array( $centerX, $centerY );
252: break;
253: case 'r':
254: $pos = array( $rightX, $centerY );
255: break;
256: case 'lb':
257: $pos = array( 0, $centerY );
258: break;
259: case 'b':
260: $pos = array( $centerX, $bottomY );
261: break;
262: case 'rb':
263: $pos = array( $centerX, $bottomY );
264: break;
265: case 'lt':
266: $pos = array( $rightX, $bottomY );
267: default:
268: $pos = array( 0, 0 );
269: break;
270: }
271:
272: $this->_makeThumbnail( $w, $h, $w, $h, $cpW, $cpH, 0, 0, $pos[0], $pos[1] );
273: }
274:
275: /**
276: * サムネイル作成
277: *
278: * @param integer $cw 生成する画像の横幅
279: * @param integer $ch 生成する画像の縦幅
280: * @param integer $tw 貼り付ける横幅
281: * @param integer $th 貼り付ける縦幅
282: * @param integer $fw 元画像から切り出す横幅
283: * @param integer $fh 元画像から切り出す縦幅
284: * @param integer $tx 生成する画像に貼り付けるx座標
285: * @param integer $ty 生成する画像に貼り付けるy座標
286: * @param integer $tx 元画像にコピーを開始するx座標
287: * @param integer $ty 元画像にコピーを開始するy座標
288: */
289: private function _makeThumbnail( $cw, $ch, $tw, $th, $fw, $fh, $tx=0, $ty=0, $fx=0, $fy=0 )
290: {
291: $this->cnv_image = imagecreatetruecolor( $cw, $ch );
292:
293: // 元画像がJPG / GIFの時
294: if( $this->org_mode === 'jpg' || $this->org_mode === 'gif' ) {
295: // 変換先がJPGなら背景は白に
296: if( $this->cnv_mode === 'jpg' ) {
297: // 背景を白に
298: $bg_color = imagecolorallocate( $this->cnv_image, 255, 255, 255 );
299: imagefill( $this->cnv_image, 0, 0, $bg_color );
300: } else {
301: $alpha = imagecolortransparent( $this->org_image ); // 元画像から透過色を取得する
302: imagefill( $this->cnv_image, 0, 0, $alpha ); // その色でキャンバスを塗りつぶす
303: imagecolortransparent( $this->cnv_image, $alpha ); // 塗りつぶした色を透過色として指定する
304: }
305: // 元画像がPNGの時
306: } else if( $this->org_mode === 'png' ) {
307: // 変換先がJPG、GIFなら背景は白に
308: // PNG -> GIFの変換時に他の要素まで透明にする危険性があるため
309: if( $this->cnv_mode === 'jpg' || $this->cnv_mode === 'gif' ) {
310: // 背景を白に
311: $bg_color = imagecolorallocate( $this->cnv_image, 255, 255, 255 );
312: imagefill( $this->cnv_image, 0, 0, $bg_color );
313: } else {
314: // 透明背景化
315: $bg_color = imagecolorallocatealpha( $this->cnv_image, 255, 255, 255, 127 );
316: imagefill( $this->cnv_image, 0, 0, $bg_color );
317: //ブレンドモードを無効にする
318: imagealphablending( $this->cnv_image, false );
319: //完全なアルファチャネル情報を保存するフラグをonにする
320: imagesavealpha( $this->cnv_image, true );
321: }
322: }
323:
324: imagecopyresampled(
325: $this->cnv_image, //貼り付けするイメージID
326: $this->org_image, //コピーする元になるイメージID
327: $tx, //int dstX (貼り付けを開始するX座標)
328: $ty, //int dstY (貼り付けを開始するY座標)
329: $fx, //int srcX (コピーを開始するX座標)
330: $fy, //int srcY (コピーを開始するY座標)
331: $tw, //int dstW (貼り付けする幅)
332: $th, //int dstH (貼り付けする高さ)
333: $fw, //int srcW (コピーする幅)
334: $fh //int srcH (コピーする高さ)
335: );
336: }
337:
338: /**
339: * 指定パスに画像登録
340: */
341: public function create()
342: {
343: if(! file_exists( dirname( $this->cnv_path ) ) ) {
344: @mkdir( dirname( $this->cnv_path ), 0777, TRUE );
345: }
346:
347: switch( $this->cnv_mode ) {
348: case 'jpg':
349: imagejpeg( $this->cnv_image, $this->cnv_path, $this->jpeg_quality );
350: break;
351: case 'png':
352: imagepng( $this->cnv_image, $this->cnv_path );
353: break;
354: case 'gif':
355: imagegif( $this->cnv_image, $this->cnv_path );
356: break;
357: }
358: }
359:
360: /**
361: * 生成画像表示
362: */
363: public function view()
364: {
365: if(! file_exists( $this->cnv_path ) ) {
366: return;
367: }
368:
369: switch( $this->cnv_mode ) {
370: case 'jpg':
371: header("Content-type: image/jpeg");
372: break;
373: case 'png':
374: header("Content-type: image/png");
375: break;
376: case 'gif':
377: header("Content-type: image/gif");
378: break;
379: }
380:
381: // 表示
382: echo file_get_contents( $this->cnv_path );
383: }
384:
385: /**
386: * デストラクタ
387: */
388: function __destruct()
389: {
390: // 削除
391: if( $this->cnv_image ) {
392: imagedestroy( $this->cnv_image );
393: }
394: if( $this->org_image ) {
395: imagedestroy( $this->org_image );
396: }
397: }
398: }
399:
400: /**
401: * GDライブラリの反転拡張
402: * via: https://gist.github.com/kijtra/990417
403: */
404:
405: //縦反転
406: function flip_vertical(&$imgsrc){
407: // PHP5.5以上であればimageflipがあるので使う
408: if( function_exists( 'imageflip' ) ) {
409: imageflip( $imgsrc, IMG_FLIP_VERTICAL );
410: return;
411: }
412:
413: $x=imagesx($imgsrc);
414: $y=imagesy($imgsrc);
415: $flip=imagecreatetruecolor($x,$y);
416: if(imagecopyresampled($flip,$imgsrc,0,0,0,$y-1,$x,$y,$x,0-$y)){
417: $imgsrc = $flip;
418: }
419: }
420:
421: //横反転
422: function flip_horizontal(&$imgsrc){
423: // PHP5.5以上であればimageflipがあるので使う
424: if( function_exists( 'imageflip' ) ) {
425: imageflip( $imgsrc, IMG_FLIP_HORIZONTAL );
426: return;
427: }
428:
429: $x=imagesx($imgsrc);
430: $y=imagesy($imgsrc);
431: $flip=imagecreatetruecolor($x,$y);
432: if(imagecopyresampled($flip,$imgsrc,0,0,$x-1,0,$x,$y,0-$x,$y)){
433: $imgsrc = $flip;
434: }
435: }
436: