Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Worksheet; 4 5 use GdImage; 6 use PhpOffice\PhpSpreadsheet\Exception; 7 use PhpOffice\PhpSpreadsheet\Shared\File; 8 9 class MemoryDrawing extends BaseDrawing 10 { 11 // Rendering functions 12 const RENDERING_DEFAULT = 'imagepng'; 13 const RENDERING_PNG = 'imagepng'; 14 const RENDERING_GIF = 'imagegif'; 15 const RENDERING_JPEG = 'imagejpeg'; 16 17 // MIME types 18 const MIMETYPE_DEFAULT = 'image/png'; 19 const MIMETYPE_PNG = 'image/png'; 20 const MIMETYPE_GIF = 'image/gif'; 21 const MIMETYPE_JPEG = 'image/jpeg'; 22 23 const SUPPORTED_MIME_TYPES = [ 24 self::MIMETYPE_GIF, 25 self::MIMETYPE_JPEG, 26 self::MIMETYPE_PNG, 27 ]; 28 29 /** 30 * Image resource. 31 * 32 * @var null|GdImage|resource 33 */ 34 private $imageResource; 35 36 /** 37 * Rendering function. 38 * 39 * @var string 40 */ 41 private $renderingFunction; 42 43 /** 44 * Mime type. 45 * 46 * @var string 47 */ 48 private $mimeType; 49 50 /** 51 * Unique name. 52 * 53 * @var string 54 */ 55 private $uniqueName; 56 57 /** @var null|resource */ 58 private $alwaysNull; 59 60 /** 61 * Create a new MemoryDrawing. 62 */ 63 public function __construct() 64 { 65 // Initialise values 66 $this->renderingFunction = self::RENDERING_DEFAULT; 67 $this->mimeType = self::MIMETYPE_DEFAULT; 68 $this->uniqueName = md5(mt_rand(0, 9999) . time() . mt_rand(0, 9999)); 69 $this->alwaysNull = null; 70 71 // Initialize parent 72 parent::__construct(); 73 } 74 75 public function __destruct() 76 { 77 if ($this->imageResource) { 78 $rslt = @imagedestroy($this->imageResource); 79 // "Fix" for Scrutinizer 80 $this->imageResource = $rslt ? null : $this->alwaysNull; 81 } 82 } 83 84 public function __clone() 85 { 86 parent::__clone(); 87 $this->cloneResource(); 88 } 89 90 private function cloneResource(): void 91 { 92 if (!$this->imageResource) { 93 return; 94 } 95 96 $width = (int) imagesx($this->imageResource); 97 $height = (int) imagesy($this->imageResource); 98 99 if (imageistruecolor($this->imageResource)) { 100 $clone = imagecreatetruecolor($width, $height); 101 if (!$clone) { 102 throw new Exception('Could not clone image resource'); 103 } 104 105 imagealphablending($clone, false); 106 imagesavealpha($clone, true); 107 } else { 108 $clone = imagecreate($width, $height); 109 if (!$clone) { 110 throw new Exception('Could not clone image resource'); 111 } 112 113 // If the image has transparency... 114 $transparent = imagecolortransparent($this->imageResource); 115 if ($transparent >= 0) { 116 $rgb = imagecolorsforindex($this->imageResource, $transparent); 117 if (empty($rgb)) { 118 throw new Exception('Could not get image colors'); 119 } 120 121 imagesavealpha($clone, true); 122 $color = imagecolorallocatealpha($clone, $rgb['red'], $rgb['green'], $rgb['blue'], $rgb['alpha']); 123 if ($color === false) { 124 throw new Exception('Could not get image alpha color'); 125 } 126 127 imagefill($clone, 0, 0, $color); 128 } 129 } 130 131 //Create the Clone!! 132 imagecopy($clone, $this->imageResource, 0, 0, 0, 0, $width, $height); 133 134 $this->imageResource = $clone; 135 } 136 137 /** 138 * @param resource $imageStream Stream data to be converted to a Memory Drawing 139 * 140 * @throws Exception 141 */ 142 public static function fromStream($imageStream): self 143 { 144 $streamValue = stream_get_contents($imageStream); 145 if ($streamValue === false) { 146 throw new Exception('Unable to read data from stream'); 147 } 148 149 return self::fromString($streamValue); 150 } 151 152 /** 153 * @param string $imageString String data to be converted to a Memory Drawing 154 * 155 * @throws Exception 156 */ 157 public static function fromString(string $imageString): self 158 { 159 $gdImage = @imagecreatefromstring($imageString); 160 if ($gdImage === false) { 161 throw new Exception('Value cannot be converted to an image'); 162 } 163 164 $mimeType = self::identifyMimeType($imageString); 165 $renderingFunction = self::identifyRenderingFunction($mimeType); 166 167 $drawing = new self(); 168 $drawing->setImageResource($gdImage); 169 $drawing->setRenderingFunction($renderingFunction); 170 $drawing->setMimeType($mimeType); 171 172 return $drawing; 173 } 174 175 private static function identifyRenderingFunction(string $mimeType): string 176 { 177 switch ($mimeType) { 178 case self::MIMETYPE_PNG: 179 return self::RENDERING_PNG; 180 case self::MIMETYPE_JPEG: 181 return self::RENDERING_JPEG; 182 case self::MIMETYPE_GIF: 183 return self::RENDERING_GIF; 184 } 185 186 return self::RENDERING_DEFAULT; 187 } 188 189 /** 190 * @throws Exception 191 */ 192 private static function identifyMimeType(string $imageString): string 193 { 194 $temporaryFileName = File::temporaryFilename(); 195 file_put_contents($temporaryFileName, $imageString); 196 197 $mimeType = self::identifyMimeTypeUsingExif($temporaryFileName); 198 if ($mimeType !== null) { 199 unlink($temporaryFileName); 200 201 return $mimeType; 202 } 203 204 $mimeType = self::identifyMimeTypeUsingGd($temporaryFileName); 205 if ($mimeType !== null) { 206 unlink($temporaryFileName); 207 208 return $mimeType; 209 } 210 211 unlink($temporaryFileName); 212 213 return self::MIMETYPE_DEFAULT; 214 } 215 216 private static function identifyMimeTypeUsingExif(string $temporaryFileName): ?string 217 { 218 if (function_exists('exif_imagetype')) { 219 $imageType = @exif_imagetype($temporaryFileName); 220 $mimeType = ($imageType) ? image_type_to_mime_type($imageType) : null; 221 222 return self::supportedMimeTypes($mimeType); 223 } 224 225 return null; 226 } 227 228 private static function identifyMimeTypeUsingGd(string $temporaryFileName): ?string 229 { 230 if (function_exists('getimagesize')) { 231 $imageSize = @getimagesize($temporaryFileName); 232 if (is_array($imageSize)) { 233 $mimeType = $imageSize['mime'] ?? null; 234 235 return self::supportedMimeTypes($mimeType); 236 } 237 } 238 239 return null; 240 } 241 242 private static function supportedMimeTypes(?string $mimeType = null): ?string 243 { 244 if (in_array($mimeType, self::SUPPORTED_MIME_TYPES, true)) { 245 return $mimeType; 246 } 247 248 return null; 249 } 250 251 /** 252 * Get image resource. 253 * 254 * @return null|GdImage|resource 255 */ 256 public function getImageResource() 257 { 258 return $this->imageResource; 259 } 260 261 /** 262 * Set image resource. 263 * 264 * @param GdImage|resource $value 265 * 266 * @return $this 267 */ 268 public function setImageResource($value) 269 { 270 $this->imageResource = $value; 271 272 if ($this->imageResource !== null) { 273 // Get width/height 274 $this->width = (int) imagesx($this->imageResource); 275 $this->height = (int) imagesy($this->imageResource); 276 } 277 278 return $this; 279 } 280 281 /** 282 * Get rendering function. 283 * 284 * @return string 285 */ 286 public function getRenderingFunction() 287 { 288 return $this->renderingFunction; 289 } 290 291 /** 292 * Set rendering function. 293 * 294 * @param string $value see self::RENDERING_* 295 * 296 * @return $this 297 */ 298 public function setRenderingFunction($value) 299 { 300 $this->renderingFunction = $value; 301 302 return $this; 303 } 304 305 /** 306 * Get mime type. 307 * 308 * @return string 309 */ 310 public function getMimeType() 311 { 312 return $this->mimeType; 313 } 314 315 /** 316 * Set mime type. 317 * 318 * @param string $value see self::MIMETYPE_* 319 * 320 * @return $this 321 */ 322 public function setMimeType($value) 323 { 324 $this->mimeType = $value; 325 326 return $this; 327 } 328 329 /** 330 * Get indexed filename (using image index). 331 */ 332 public function getIndexedFilename(): string 333 { 334 $extension = strtolower($this->getMimeType()); 335 $extension = explode('/', $extension); 336 $extension = $extension[1]; 337 338 return $this->uniqueName . $this->getImageIndex() . '.' . $extension; 339 } 340 341 /** 342 * Get hash code. 343 * 344 * @return string Hash code 345 */ 346 public function getHashCode() 347 { 348 return md5( 349 $this->renderingFunction . 350 $this->mimeType . 351 $this->uniqueName . 352 parent::getHashCode() . 353 __CLASS__ 354 ); 355 } 356 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body