Total Complexity | 103 |
Total Lines | 687 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like Image often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Image, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
26 | class Image |
||
27 | { |
||
28 | protected static $supportedExtensions = array('jpg', 'jpeg', 'gif', 'png'); |
||
29 | |||
30 | /** |
||
31 | * Image width. |
||
32 | * |
||
33 | * @var int $witdh |
||
34 | */ |
||
35 | protected $width; |
||
36 | |||
37 | /** |
||
38 | * Image height. |
||
39 | * |
||
40 | * @var int $height |
||
41 | */ |
||
42 | protected $height; |
||
43 | |||
44 | /** |
||
45 | * Image MIME type. |
||
46 | * |
||
47 | * @var string $mime |
||
48 | */ |
||
49 | protected $mime; |
||
50 | |||
51 | /** |
||
52 | * Number of bits for each color. |
||
53 | * |
||
54 | * @var string $mime |
||
55 | */ |
||
56 | protected $bits; |
||
57 | |||
58 | /** |
||
59 | * Number of color channels (i.e. 3 for RGB pictures and 4 for CMYK pictures). |
||
60 | * |
||
61 | * @var int $channels |
||
62 | */ |
||
63 | protected $channels; |
||
64 | |||
65 | /** |
||
66 | * GD image. |
||
67 | * |
||
68 | * @var resource $gdImage |
||
69 | */ |
||
70 | protected $gdImage; |
||
71 | |||
72 | /** |
||
73 | * The size of the image produced by the `getData()` method. |
||
74 | * |
||
75 | * @var int $dataSize |
||
76 | */ |
||
77 | protected $dataSize; |
||
78 | |||
79 | /** |
||
80 | * Quality of rescaled image. |
||
81 | * |
||
82 | * @var int |
||
83 | */ |
||
84 | protected $resizeQuality; |
||
85 | |||
86 | /** |
||
87 | * The factory method. |
||
88 | * |
||
89 | * @param string $data |
||
90 | * @param bool $bmpSupport |
||
91 | * |
||
92 | * @return Image |
||
93 | */ |
||
94 | public static function create($data, $bmpSupport = false) |
||
95 | { |
||
96 | return new Image($data, $bmpSupport); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Parses the image size from a string in the form of `[width]x[height]`, |
||
101 | * for example 278x219. |
||
102 | * |
||
103 | * @param string $size WxH string |
||
104 | * |
||
105 | * @return array An array with width and height values array([width], [height]), |
||
106 | * for the example above: array(278, 219). |
||
107 | */ |
||
108 | public static function parseSize($size) |
||
109 | { |
||
110 | $sizeParts = explode('x', trim($size)); |
||
111 | |||
112 | return count($sizeParts) === 2 ? array_map('intval', $sizeParts) : array(0, 0); |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Checks if a given exception is supported by the Image class. |
||
117 | * |
||
118 | * @param string $extension |
||
119 | * @param bool $bmpSupport |
||
120 | * |
||
121 | * @return bool |
||
122 | */ |
||
123 | public static function isSupportedExtension($extension, $bmpSupport = false) |
||
124 | { |
||
125 | $supportedExtensions = static::$supportedExtensions; |
||
126 | |||
127 | if ($bmpSupport) { |
||
128 | $supportedExtensions[] = 'bmp'; |
||
129 | } |
||
130 | |||
131 | return in_array(strtolower($extension), $supportedExtensions); |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Returns the MIME type for a given extension. |
||
136 | * |
||
137 | * @param string $extension |
||
138 | * |
||
139 | * @return string MIME type |
||
140 | */ |
||
141 | public static function mimeTypeFromExtension($extension) |
||
142 | { |
||
143 | $extensionMimeTypeMap = array( |
||
144 | 'gif' => 'image/gif', |
||
145 | 'jpg' => 'image/jpeg', |
||
146 | 'jpeg' => 'image/jpeg', |
||
147 | 'bmp' => 'image/bmp', |
||
148 | 'png' => 'image/png', |
||
149 | 'wbmp' => 'image/wbmp' |
||
150 | ); |
||
151 | |||
152 | $extension = strtolower($extension); |
||
153 | |||
154 | return array_key_exists($extension, $extensionMimeTypeMap) ? $extensionMimeTypeMap[$extension] : null; |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Constructor. |
||
159 | * |
||
160 | * @param string $imageData image data |
||
161 | * @param bool $bmpSupport `true` if bitmaps are supported (be aware of poor efficiency!). |
||
162 | * |
||
163 | * @throws CKFinderException in case the image could not be initialized properly. |
||
164 | */ |
||
165 | |||
166 | public function __construct($imageData, $bmpSupport = false) |
||
167 | { |
||
168 | if (!extension_loaded('gd')) { |
||
169 | throw new CKFinderException('PHP GD library not found'); |
||
170 | } |
||
171 | |||
172 | $imgInfo = @getimagesizefromstring($imageData); |
||
173 | |||
174 | if ($imgInfo === false) { |
||
175 | throw new CKFinderException('Unsupported image type'); |
||
176 | } |
||
177 | |||
178 | $this->width = isset($imgInfo[0]) ? $imgInfo[0] : 0; |
||
179 | $this->height = isset($imgInfo[1]) ? $imgInfo[1] : 0; |
||
180 | $this->mime = isset($imgInfo['mime']) ? $imgInfo['mime'] : ''; |
||
181 | $this->bits = isset($imgInfo['bits']) ? $imgInfo['bits'] : 8; |
||
182 | $this->channels = isset($imgInfo['channels']) ? $imgInfo['channels'] : 3; |
||
183 | $this->dataSize = strlen($imageData); |
||
184 | |||
185 | if (!$this->width || !$this->height || !$this->mime) { |
||
186 | throw new CKFinderException('Unsupported image type'); |
||
187 | } |
||
188 | |||
189 | $this->setMemory($this->width, $this->height, $this->bits, $this->channels); |
||
190 | |||
191 | $gdSupportedTypes = @imagetypes(); |
||
192 | |||
193 | $supportedFormats = array( |
||
194 | 'image/gif' => $gdSupportedTypes & IMG_GIF, |
||
195 | 'image/jpeg' => $gdSupportedTypes & IMG_JPG, |
||
196 | 'image/png' => $gdSupportedTypes & IMG_PNG, |
||
197 | 'image/wbmp' => $gdSupportedTypes & IMG_WBMP, |
||
198 | 'image/bmp' => $bmpSupport && ($gdSupportedTypes & IMG_JPG), |
||
199 | 'image/x-ms-bmp' => $bmpSupport && ($gdSupportedTypes & IMG_JPG) |
||
200 | ); |
||
201 | |||
202 | if (!array_key_exists($this->mime, $supportedFormats) || !$supportedFormats[$this->mime]) { |
||
203 | throw new CKFinderException('Unsupported image type: ' . $this->mime); |
||
204 | } |
||
205 | |||
206 | if ($this->mime === 'image/bmp' || $this->mime === 'image/x-ms-bmp') { |
||
207 | $this->gdImage = $this->createFromBmp($imageData); |
||
208 | } else { |
||
209 | $this->gdImage = imagecreatefromstring($imageData); |
||
|
|||
210 | } |
||
211 | |||
212 | if (!is_resource($this->gdImage)) { |
||
213 | throw new CKFinderException('Unsupported image type (not resource): ' . $this->mime); |
||
214 | } |
||
215 | |||
216 | unset($imageData); |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Returns the aspect ratio size as associative array: |
||
221 | * @code |
||
222 | * array |
||
223 | * ( |
||
224 | * [width] => 80 |
||
225 | * [heigth] => 120 |
||
226 | * ) |
||
227 | * @endcode |
||
228 | * |
||
229 | * @param int $maxWidth requested width |
||
230 | * @param int $maxHeight requested height |
||
231 | * @param int $actualWidth original width |
||
232 | * @param int $actualHeight original height |
||
233 | * @param bool $useHigherFactor defines which factor should be used to calculate the new |
||
234 | * size. For example: |
||
235 | * - original image size 800x400 |
||
236 | * - calculateAspectRatio(300, 200, 800, 400, false) will return 300x150 |
||
237 | * - calculateAspectRatio(300, 200, 800, 400, true) will return 400x200 |
||
238 | * |
||
239 | * @return array |
||
240 | */ |
||
241 | public static function calculateAspectRatio($maxWidth, $maxHeight, $actualWidth, $actualHeight, $useHigherFactor = false) |
||
242 | { |
||
243 | $oSize = array('width' => $maxWidth, 'height' => $maxHeight); |
||
244 | |||
245 | // Calculates the X and Y resize factors |
||
246 | $iFactorX = (float) $maxWidth / (float) $actualWidth; |
||
247 | $iFactorY = (float) $maxHeight / (float) $actualHeight; |
||
248 | |||
249 | // If some dimension have to be resized |
||
250 | if ($iFactorX != 1 || $iFactorY != 1) { |
||
251 | if ($useHigherFactor) { |
||
252 | // Uses the higher Factor to change the opposite size |
||
253 | if ($iFactorX > $iFactorY) { |
||
254 | $oSize['height'] = (int) round($actualHeight * $iFactorX); |
||
255 | } elseif ($iFactorX < $iFactorY) { |
||
256 | $oSize['width'] = (int) round($actualWidth * $iFactorY); |
||
257 | } |
||
258 | } else { |
||
259 | // Uses the lower Factor to change the opposite size |
||
260 | if ($iFactorX < $iFactorY) { |
||
261 | $oSize['height'] = (int) round($actualHeight * $iFactorX); |
||
262 | } elseif ($iFactorX > $iFactorY) { |
||
263 | $oSize['width'] = (int) round($actualWidth * $iFactorY); |
||
264 | } |
||
265 | } |
||
266 | } |
||
267 | |||
268 | if ($oSize['height'] <= 0) { |
||
269 | $oSize['height'] = 1; |
||
270 | } |
||
271 | |||
272 | if ($oSize['width'] <= 0) { |
||
273 | $oSize['width'] = 1; |
||
274 | } |
||
275 | |||
276 | // Returns the Size |
||
277 | return $oSize; |
||
278 | } |
||
279 | |||
280 | |||
281 | /** |
||
282 | * @link http://pl.php.net/manual/pl/function.imagecreatefromjpeg.php |
||
283 | * function posted by e dot a dot schultz at gmail dot com |
||
284 | * |
||
285 | * @param $imageWidth |
||
286 | * @param $imageHeight |
||
287 | * @param $imageBits |
||
288 | * @param $imageChannels |
||
289 | * |
||
290 | * @return bool |
||
291 | */ |
||
292 | public function setMemory($imageWidth, $imageHeight, $imageBits, $imageChannels) |
||
293 | { |
||
294 | $MB = 1048576; // number of bytes in 1M |
||
295 | $K64 = 65536; // number of bytes in 64K |
||
296 | $TWEAKFACTOR = 2.4; // Or whatever works for you |
||
297 | $memoryNeeded = round(($imageWidth * $imageHeight |
||
298 | * $imageBits |
||
299 | * $imageChannels / 8 |
||
300 | + $K64 |
||
301 | ) * $TWEAKFACTOR |
||
302 | ) + 3 * $MB; |
||
303 | |||
304 | //ini_get('memory_limit') only works if compiled with "--enable-memory-limit" also |
||
305 | //Default memory limit is 8MB so well stick with that. |
||
306 | //To find out what yours is, view your php.ini file. |
||
307 | $memoryLimit = Utils::returnBytes(@ini_get('memory_limit')) / $MB; |
||
308 | // There are no memory limits, nothing to do |
||
309 | if ($memoryLimit == -1) { |
||
310 | return true; |
||
311 | } |
||
312 | if (!$memoryLimit) { |
||
313 | $memoryLimit = 8; |
||
314 | } |
||
315 | |||
316 | $memoryLimitMB = $memoryLimit * $MB; |
||
317 | if (function_exists('memory_get_usage')) { |
||
318 | if (memory_get_usage() + $memoryNeeded > $memoryLimitMB) { |
||
319 | $newLimit = $memoryLimit + ceil((memory_get_usage() |
||
320 | + $memoryNeeded |
||
321 | - $memoryLimitMB |
||
322 | ) / $MB |
||
323 | ); |
||
324 | if (@ini_set('memory_limit', $newLimit . 'M') === false) { |
||
325 | return false; |
||
326 | } |
||
327 | } |
||
328 | } else { |
||
329 | if ($memoryNeeded + 3 * $MB > $memoryLimitMB) { |
||
330 | $newLimit = $memoryLimit + ceil((3 * $MB |
||
331 | + $memoryNeeded |
||
332 | - $memoryLimitMB |
||
333 | ) / $MB |
||
334 | ); |
||
335 | if (false === @ini_set('memory_limit', $newLimit . 'M')) { |
||
336 | return false; |
||
337 | } |
||
338 | } |
||
339 | } |
||
340 | |||
341 | return true; |
||
342 | } |
||
343 | |||
344 | /** |
||
345 | * @link http://pl.php.net/manual/en/function.imagecopyresampled.php |
||
346 | * Replacement to `imagecopyresampled` that will deliver results that are almost identical except |
||
347 | * MUCH faster (very typically 30 times faster). |
||
348 | * |
||
349 | * @static |
||
350 | * @access public |
||
351 | * @param resource $dstImage |
||
352 | * @param resource $srcImage |
||
353 | * @param int $dstX |
||
354 | * @param int $dstY |
||
355 | * @param int $srcX |
||
356 | * @param int $srcY |
||
357 | * @param int $dstW |
||
358 | * @param int $dstH |
||
359 | * @param int $srcW |
||
360 | * @param int $srcH |
||
361 | * @param int $quality |
||
362 | * |
||
363 | * @return boolean |
||
364 | */ |
||
365 | public function fastCopyResampled(&$dstImage, $srcImage, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH, $quality = 3) |
||
366 | { |
||
367 | if (empty($srcImage) || empty($dstImage)) { |
||
368 | return false; |
||
369 | } |
||
370 | |||
371 | if ($quality <= 1) { |
||
372 | $temp = imagecreatetruecolor($dstW + 1, $dstH + 1); |
||
373 | imagecopyresized($temp, $srcImage, $dstX, $dstY, $srcX, $srcY, $dstW + 1, $dstH + 1, $srcW, $srcH); |
||
374 | imagecopyresized($dstImage, $temp, 0, 0, 0, 0, $dstW, $dstH, $dstW, $dstH); |
||
375 | imagedestroy($temp); |
||
376 | } elseif ($quality < 5 && (($dstW * $quality) < $srcW || ($dstH * $quality) < $srcH)) { |
||
377 | $tmpW = $dstW * $quality; |
||
378 | $tmpH = $dstH * $quality; |
||
379 | $temp = imagecreatetruecolor($tmpW + 1, $tmpH + 1); |
||
380 | imagecopyresized($temp, $srcImage, 0, 0, $srcX, $srcY, $tmpW + 1, $tmpH + 1, $srcW, $srcH); |
||
381 | imagecopyresampled($dstImage, $temp, $dstX, $dstY, 0, 0, $dstW, $dstH, $tmpW, $tmpH); |
||
382 | imagedestroy($temp); |
||
383 | } else { |
||
384 | imagecopyresampled($dstImage, $srcImage, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); |
||
385 | } |
||
386 | |||
387 | return true; |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Source: http://pl.php.net/imagecreate |
||
392 | * (optimized for speed and memory usage, but yet not very efficient). |
||
393 | * |
||
394 | * @param string $data bitmap data |
||
395 | * |
||
396 | * @return resource |
||
397 | */ |
||
398 | public function createFromBmp($data) |
||
399 | { |
||
400 | $stream = fopen('php://temp', 'r+'); |
||
401 | fwrite($stream, $data); |
||
402 | rewind($stream); |
||
403 | |||
404 | //20 seconds seems to be a reasonable value to not kill a server and process images up to 1680x1050 |
||
405 | @set_time_limit(20); |
||
406 | |||
407 | if (!is_resource($stream)) { |
||
408 | return false; |
||
409 | } |
||
410 | |||
411 | $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($stream, 14)); |
||
412 | if ($FILE['file_type'] != 19778) { |
||
413 | return false; |
||
414 | } |
||
415 | |||
416 | $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel' . |
||
417 | '/Vcompression/Vsize_bitmap/Vhoriz_resolution' . |
||
418 | '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($stream, 40)); |
||
419 | |||
420 | $BMP['colors'] = pow(2, $BMP['bits_per_pixel']); |
||
421 | |||
422 | if ($BMP['size_bitmap'] == 0) { |
||
423 | $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset']; |
||
424 | } |
||
425 | |||
426 | $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel'] / 8; |
||
427 | $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']); |
||
428 | $BMP['decal'] = ($BMP['width'] * $BMP['bytes_per_pixel'] / 4); |
||
429 | $BMP['decal'] -= floor($BMP['width'] * $BMP['bytes_per_pixel'] / 4); |
||
430 | $BMP['decal'] = 4 - (4 * $BMP['decal']); |
||
431 | |||
432 | if ($BMP['decal'] == 4) { |
||
433 | $BMP['decal'] = 0; |
||
434 | } |
||
435 | |||
436 | $PALETTE = array(); |
||
437 | if ($BMP['colors'] < 16777216) { |
||
438 | $PALETTE = unpack('V' . $BMP['colors'], fread($stream, $BMP['colors'] * 4)); |
||
439 | } |
||
440 | |||
441 | //2048x1536px@24bit don't even try to process larger files as it will probably fail |
||
442 | if ($BMP['size_bitmap'] > 3 * 2048 * 1536) { |
||
443 | return false; |
||
444 | } |
||
445 | |||
446 | $IMG = fread($stream, $BMP['size_bitmap']); |
||
447 | fclose($stream); |
||
448 | $VIDE = chr(0); |
||
449 | |||
450 | $res = imagecreatetruecolor($BMP['width'], $BMP['height']); |
||
451 | $P = 0; |
||
452 | $Y = $BMP['height'] - 1; |
||
453 | |||
454 | $line_length = $BMP['bytes_per_pixel'] * $BMP['width']; |
||
455 | |||
456 | if ($BMP['bits_per_pixel'] == 24) { |
||
457 | while ($Y >= 0) { |
||
458 | $X = 0; |
||
459 | $temp = unpack("C*", substr($IMG, $P, $line_length)); |
||
460 | |||
461 | while ($X < $BMP['width']) { |
||
462 | $offset = $X * 3; |
||
463 | imagesetpixel($res, $X++, $Y, ($temp[$offset + 3] << 16) + ($temp[$offset + 2] << 8) + $temp[$offset + 1]); |
||
464 | } |
||
465 | $Y--; |
||
466 | $P += $line_length + $BMP['decal']; |
||
467 | } |
||
468 | } elseif ($BMP['bits_per_pixel'] == 8) { |
||
469 | while ($Y >= 0) { |
||
470 | $X = 0; |
||
471 | |||
472 | $temp = unpack("C*", substr($IMG, $P, $line_length)); |
||
473 | |||
474 | while ($X < $BMP['width']) { |
||
475 | imagesetpixel($res, $X++, $Y, $PALETTE[$temp[$X] + 1]); |
||
476 | } |
||
477 | $Y--; |
||
478 | $P += $line_length + $BMP['decal']; |
||
479 | } |
||
480 | } elseif ($BMP['bits_per_pixel'] == 4) { |
||
481 | while ($Y >= 0) { |
||
482 | $X = 0; |
||
483 | $i = 1; |
||
484 | $low = true; |
||
485 | |||
486 | $temp = unpack("C*", substr($IMG, $P, $line_length)); |
||
487 | |||
488 | while ($X < $BMP['width']) { |
||
489 | if ($low) { |
||
490 | $index = $temp[$i] >> 4; |
||
491 | } else { |
||
492 | $index = $temp[$i++] & 0x0F; |
||
493 | } |
||
494 | $low = !$low; |
||
495 | |||
496 | imagesetpixel($res, $X++, $Y, $PALETTE[$index + 1]); |
||
497 | } |
||
498 | $Y--; |
||
499 | $P += $line_length + $BMP['decal']; |
||
500 | } |
||
501 | } elseif ($BMP['bits_per_pixel'] == 1) { |
||
502 | $COLOR = unpack("n", $VIDE . substr($IMG, floor($P), 1)); |
||
503 | if (($P * 8) % 8 == 0) { |
||
504 | $COLOR[1] = $COLOR[1] >> 7; |
||
505 | } elseif (($P * 8) % 8 == 1) { |
||
506 | $COLOR[1] = ($COLOR[1] & 0x40) >> 6; |
||
507 | } elseif (($P * 8) % 8 == 2) { |
||
508 | $COLOR[1] = ($COLOR[1] & 0x20) >> 5; |
||
509 | } elseif (($P * 8) % 8 == 3) { |
||
510 | $COLOR[1] = ($COLOR[1] & 0x10) >> 4; |
||
511 | } elseif (($P * 8) % 8 == 4) { |
||
512 | $COLOR[1] = ($COLOR[1] & 0x8) >> 3; |
||
513 | } elseif (($P * 8) % 8 == 5) { |
||
514 | $COLOR[1] = ($COLOR[1] & 0x4) >> 2; |
||
515 | } elseif (($P * 8) % 8 == 6) { |
||
516 | $COLOR[1] = ($COLOR[1] & 0x2) >> 1; |
||
517 | } elseif (($P * 8) % 8 == 7) { |
||
518 | $COLOR[1] = ($COLOR[1] & 0x1); |
||
519 | } |
||
520 | $COLOR[1] = $PALETTE[$COLOR[1] + 1]; |
||
521 | } else { |
||
522 | return false; |
||
523 | } |
||
524 | |||
525 | return $res; |
||
526 | } |
||
527 | |||
528 | /** |
||
529 | * Resizes an image to a given size keeping the aspect ratio. |
||
530 | * |
||
531 | * @param int $maxWidth maximum width |
||
532 | * @param int $maxHeight maximum height |
||
533 | * @param int $quality quality |
||
534 | * @param bool $useHigherFactor |
||
535 | * |
||
536 | * @return Image $this |
||
537 | */ |
||
538 | public function resize($maxWidth, $maxHeight, $quality = 80, $useHigherFactor = false) |
||
539 | { |
||
540 | $this->resizeQuality = $quality; |
||
541 | |||
542 | $maxWidth = (int) $maxWidth ?: $this->width; |
||
543 | $maxHeight = (int) $maxHeight ?: $this->height; |
||
544 | |||
545 | if ($this->width <= $maxWidth && $this->height <= $maxHeight) { |
||
546 | return $this; |
||
547 | } |
||
548 | |||
549 | $targetSize = static::calculateAspectRatio($maxWidth, $maxHeight, $this->width, $this->height, $useHigherFactor); |
||
550 | |||
551 | $targetWidth = $targetSize['width']; |
||
552 | $targetHeight = $targetSize['height']; |
||
553 | |||
554 | $targetImage = imagecreatetruecolor($targetWidth, $targetHeight); |
||
555 | |||
556 | if ($this->mime === 'image/png') { |
||
557 | $bg = imagecolorallocatealpha($targetImage, 255, 255, 255, 127); |
||
558 | imagefill($targetImage, 0, 0, $bg); |
||
559 | imagealphablending($targetImage, false); |
||
560 | imagesavealpha($targetImage, true); |
||
561 | } |
||
562 | |||
563 | $this->fastCopyResampled($targetImage, $this->gdImage, 0, 0, 0, 0, $targetWidth, $targetHeight, |
||
564 | $this->width, $this->height, (int)max(floor($quality / 20), 6)); |
||
565 | |||
566 | imagedestroy($this->gdImage); |
||
567 | $this->gdImage = $targetImage; |
||
568 | $this->width = $targetWidth; |
||
569 | $this->height = $targetHeight; |
||
570 | |||
571 | return $this; |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Returns image data. |
||
576 | * |
||
577 | * @param string $format Returned image format mimetype (current image mimetype is used if not set). |
||
578 | * @param int $quality Image quelity (used for JPG images only) |
||
579 | * |
||
580 | * @return string image data |
||
581 | */ |
||
582 | public function getData($format = null, $quality = 80) |
||
583 | { |
||
584 | $mime = $format ?: $this->mime; |
||
585 | |||
586 | ob_start(); |
||
587 | |||
588 | switch ($mime) { |
||
589 | case 'image/gif': |
||
590 | imagegif($this->gdImage); |
||
591 | break; |
||
592 | case 'image/jpeg': |
||
593 | case 'image/bmp': |
||
594 | case 'image/x-ms-bmp': |
||
595 | $quality = $this->resizeQuality ?: $quality; |
||
596 | imagejpeg($this->gdImage, null, $quality); |
||
597 | break; |
||
598 | case 'image/png': |
||
599 | imagealphablending($this->gdImage, false); |
||
600 | imagesavealpha($this->gdImage, true); |
||
601 | imagepng($this->gdImage); |
||
602 | break; |
||
603 | case 'image/wbmp': |
||
604 | imagewbmp($this->gdImage); |
||
605 | break; |
||
606 | } |
||
607 | |||
608 | $this->dataSize = ob_get_length(); |
||
609 | |||
610 | return ob_get_clean(); |
||
611 | } |
||
612 | |||
613 | /** |
||
614 | * Returns GD image resource. |
||
615 | * |
||
616 | * @return resource GD image resource |
||
617 | */ |
||
618 | public function getGDImage() |
||
619 | { |
||
620 | return $this->gdImage; |
||
621 | } |
||
622 | |||
623 | /** |
||
624 | * Returns the size of image data produced by the `getData()` method. |
||
625 | * |
||
626 | * @return int image data size in bytes |
||
627 | */ |
||
628 | public function getDataSize() |
||
629 | { |
||
630 | return $this->dataSize; |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * Returns image width in pixels. |
||
635 | * |
||
636 | * @return int image width |
||
637 | */ |
||
638 | public function getWidth() |
||
639 | { |
||
640 | return $this->width; |
||
641 | } |
||
642 | |||
643 | /** |
||
644 | * Returns image height in pixels. |
||
645 | * |
||
646 | * @return int image height |
||
647 | */ |
||
648 | public function getHeight() |
||
649 | { |
||
650 | return $this->height; |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Returns image MIME type. |
||
655 | * |
||
656 | * @return string MIME type |
||
657 | */ |
||
658 | public function getMimeType() |
||
661 | } |
||
662 | |||
663 | public function crop($x, $y, $width, $height) |
||
664 | { |
||
665 | $targetImage = imagecreatetruecolor($width, $height); |
||
666 | |||
667 | if ($this->mime === 'image/png') { |
||
668 | $bg = imagecolorallocatealpha($targetImage, 255, 255, 255, 127); |
||
669 | imagefill($targetImage, 0, 0, $bg); |
||
670 | imagealphablending($targetImage, false); |
||
671 | imagesavealpha($targetImage, true); |
||
672 | } |
||
673 | |||
674 | imagecopy($targetImage, $this->gdImage, 0, 0, $x, $y, $width, $height); |
||
675 | |||
676 | imagedestroy($this->gdImage); |
||
677 | $this->gdImage = $targetImage; |
||
678 | $this->width = $width; |
||
679 | $this->height = $height; |
||
680 | |||
681 | return $this; |
||
682 | } |
||
683 | |||
684 | public function rotate($degrees, $bgcolor = 0) |
||
696 | } |
||
697 | |||
698 | public function getInfo() |
||
699 | { |
||
700 | $info = array( |
||
701 | 'width' => $this->getWidth(), |
||
702 | 'height' => $this->getHeight(), |
||
703 | 'size' => $this->getDataSize() |
||
704 | ); |
||
705 | |||
706 | return $info; |
||
707 | } |
||
708 | |||
709 | public function __destruct() |
||
713 | } |
||
714 | } |
||
715 | } |
||
716 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.