@@ -10,65 +10,36 @@ class ImageUtils {
10
10
* @param int $maxWidth - maximum new width
11
11
* @param int $maxHeight - maximum new height
12
12
* @param string $targetDir - target directory
13
- * @return path of the new image file or NULL if it could not be created.
13
+ * @return string - the path of the new image file, e.g. /target/dir/basename.variation.png ( or NULL in case of GD issues)
14
14
*/
15
15
public static function createThumbnail ($ imagePath , $ maxWidth , $ maxHeight , $ targetDir = NULL ) {
16
- $ pathinfo = pathinfo ($ imagePath );
17
- $ targetPath = '. ' ;
18
- if ($ targetDir == NULL ) {
19
- $ targetPath = $ pathinfo ['dirname ' ].'/ ' .$ pathinfo ['filename ' ].'.thumbnail. ' ;
20
- } else {
21
- $ targetPath = $ targetDir .'/ ' .$ pathinfo ['filename ' ].'.thumbnail. ' ;
22
- }
23
- if (class_exists ('Imagick ' )) {
24
- $ image = new \Imagick ($ imagePath );
25
- $ image ->thumbnailImage ($ maxWidth , $ maxHeight , TRUE );
26
- $ targetPath .= 'png ' ;
27
- if (!$ image ->writeImage ($ targetPath )) {
28
- $ targetPath = NULL ;
29
- }
30
- } else {
31
- // We use GD
32
- $ imageDetails = getimagesize ($ imagePath );
33
- $ image = self ::readImage ($ imagePath , $ imageDetails );
34
- if ($ image != NULL ) {
35
- // Compute new dimensions
36
- $ size = self ::computeNewSize ($ imageDetails [0 ], $ imageDetails [1 ], $ maxWidth , $ maxHeight );
16
+ $ targetPath = self ::getNewPath ($ imagePath , 'thumbnail ' , $ targetDir );
37
17
38
- // Scale it
39
- $ thumbnail = imagecreatetruecolor ($ size ->width , $ size -height);
40
- imagecopyresized ($ thumbnail , $ image , 0 , 0 , 0 , 0 , $ size ->width , $ size ->height , $ imageDetails [0 ], $ imageDetails [1 ]);
41
- // Writing it
42
- $ gdInfo = gd_info ();
43
- // Preferential order PNG, JPEG, WEBP, XPM, WBMP, GIF, BMP
44
- if ($ gdInfo ['PNG Support ' ]) {
45
- $ targetPath .= 'png ' ;
46
- if (!imagepng ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
47
- } else if ($ gdInfo ['JPEG Support ' ]) {
48
- $ targetPath .= 'jpg ' ;
49
- if (!imagejpeg ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
50
- } else if ($ gdInfo ['WebP Support ' ]) {
51
- $ targetPath .= 'webp ' ;
52
- if (!imagewebp ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
53
- } else if ($ gdInfo ['XPM Support ' ]) {
54
- $ targetPath .= 'xpm ' ;
55
- if (!imagexbm ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
56
- } else if ($ gdInfo ['WBMP Support ' ]) {
57
- $ targetPath .= 'wbmp ' ;
58
- if (!imagewbmp ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
59
- } else if ($ gdInfo ['GIF Create Support ' ]) {
60
- $ targetPath .= 'gif ' ;
61
- if (!imagegif ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
62
- } else if ($ gdInfo ['BMP Support ' ]) {
63
- $ targetPath .= 'bmp ' ;
64
- if (!imagebmp ($ thumbnail , $ targetPath )) $ targetPath = NULL ;
65
- } else {
18
+ if ($ targetPath != NULL ) {
19
+ if (class_exists ('Imagick ' )) {
20
+ $ image = new \Imagick ($ imagePath );
21
+ $ image ->thumbnailImage ($ maxWidth , $ maxHeight , TRUE );
22
+ if (!$ image ->writeImage ($ targetPath )) {
66
23
$ targetPath = NULL ;
67
24
}
68
- imagedestroy ($ thumbnail );
69
- imagedestroy ($ image );
70
25
} else {
71
- $ targetPath = NULL ;
26
+ // We use GD
27
+ $ imageDetails = getimagesize ($ imagePath );
28
+ $ image = self ::readImage ($ imagePath , $ imageDetails );
29
+ if ($ image != NULL ) {
30
+ // Compute new dimensions
31
+ $ size = self ::computeNewSize ($ imageDetails [0 ], $ imageDetails [1 ], $ maxWidth , $ maxHeight );
32
+
33
+ // Scale it
34
+ $ thumbnail = imagecreatetruecolor ($ size ->width , $ size ->height );
35
+ imagecopyresized ($ thumbnail , $ image , 0 , 0 , 0 , 0 , $ size ->width , $ size ->height , $ imageDetails [0 ], $ imageDetails [1 ]);
36
+ // Writing it
37
+ $ targetPath = self ::writeImage ($ thumbnail , $ targetPath );
38
+ imagedestroy ($ thumbnail );
39
+ imagedestroy ($ image );
40
+ } else {
41
+ $ targetPath = NULL ;
42
+ }
72
43
}
73
44
}
74
45
return $ targetPath ;
@@ -130,6 +101,44 @@ public static function readImage($imagePath, $imageDetails = NULL) {
130
101
return NULL ;
131
102
}
132
103
104
+ /**
105
+ * Write an GD image to the specified path.
106
+ * @param resource $image - the GD image resource
107
+ * @param string $path - the path where to write to (must include the filetype extension)
108
+ * @return string - the path when writing was successful, NULL otherwise
109
+ */
110
+ public static function writeImage ($ image , $ path ) {
111
+ $ gdInfo = gd_info ();
112
+ $ ext = strtolower (pathinfo ($ path , PATHINFO_EXTENSION ));
113
+ switch ($ ext ) {
114
+ case 'png ' :
115
+ if (!imagepng ($ thumbnail , $ path )) $ path = NULL ;
116
+ break ;
117
+ case 'jpg ' :
118
+ case 'jpeg ' :
119
+ if (!imagejpeg ($ thumbnail , $ path )) $ path = NULL ;
120
+ break ;
121
+ case 'webp ' :
122
+ if (!imagewebp ($ thumbnail , $ path )) $ path = NULL ;
123
+ break ;
124
+ case 'xpm ' :
125
+ if (!imagexbm ($ thumbnail , $ path )) $ path = NULL ;
126
+ break ;
127
+ case 'wbmp ' :
128
+ if (!imagewbmp ($ thumbnail , $ path )) $ path = NULL ;
129
+ break ;
130
+ case 'gif ' :
131
+ if (!imagegif ($ thumbnail , $ path )) $ path = NULL ;
132
+ break ;
133
+ case 'bmp ' :
134
+ if (!imagebmp ($ thumbnail , $ path )) $ path = NULL ;
135
+ break ;
136
+ default :
137
+ $ path = NULL ;
138
+ }
139
+ return $ path ;
140
+ }
141
+
133
142
/**
134
143
* Returns an object with width and height attributes to resize.
135
144
* @param int $origWidth - original width
@@ -152,5 +161,145 @@ public static function computeNewSize($origWidth, $origHeight, $maxWidth, $maxHe
152
161
}
153
162
return $ rc ;
154
163
}
164
+
165
+ /**
166
+ * Cuts and scale the given image to new height and new width. The image will not be stretched or densed.
167
+ * @param string $imagePath - path of image to read from
168
+ * @param string $variation - The identifier to be included in the filename when writing the new image
169
+ * @param int $newHeight - new height of image
170
+ * @param int $newWidth - new width of image
171
+ * @param string $targetDir - target directory
172
+ * @return string the path to the new image file or NULL if action failed
173
+ * @return string - the path of the new image file, e.g. /target/dir/basename.variation.png (or NULL in case of GD issues)
174
+ */
175
+ public static function cropAndScale ($ imagePath , $ variation , $ newHeight , $ newWidth , $ options = NULL , $ targetDir = NULL ) {
176
+ $ targetPath = self ::getNewPath ($ imagePath , $ variation , $ targetDir );
177
+ if ($ options == NULL ) $ options = self ::cropAndScaleOptions ();
178
+
179
+ if ($ targetPath != NULL ) {
180
+ $ actions = NULL ;
181
+ if (class_exists ('Imagick ' )) {
182
+ $ image = new \Imagick ($ imagePath );
183
+ $ width = $ image ->getImageWidth ();
184
+ $ height = $ image ->getImageHeight ();
185
+ $ actions = self ::computeCropAndScale ($ width , $ height , $ newWidth , $ newHeight , $ options );
186
+ if ($ actions ->scale != 1 ) {
187
+ $ image ->scaleImage ($ actions ->factor * $ width , 0 );
188
+ }
189
+ if ($ image ->cropImage ($ actions ->width , $ actions ->height , $ actions ->x , $ actions ->y )) {
190
+ // Writing it
191
+ if (!$ image ->writeImage ($ targetPath )) {
192
+ $ targetPath = NULL ;
193
+ }
194
+ } else {
195
+ $ targetPath = NULL ;
196
+ }
197
+ } else {
198
+ // We use GD
199
+ $ imageDetails = getimagesize ($ imagePath );
200
+ $ actions = self ::computeCropAndScale ($ imageDetails [0 ], $ imageDetails [1 ], $ newWidth , $ newHeight , $ options );
201
+
202
+ // Scale it
203
+ $ target = imagecreatetruecolor ($ actions ->width , $ actions ->height );
204
+ imagecopyresized ($ target , $ image , 0 , 0 , $ actions ->x / $ actions ->factor , $ actions ->y / $ actions ->factor , $ newWidth , $ newHeight , $ imageDetails [0 ] / $ actions ->factor , $ imageDetails [1 ] / $ actions ->factor );
205
+ $ targetPath = self ::writeImage ($ target , $ targetPath );
206
+ imagedestroy ($ target );
207
+ imagedestroy ($ image );
208
+ }
209
+ }
210
+ return $ targetPath ;
211
+ }
212
+
213
+ /**
214
+ * Creates options for the cropAndScale() function.
215
+ * @param boolean $cropX - whether cropping width is permitted
216
+ * @param boolean $cropY - whether cropping height is permitted
217
+ * @param boolean $centerX - whether new image will be centered at X axis in case of cropping
218
+ * @param boolean $centerY - whether new image will be centered at Y axis in case of cropping
219
+ * @return object - the options for the cropAndScale() function
220
+ */
221
+ public static function cropAndScaleOptions ($ centerX = TRUE , $ centerY = FALSE ) {
222
+ $ rc = new \stdClass ;
223
+ $ rc ->centerX = $ centerX ;
224
+ $ rc ->centerY = $ centerY ;
225
+ return $ rc ;
226
+ }
227
+
228
+ public static function computeCropAndScale ($ origWidth , $ origHeight , $ maxWidth , $ maxHeight , $ options = NULL ) {
229
+ $ rc = new \stdClass ;
230
+ if ($ options == NULL ) $ options = self ::cropAndScaleOptions ();
231
+
232
+
233
+ // Assume X scaling to maxWidth
234
+ $ rc ->factor = $ maxWidth / $ origWidth ;
235
+
236
+ // Positioning for cropping
237
+ $ rc ->x = 0 ;
238
+ $ rc ->y = 0 ;
239
+
240
+ // Compute potential target
241
+ $ rc ->width = $ maxWidth ;
242
+ $ rc ->height = $ rc ->factor * $ origHeight ;
243
+ $ rc ->options = $ options ;
244
+
245
+ if ($ rc ->height < $ maxHeight ) {
246
+ // scale up and crop along X axis
247
+ $ rc ->factor = $ maxHeight / $ origHeight ;
248
+ $ rc ->width = $ rc ->factor * $ origWidth ;
249
+ $ rc ->height = $ maxHeight ;
250
+ if ($ options ->centerX ) {
251
+ $ rc ->x = ($ rc ->width - $ maxWidth ) / 2 ;
252
+ }
253
+ } else if ($ rc ->height > $ maxHeight ) {
254
+ if ($ options ->centerY ) {
255
+ $ rc ->y = ($ rc ->height - $ maxHeight ) / 2 ;
256
+ }
257
+ }
258
+ $ rc ->width = $ maxWidth ;
259
+ $ rc ->height = $ maxHeight ;
260
+
261
+ return $ rc ;
262
+ }
263
+
264
+ /**
265
+ * Computes the variation path of an image file using a priority: PNG, JPEG, WEBP, XPM, WBMP, GIF, BMP
266
+ * @param string $imagePath - the original image path
267
+ * @param string $variation - the identifier to be included in new filename
268
+ * @param string $targetDir - the target directory
269
+ * @return string - the new path of the image file, e.g. /target/dir/basename.variation.png (or NULL in case of GD issues)
270
+ */
271
+ public static function getNewPath ($ imagePath , $ variation , $ targetDir = NULL ) {
272
+ $ pathinfo = pathinfo ($ imagePath );
273
+ $ targetPath = '. ' ;
274
+ if ($ targetDir == NULL ) {
275
+ $ targetPath = $ pathinfo ['dirname ' ].'/ ' .$ pathinfo ['filename ' ].'. ' .$ variation .'. ' ;
276
+ } else {
277
+ $ targetPath = $ targetDir .'/ ' .$ pathinfo ['filename ' ].'. ' .$ variation .'. ' ;
278
+ }
279
+ if (class_exists ('Imagick ' )) {
280
+ $ targetPath .= 'png ' ;
281
+ } else {
282
+ $ gdInfo = gd_info ();
283
+ // Preferential order PNG, JPEG, WEBP, XPM, WBMP, GIF, BMP
284
+ if ($ gdInfo ['PNG Support ' ]) {
285
+ $ targetPath .= 'png ' ;
286
+ } else if ($ gdInfo ['JPEG Support ' ]) {
287
+ $ targetPath .= 'jpg ' ;
288
+ } else if ($ gdInfo ['WebP Support ' ]) {
289
+ $ targetPath .= 'webp ' ;
290
+ } else if ($ gdInfo ['XPM Support ' ]) {
291
+ $ targetPath .= 'xpm ' ;
292
+ } else if ($ gdInfo ['WBMP Support ' ]) {
293
+ $ targetPath .= 'wbmp ' ;
294
+ } else if ($ gdInfo ['GIF Create Support ' ]) {
295
+ $ targetPath .= 'gif ' ;
296
+ } else if ($ gdInfo ['BMP Support ' ]) {
297
+ $ targetPath .= 'bmp ' ;
298
+ } else {
299
+ $ targetPath = NULL ;
300
+ }
301
+ }
302
+ return $ targetPath ;
303
+ }
155
304
}
156
305
0 commit comments