1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace ContentsFile\Model\Behavior\Traits; |
4
|
|
|
|
5
|
|
|
use Cake\Core\Configure; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* ImageContentsFileBehaviorTrait |
9
|
|
|
* 画像関係の処理 |
10
|
|
|
*/ |
11
|
|
|
trait ImageContentsFileBehaviorTrait |
12
|
|
|
{ |
13
|
|
|
private $tp; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* imageResize |
17
|
|
|
* 画像のリサイズ処理(外からでもたたけるようにpublicにする |
18
|
|
|
* @author hagiwara |
19
|
|
|
* @param string $imagePath |
20
|
|
|
* @param array $baseSize |
21
|
|
|
* @return bool |
22
|
|
|
*/ |
23
|
|
|
public function imageResize(string $imagePath, array $baseSize): bool |
24
|
|
|
{ |
25
|
|
|
$imageInfo = $this->getImageInfo($imagePath); |
26
|
|
|
$image = $imageInfo['image']; |
27
|
|
|
$imagetype = $imageInfo['imagetype']; |
28
|
|
|
if (!$image) { |
29
|
|
|
// 画像の読み込み失敗 |
30
|
|
|
return false; |
31
|
|
|
} |
32
|
|
|
// // 画像の縦横サイズを取得 |
33
|
|
|
$imageSizeInfo = $this->imageSizeInfo($image, $baseSize); |
34
|
|
|
|
35
|
|
|
return $this->imageResizeMake($image, $imagetype, $imagePath, $baseSize, $imageSizeInfo); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* getImageInfo |
40
|
|
|
* 画像情報の取得 |
41
|
|
|
* @author hagiwara |
42
|
|
|
* @param string $imagePath |
43
|
|
|
* @return bool|array |
44
|
|
|
*/ |
45
|
|
|
private function getImageInfo(string $imagePath) |
46
|
|
|
{ |
47
|
|
|
if (file_exists($imagePath) === false) { |
48
|
|
|
return false; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
$imagetype = exif_imagetype($imagePath); |
52
|
|
|
if ($imagetype === false) { |
53
|
|
|
return false; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
// 画像読み込み |
57
|
|
|
switch ($imagetype) { |
58
|
|
|
case IMAGETYPE_GIF: |
59
|
|
|
$image = ImageCreateFromGIF($imagePath); |
60
|
|
|
break; |
61
|
|
|
case IMAGETYPE_JPEG: |
62
|
|
|
$image = ImageCreateFromJPEG($imagePath); |
63
|
|
|
break; |
64
|
|
|
case IMAGETYPE_PNG: |
65
|
|
|
$image = ImageCreateFromPNG($imagePath); |
66
|
|
|
break; |
67
|
|
|
default: |
68
|
|
|
$image = false; |
69
|
|
|
} |
70
|
|
|
return [ |
71
|
|
|
'image' => $image, |
72
|
|
|
'imagetype' => $imagetype, |
73
|
|
|
]; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* imageSizeInfo |
78
|
|
|
* 画像リサイズ情報の取得 |
79
|
|
|
* @author hagiwara |
80
|
|
|
* @param resource $image |
81
|
|
|
* @param array $baseSize |
82
|
|
|
* @return array |
83
|
|
|
*/ |
84
|
|
|
private function imageSizeInfo($image, array $baseSize): array |
85
|
|
|
{ |
86
|
|
|
// 画像の縦横サイズを取得 |
87
|
|
|
$sizeX = ImageSX($image); |
88
|
|
|
$sizeY = ImageSY($image); |
89
|
|
|
// リサイズ後のサイズ |
90
|
|
|
if (!array_key_exists('height', $baseSize)) { |
91
|
|
|
$baseSize['height'] = 0; |
92
|
|
|
} |
93
|
|
|
if (!array_key_exists('width', $baseSize)) { |
94
|
|
|
$baseSize['width'] = 0; |
95
|
|
|
} |
96
|
|
|
// リサイズ種別 |
97
|
|
|
if (!array_key_exists('type', $baseSize)) { |
98
|
|
|
$baseSize['type'] = 'normal'; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
if ($baseSize['type'] == 'normal_s' || $baseSize['type'] == 'scoop') { |
102
|
|
|
// 短い方基準もしくは、くりぬき |
103
|
|
View Code Duplication |
if (empty($baseSize['width']) || !empty($baseSize['height']) && $sizeX * $baseSize['height'] < $sizeY * $baseSize['width']) { |
|
|
|
|
104
|
|
|
// 縦基準 |
105
|
|
|
$mag = $baseSize['width'] / $sizeX; |
106
|
|
|
$reSizeX = $baseSize['width']; |
107
|
|
|
$reSizeY = $sizeY * $mag; |
108
|
|
|
} else { |
109
|
|
|
// 横基準 |
110
|
|
|
$mag = $baseSize['height'] / $sizeY; |
111
|
|
|
$reSizeY = $baseSize['height']; |
112
|
|
|
$reSizeX = $sizeX * $mag; |
113
|
|
|
} |
114
|
|
View Code Duplication |
} else { |
|
|
|
|
115
|
|
|
// 長い方基準 |
116
|
|
|
if (empty($baseSize['width']) || !empty($baseSize['height']) && $sizeX * $baseSize['height'] < $sizeY * $baseSize['width']) { |
117
|
|
|
// 縦基準 |
118
|
|
|
$mag = $baseSize['height'] / $sizeY; |
119
|
|
|
$reSizeY = $baseSize['height']; |
120
|
|
|
$reSizeX = $sizeX * $mag; |
121
|
|
|
} else { |
122
|
|
|
// 横基準 |
123
|
|
|
$mag = $baseSize['width'] / $sizeX; |
124
|
|
|
$reSizeX = $baseSize['width']; |
125
|
|
|
$reSizeY = $sizeY * $mag; |
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
return [ |
129
|
|
|
'sizeX' => $sizeX, |
130
|
|
|
'sizeY' => $sizeY, |
131
|
|
|
'reSizeX' => $reSizeX, |
132
|
|
|
'reSizeY' => $reSizeY, |
133
|
|
|
'type' => $baseSize['type'], |
134
|
|
|
]; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* imageResizeMake |
139
|
|
|
* 画像リサイズ情報の取得 |
140
|
|
|
* @author hagiwara |
141
|
|
|
* @param resource $image |
142
|
|
|
* @param int $imagetype |
143
|
|
|
* @param string $imagePath |
144
|
|
|
* @param array $baseSize |
145
|
|
|
* @param array $imageSizeInfo |
146
|
|
|
*/ |
147
|
|
|
private function imageResizeMake($image, int $imagetype, string $imagePath, array $baseSize, array $imageSizeInfo): bool |
148
|
|
|
{ |
149
|
|
|
// サイズ変更後の画像データを生成 |
150
|
|
|
$campusX = $imageSizeInfo['reSizeX']; |
151
|
|
|
$campusY = $imageSizeInfo['reSizeY']; |
152
|
|
|
// くりぬきの場合(幅と高さが両方必要) |
153
|
|
|
if ($imageSizeInfo['type'] == 'scoop' && !empty($baseSize['width']) && !empty($baseSize['height'])) { |
154
|
|
|
$campusX = $baseSize['width']; |
155
|
|
|
$campusY = $baseSize['height']; |
156
|
|
|
} |
157
|
|
|
$outImage = ImageCreateTrueColor($campusX, $campusY); |
158
|
|
|
if (!$outImage) { |
159
|
|
|
// リサイズ後の画像作成失敗 |
160
|
|
|
return false; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
switch ($imagetype) { |
164
|
|
|
case IMAGETYPE_GIF: |
165
|
|
|
//透過GIF対策 |
166
|
|
|
$alpha = imagecolortransparent($image); // 元画像から透過色を取得する |
167
|
|
|
imagefill($outImage, 0, 0, $alpha); // その色でキャンバスを塗りつぶす |
168
|
|
|
imagecolortransparent($outImage, $alpha); // 塗りつぶした色を透過色として指定する |
169
|
|
|
//!透過GIF対策 |
170
|
|
|
break; |
171
|
|
|
case IMAGETYPE_PNG: |
172
|
|
|
//透過PNG対策 |
173
|
|
|
//ブレンドモードを無効にする |
174
|
|
|
imagealphablending($outImage, false); |
175
|
|
|
//完全なアルファチャネル情報を保存するフラグをonにする |
176
|
|
|
imagesavealpha($outImage, true); |
177
|
|
|
//!透過PNG対策 |
178
|
|
|
break; |
179
|
|
|
default: |
180
|
|
|
break; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
$diffX = 0; |
184
|
|
|
$diffY = 0; |
185
|
|
|
// くりぬきの場合(幅と高さが両方必要) |
186
|
|
|
if ($imageSizeInfo['type'] == 'scoop' && !empty($baseSize['width']) && !empty($baseSize['height'])) { |
187
|
|
|
$diffX = ($imageSizeInfo['sizeX'] - ($baseSize['width'] * $imageSizeInfo['sizeX'] / $imageSizeInfo['reSizeX'])) / 2; |
188
|
|
|
$diffY = ($imageSizeInfo['sizeY'] - ($baseSize['height'] * $imageSizeInfo['sizeY'] / $imageSizeInfo['reSizeY'])) / 2; |
189
|
|
|
} |
190
|
|
|
$ret = imagecopyresampled($outImage, $image, 0, 0, $diffX, $diffY, $imageSizeInfo['reSizeX'], $imageSizeInfo['reSizeY'], $imageSizeInfo['sizeX'], $imageSizeInfo['sizeY']); |
191
|
|
|
if ($ret === false) { |
192
|
|
|
// リサイズ失敗 |
193
|
|
|
return false; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
ImageDestroy($image); |
197
|
|
|
|
198
|
|
|
// 画像保存 |
199
|
|
|
$imagepathinfo = $this->getPathInfo($imagePath, $baseSize); |
200
|
|
|
//resizeファイルを格納するディレクトリを作成 |
201
|
|
|
if ( |
202
|
|
|
!$this->mkdir($imagepathinfo['resize_dir'], 0777, true) |
|
|
|
|
203
|
|
|
) { |
204
|
|
|
return false; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
switch ($imagetype) { |
208
|
|
|
case IMAGETYPE_GIF: |
209
|
|
|
ImageGIF($outImage, $imagepathinfo['resize_filepath']); |
210
|
|
|
break; |
211
|
|
|
case IMAGETYPE_JPEG: |
212
|
|
|
ImageJPEG($outImage, $imagepathinfo['resize_filepath'], 100); |
213
|
|
|
break; |
214
|
|
|
case IMAGETYPE_PNG: |
215
|
|
|
ImagePNG($outImage, $imagepathinfo['resize_filepath']); |
216
|
|
|
break; |
217
|
|
|
default: |
218
|
|
|
return false; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
ImageDestroy($outImage); |
222
|
|
|
|
223
|
|
|
return true; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* getPathInfo |
228
|
|
|
* 通常のpathinfoに加えてContentsFile独自のpathも一緒に設定する |
229
|
|
|
* @author hagiwara |
230
|
|
|
* @param string $imagePath |
231
|
|
|
* @param array $resize |
232
|
|
|
* @return array |
233
|
|
|
*/ |
234
|
|
|
public function getPathInfo(string $imagePath, array $resize = []): array |
235
|
|
|
{ |
236
|
|
|
$pathinfo = pathinfo($imagePath); |
237
|
|
|
$pathinfo['resize_dir'] = $pathinfo['dirname'] . '/contents_file_resize_' . $pathinfo['filename']; |
238
|
|
|
//一旦ベースのパスを通しておく |
239
|
|
|
$pathinfo['resize_filepath'] = $imagePath; |
240
|
|
|
if (!empty($resize)) { |
241
|
|
|
if (!isset($resize['width'])) { |
242
|
|
|
$resize['width'] = 0; |
243
|
|
|
} |
244
|
|
|
if (!isset($resize['height'])) { |
245
|
|
|
$resize['height'] = 0; |
246
|
|
|
} |
247
|
|
|
if (!isset($resize['type'])) { |
248
|
|
|
$resize['type'] = 'normal'; |
249
|
|
|
} |
250
|
|
|
$pathinfo['resize_filepath'] = $pathinfo['resize_dir'] . '/' . $resize['width'] . '_' . $resize['height'] . '_' . $resize['type']; |
251
|
|
|
if (Configure::read('ContentsFile.Setting.ext') === true) { |
252
|
|
|
$ext = (new \SplFileInfo($imagePath))->getExtension(); |
253
|
|
|
$pathinfo['resize_filepath'] .= '.' . $ext; |
254
|
|
|
} |
255
|
|
|
} |
256
|
|
|
return $pathinfo; |
257
|
|
|
} |
258
|
|
|
} |
259
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.