1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
# ========================================================================# |
4
|
|
|
# |
5
|
|
|
# Author: Jarrod Oberto |
6
|
|
|
# Version: 1.0 |
7
|
|
|
# Date: 17-Jan-10 |
8
|
|
|
# Purpose: Resizes and saves image |
9
|
|
|
# Requires : Requires PHP5, GD library. |
10
|
|
|
# ========================================================================# |
11
|
|
|
namespace core\images; |
12
|
|
|
|
13
|
|
|
Class Resize |
14
|
|
|
{ |
15
|
|
|
// *** Class variables |
16
|
|
|
private $image; |
17
|
|
|
private $width; |
18
|
|
|
private $height; |
19
|
|
|
private $imageResized; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Resize constructor. |
23
|
|
|
* @param null|string $fileName |
24
|
|
|
*/ |
25
|
|
|
public function __construct($fileName) |
26
|
|
|
{ |
27
|
|
|
// *** Open up the file |
28
|
|
|
$this->image = $this->openImage($fileName); |
29
|
|
|
|
30
|
|
|
// *** Get width and height |
31
|
|
|
$this->width = imagesx($this->image); |
32
|
|
|
$this->height = imagesy($this->image); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
## -------------------------------------------------------- |
36
|
|
|
/** |
37
|
|
|
* @param null|string $file |
38
|
|
|
* @return bool|resource |
39
|
|
|
*/ |
40
|
|
|
private function openImage($file) |
41
|
|
|
{ |
42
|
|
|
// *** Get extension |
43
|
|
|
$extension = strtolower(strrchr($file, '.')); |
44
|
|
|
|
45
|
|
|
switch ($extension) |
46
|
|
|
{ |
47
|
|
|
case '.jpg': |
48
|
|
|
case '.jpeg': |
49
|
|
|
$img = @imagecreatefromjpeg($file); |
50
|
|
|
break; |
51
|
|
|
case '.gif': |
52
|
|
|
$img = @imagecreatefromgif($file); |
53
|
|
|
break; |
54
|
|
|
case '.png': |
55
|
|
|
$img = @imagecreatefrompng($file); |
56
|
|
|
break; |
57
|
|
|
default: |
58
|
|
|
$img = false; |
59
|
|
|
break; |
60
|
|
|
} |
61
|
|
|
return $img; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
## -------------------------------------------------------- |
65
|
|
|
|
66
|
|
|
public function resizeImage($newWidth, $newHeight, $option = "auto") |
67
|
|
|
{ |
68
|
|
|
// *** Get optimal width and height - based on $option |
69
|
|
|
$optionArray = $this->getDimensions($newWidth, $newHeight, $option); |
70
|
|
|
|
71
|
|
|
$optimalWidth = $optionArray['optimalWidth']; |
72
|
|
|
$optimalHeight = $optionArray['optimalHeight']; |
73
|
|
|
|
74
|
|
|
|
75
|
|
|
// *** Resample - create image canvas of x, y size |
76
|
|
|
$this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight); |
77
|
|
|
imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height); |
78
|
|
|
|
79
|
|
|
|
80
|
|
|
// *** if option is 'crop', then crop too |
81
|
|
|
if ($option == 'crop') { |
82
|
|
|
$this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight); |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
## -------------------------------------------------------- |
87
|
|
|
/** |
88
|
|
|
* @param $newWidth |
89
|
|
|
* @param $newHeight |
90
|
|
|
* @param string $option |
91
|
|
|
* @return array |
92
|
|
|
*/ |
93
|
|
|
private function getDimensions($newWidth, $newHeight, $option) |
94
|
|
|
{ |
95
|
|
|
|
96
|
|
|
switch ($option) |
97
|
|
|
{ |
98
|
|
|
case 'exact': |
99
|
|
|
$optimalWidth = $newWidth; |
100
|
|
|
$optimalHeight = $newHeight; |
101
|
|
|
break; |
102
|
|
|
case 'portrait': |
103
|
|
|
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
104
|
|
|
$optimalHeight = $newHeight; |
105
|
|
|
break; |
106
|
|
|
case 'landscape': |
107
|
|
|
$optimalWidth = $newWidth; |
108
|
|
|
$optimalHeight = $this->getSizeByFixedWidth($newWidth); |
109
|
|
|
break; |
110
|
|
View Code Duplication |
case 'auto': |
|
|
|
|
111
|
|
|
$optionArray = $this->getSizeByAuto($newWidth, $newHeight); |
112
|
|
|
$optimalWidth = $optionArray['optimalWidth']; |
113
|
|
|
$optimalHeight = $optionArray['optimalHeight']; |
114
|
|
|
break; |
115
|
|
View Code Duplication |
case 'crop': |
|
|
|
|
116
|
|
|
$optionArray = $this->getOptimalCrop($newWidth, $newHeight); |
117
|
|
|
$optimalWidth = $optionArray['optimalWidth']; |
118
|
|
|
$optimalHeight = $optionArray['optimalHeight']; |
119
|
|
|
break; |
120
|
|
|
default: |
121
|
|
|
$optimalWidth = ""; |
122
|
|
|
$optimalHeight = ""; |
123
|
|
|
break; |
124
|
|
|
} |
125
|
|
|
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
## -------------------------------------------------------- |
129
|
|
|
|
130
|
|
|
private function getSizeByFixedHeight($newHeight) |
131
|
|
|
{ |
132
|
|
|
$ratio = $this->width / $this->height; |
133
|
|
|
$newWidth = $newHeight * $ratio; |
134
|
|
|
return $newWidth; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
private function getSizeByFixedWidth($newWidth) |
138
|
|
|
{ |
139
|
|
|
$ratio = $this->height / $this->width; |
140
|
|
|
$newHeight = $newWidth * $ratio; |
141
|
|
|
return $newHeight; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
private function getSizeByAuto($newWidth, $newHeight) |
145
|
|
|
{ |
146
|
|
|
if ($this->height < $this->width) { |
147
|
|
|
// *** Image to be resized is wider (landscape) |
148
|
|
|
{ |
149
|
|
|
$optimalWidth = $newWidth; |
150
|
|
|
} |
151
|
|
|
$optimalHeight = $this->getSizeByFixedWidth($newWidth); |
152
|
|
|
} elseif ($this->height > $this->width) { |
153
|
|
|
// *** Image to be resized is taller (portrait) |
154
|
|
|
{ |
155
|
|
|
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
156
|
|
|
} |
157
|
|
|
$optimalHeight = $newHeight; |
158
|
|
|
} else |
159
|
|
|
// *** Image to be resizerd is a square |
160
|
|
|
{ |
161
|
|
|
if ($newHeight < $newWidth) { |
162
|
|
|
$optimalWidth = $newWidth; |
163
|
|
|
$optimalHeight = $this->getSizeByFixedWidth($newWidth); |
164
|
|
|
} else if ($newHeight > $newWidth) { |
165
|
|
|
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
166
|
|
|
$optimalHeight = $newHeight; |
167
|
|
|
} else { |
168
|
|
|
// *** Sqaure being resized to a square |
169
|
|
|
$optimalWidth = $newWidth; |
170
|
|
|
$optimalHeight = $newHeight; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
## -------------------------------------------------------- |
178
|
|
|
|
179
|
|
|
private function getOptimalCrop($newWidth, $newHeight) |
180
|
|
|
{ |
181
|
|
|
|
182
|
|
|
$heightRatio = $this->height / $newHeight; |
183
|
|
|
$widthRatio = $this->width / $newWidth; |
184
|
|
|
|
185
|
|
|
if ($heightRatio < $widthRatio) { |
186
|
|
|
$optimalRatio = $heightRatio; |
187
|
|
|
} else { |
188
|
|
|
$optimalRatio = $widthRatio; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
$optimalHeight = $this->height / $optimalRatio; |
192
|
|
|
$optimalWidth = $this->width / $optimalRatio; |
193
|
|
|
|
194
|
|
|
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
## -------------------------------------------------------- |
198
|
|
|
|
199
|
|
|
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight) |
200
|
|
|
{ |
201
|
|
|
// *** Find center - this will be used for the crop |
202
|
|
|
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2); |
203
|
|
|
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2); |
204
|
|
|
|
205
|
|
|
$crop = $this->imageResized; |
206
|
|
|
|
207
|
|
|
// *** Now crop from center to exact requested size |
208
|
|
|
$this->imageResized = imagecreatetruecolor($newWidth, $newHeight); |
209
|
|
|
imagecopyresampled($this->imageResized, $crop, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight, $newWidth, $newHeight); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
## -------------------------------------------------------- |
213
|
|
|
/** |
214
|
|
|
* @param string $savePath |
215
|
|
|
* @param string $imageQuality |
216
|
|
|
*/ |
217
|
|
|
public function saveImage($savePath, $imageQuality = "100") |
218
|
|
|
{ |
219
|
|
|
// *** Get extension |
220
|
|
|
$extension = strrchr($savePath, '.'); |
221
|
|
|
$extension = strtolower($extension); |
222
|
|
|
|
223
|
|
|
switch ($extension) |
224
|
|
|
{ |
225
|
|
|
case '.jpg': |
226
|
|
|
case '.jpeg': |
227
|
|
|
if (imagetypes() & IMG_JPG) { |
228
|
|
|
imagejpeg($this->imageResized, $savePath, $imageQuality); |
229
|
|
|
} |
230
|
|
|
break; |
231
|
|
|
|
232
|
|
|
case '.gif': |
233
|
|
|
if (imagetypes() & IMG_GIF) { |
234
|
|
|
imagegif($this->imageResized, $savePath); |
235
|
|
|
} |
236
|
|
|
break; |
237
|
|
|
|
238
|
|
|
case '.png': |
239
|
|
|
// *** Scale quality from 0-100 to 0-9 |
240
|
|
|
$scaleQuality = round(($imageQuality / 100) * 9); |
241
|
|
|
|
242
|
|
|
// *** Invert quality setting as 0 is best, not 9 |
243
|
|
|
$invertScaleQuality = 9 - $scaleQuality; |
244
|
|
|
|
245
|
|
|
if (imagetypes() & IMG_PNG) { |
246
|
|
|
imagepng($this->imageResized, $savePath, $invertScaleQuality); |
247
|
|
|
} |
248
|
|
|
break; |
249
|
|
|
|
250
|
|
|
// ... etc |
251
|
|
|
|
252
|
|
|
default: |
253
|
|
|
// *** No extension - No save. |
254
|
|
|
break; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
imagedestroy($this->imageResized); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
|
261
|
|
|
## -------------------------------------------------------- |
262
|
|
|
|
263
|
|
|
} |
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.