File indexing completed on 2025-01-26 05:29:15
0001 <?php 0002 0003 namespace Intervention\Image; 0004 0005 use GuzzleHttp\Psr7\Stream; 0006 use Psr\Http\Message\StreamInterface; 0007 0008 abstract class AbstractDecoder 0009 { 0010 /** 0011 * Initiates new image from path in filesystem 0012 * 0013 * @param string $path 0014 * @return \Intervention\Image\Image 0015 */ 0016 abstract public function initFromPath($path); 0017 0018 /** 0019 * Initiates new image from binary data 0020 * 0021 * @param string $data 0022 * @return \Intervention\Image\Image 0023 */ 0024 abstract public function initFromBinary($data); 0025 0026 /** 0027 * Initiates new image from GD resource 0028 * 0029 * @param Resource $resource 0030 * @return \Intervention\Image\Image 0031 */ 0032 abstract public function initFromGdResource($resource); 0033 0034 /** 0035 * Initiates new image from Imagick object 0036 * 0037 * @param \Imagick $object 0038 * @return \Intervention\Image\Image 0039 */ 0040 abstract public function initFromImagick(\Imagick $object); 0041 0042 /** 0043 * Buffer of input data 0044 * 0045 * @var mixed 0046 */ 0047 private $data; 0048 0049 /** 0050 * Creates new Decoder with data 0051 * 0052 * @param mixed $data 0053 */ 0054 public function __construct($data = null) 0055 { 0056 $this->data = $data; 0057 } 0058 0059 /** 0060 * Init from given URL 0061 * 0062 * @param string $url 0063 * @return \Intervention\Image\Image 0064 */ 0065 public function initFromUrl($url) 0066 { 0067 0068 $options = [ 0069 'http' => [ 0070 'method'=>"GET", 0071 'header'=>"Accept-language: en\r\n". 0072 "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2\r\n" 0073 ] 0074 ]; 0075 0076 $context = stream_context_create($options); 0077 0078 0079 if ($data = @file_get_contents($url, false, $context)) { 0080 return $this->initFromBinary($data); 0081 } 0082 0083 throw new \Intervention\Image\Exception\NotReadableException( 0084 "Unable to init from given url (".$url.")." 0085 ); 0086 } 0087 0088 /** 0089 * Init from given stream 0090 * 0091 * @param StreamInterface|resource $stream 0092 * @return \Intervention\Image\Image 0093 */ 0094 public function initFromStream($stream) 0095 { 0096 if (!$stream instanceof StreamInterface) { 0097 $stream = new Stream($stream); 0098 } 0099 0100 try { 0101 $offset = $stream->tell(); 0102 } catch (\RuntimeException $e) { 0103 $offset = 0; 0104 } 0105 0106 $shouldAndCanSeek = $offset !== 0 && $stream->isSeekable(); 0107 0108 if ($shouldAndCanSeek) { 0109 $stream->rewind(); 0110 } 0111 0112 try { 0113 $data = $stream->getContents(); 0114 } catch (\RuntimeException $e) { 0115 $data = null; 0116 } 0117 0118 if ($shouldAndCanSeek) { 0119 $stream->seek($offset); 0120 } 0121 0122 if ($data) { 0123 return $this->initFromBinary($data); 0124 } 0125 0126 throw new \Intervention\Image\Exception\NotReadableException( 0127 "Unable to init from given stream" 0128 ); 0129 } 0130 0131 /** 0132 * Determines if current source data is GD resource 0133 * 0134 * @return boolean 0135 */ 0136 public function isGdResource() 0137 { 0138 if (is_resource($this->data)) { 0139 return (get_resource_type($this->data) == 'gd'); 0140 } 0141 0142 return false; 0143 } 0144 0145 /** 0146 * Determines if current source data is Imagick object 0147 * 0148 * @return boolean 0149 */ 0150 public function isImagick() 0151 { 0152 return is_a($this->data, 'Imagick'); 0153 } 0154 0155 /** 0156 * Determines if current source data is Intervention\Image\Image object 0157 * 0158 * @return boolean 0159 */ 0160 public function isInterventionImage() 0161 { 0162 return is_a($this->data, '\Intervention\Image\Image'); 0163 } 0164 0165 /** 0166 * Determines if current data is SplFileInfo object 0167 * 0168 * @return boolean 0169 */ 0170 public function isSplFileInfo() 0171 { 0172 return is_a($this->data, 'SplFileInfo'); 0173 } 0174 0175 /** 0176 * Determines if current data is Symfony UploadedFile component 0177 * 0178 * @return boolean 0179 */ 0180 public function isSymfonyUpload() 0181 { 0182 return is_a($this->data, 'Symfony\Component\HttpFoundation\File\UploadedFile'); 0183 } 0184 0185 /** 0186 * Determines if current source data is file path 0187 * 0188 * @return boolean 0189 */ 0190 public function isFilePath() 0191 { 0192 if (is_string($this->data)) { 0193 try { 0194 return is_file($this->data); 0195 } catch (\Exception $e) { 0196 return false; 0197 } 0198 } 0199 0200 return false; 0201 } 0202 0203 /** 0204 * Determines if current source data is url 0205 * 0206 * @return boolean 0207 */ 0208 public function isUrl() 0209 { 0210 return (bool) filter_var($this->data, FILTER_VALIDATE_URL); 0211 } 0212 0213 /** 0214 * Determines if current source data is a stream resource 0215 * 0216 * @return boolean 0217 */ 0218 public function isStream() 0219 { 0220 if ($this->data instanceof StreamInterface) return true; 0221 if (!is_resource($this->data)) return false; 0222 if (get_resource_type($this->data) !== 'stream') return false; 0223 0224 return true; 0225 } 0226 0227 /** 0228 * Determines if current source data is binary data 0229 * 0230 * @return boolean 0231 */ 0232 public function isBinary() 0233 { 0234 if (is_string($this->data)) { 0235 $mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $this->data); 0236 return (substr($mime, 0, 4) != 'text' && $mime != 'application/x-empty'); 0237 } 0238 0239 return false; 0240 } 0241 0242 /** 0243 * Determines if current source data is data-url 0244 * 0245 * @return boolean 0246 */ 0247 public function isDataUrl() 0248 { 0249 $data = $this->decodeDataUrl($this->data); 0250 0251 return is_null($data) ? false : true; 0252 } 0253 0254 /** 0255 * Determines if current source data is base64 encoded 0256 * 0257 * @return boolean 0258 */ 0259 public function isBase64() 0260 { 0261 if (!is_string($this->data)) { 0262 return false; 0263 } 0264 0265 return base64_encode(base64_decode($this->data)) === $this->data; 0266 } 0267 0268 /** 0269 * Initiates new Image from Intervention\Image\Image 0270 * 0271 * @param Image $object 0272 * @return \Intervention\Image\Image 0273 */ 0274 public function initFromInterventionImage($object) 0275 { 0276 return $object; 0277 } 0278 0279 /** 0280 * Parses and decodes binary image data from data-url 0281 * 0282 * @param string $data_url 0283 * @return string 0284 */ 0285 private function decodeDataUrl($data_url) 0286 { 0287 if (!is_string($data_url)) { 0288 return null; 0289 } 0290 0291 $pattern = "/^data:(?:image\/[a-zA-Z\-\.]+)(?:charset=\".+\")?;base64,(?P<data>.+)$/"; 0292 preg_match($pattern, $data_url, $matches); 0293 0294 if (is_array($matches) && array_key_exists('data', $matches)) { 0295 return base64_decode($matches['data']); 0296 } 0297 0298 return null; 0299 } 0300 0301 /** 0302 * Initiates new image from mixed data 0303 * 0304 * @param mixed $data 0305 * @return \Intervention\Image\Image 0306 */ 0307 public function init($data) 0308 { 0309 $this->data = $data; 0310 0311 switch (true) { 0312 0313 case $this->isGdResource(): 0314 return $this->initFromGdResource($this->data); 0315 0316 case $this->isImagick(): 0317 return $this->initFromImagick($this->data); 0318 0319 case $this->isInterventionImage(): 0320 return $this->initFromInterventionImage($this->data); 0321 0322 case $this->isSplFileInfo(): 0323 return $this->initFromPath($this->data->getRealPath()); 0324 0325 case $this->isBinary(): 0326 return $this->initFromBinary($this->data); 0327 0328 case $this->isUrl(): 0329 return $this->initFromUrl($this->data); 0330 0331 case $this->isStream(): 0332 return $this->initFromStream($this->data); 0333 0334 case $this->isDataUrl(): 0335 return $this->initFromBinary($this->decodeDataUrl($this->data)); 0336 0337 case $this->isFilePath(): 0338 return $this->initFromPath($this->data); 0339 0340 // isBase64 has to be after isFilePath to prevent false positives 0341 case $this->isBase64(): 0342 return $this->initFromBinary(base64_decode($this->data)); 0343 0344 default: 0345 throw new Exception\NotReadableException("Image source not readable"); 0346 } 0347 } 0348 0349 /** 0350 * Decoder object transforms to string source data 0351 * 0352 * @return string 0353 */ 0354 public function __toString() 0355 { 0356 return (string) $this->data; 0357 } 0358 }