]> git.mxchange.org Git - friendica.git/blob - src/Util/Images.php
Merge pull request #7828 from nupplaphil/task/move_enotify
[friendica.git] / src / Util / Images.php
1 <?php
2
3 namespace Friendica\Util;
4
5 use Friendica\BaseObject;
6 use Friendica\Core\Cache;
7 use Friendica\Core\Logger;
8 use Friendica\Core\System;
9 use Imagick;
10
11 /**
12  * Image utilities
13  */
14 class Images
15 {
16         /**
17          * Maps Mime types to Imagick formats
18          *
19          * @return array
20          */
21         public static function getFormatsMap()
22         {
23                 $m = [
24                         'image/jpeg' => 'JPG',
25                         'image/png' => 'PNG',
26                         'image/gif' => 'GIF'
27                 ];
28
29                 return $m;
30         }
31
32         /**
33          * Returns supported image mimetypes and corresponding file extensions
34          *
35          * @return array
36          */
37         public static function supportedTypes()
38         {
39                 $types = [
40                         'image/jpeg' => 'jpg'
41                 ];
42                 if (class_exists('Imagick')) {
43                         // Imagick::queryFormats won't help us a lot there...
44                         // At least, not yet, other parts of friendica uses this array
45                         $types += [
46                                 'image/png' => 'png',
47                                 'image/gif' => 'gif'
48                         ];
49                 } elseif (imagetypes() & IMG_PNG) {
50                         $types += [
51                                 'image/png' => 'png'
52                         ];
53                 }
54
55                 return $types;
56         }
57
58         /**
59          * Guess image mimetype from filename or from Content-Type header
60          *
61          * @param string  $filename Image filename
62          * @param boolean $fromcurl Check Content-Type header from curl request
63          * @param string  $header   passed headers to take into account
64          *
65          * @return string|null
66          * @throws \Exception
67          */
68         public static function guessType($filename, $fromcurl = false, $header = '')
69         {
70                 Logger::info('Image: guessType: ' . $filename . ($fromcurl ? ' from curl headers' : ''));
71                 $type = null;
72                 if ($fromcurl) {
73                         $headers = [];
74                         $h = explode("\n", $header);
75                         foreach ($h as $l) {
76                                 $data = array_map("trim", explode(":", trim($l), 2));
77                                 if (count($data) > 1) {
78                                         list($k, $v) = $data;
79                                         $headers[$k] = $v;
80                                 }
81                         }
82
83                         if (array_key_exists('Content-Type', $headers)) {
84                                 $type = $headers['Content-Type'];
85                         }
86                 }
87
88                 if (is_null($type)) {
89                         // Guessing from extension? Isn't that... dangerous?
90                         if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) {
91                                 /**
92                                  * Well, this not much better,
93                                  * but at least it comes from the data inside the image,
94                                  * we won't be tricked by a manipulated extension
95                                  */
96                                 $image = new Imagick($filename);
97                                 $type = $image->getImageMimeType();
98                         } else {
99                                 $ext = pathinfo($filename, PATHINFO_EXTENSION);
100                                 $types = self::supportedTypes();
101                                 $type = 'image/jpeg';
102                                 foreach ($types as $m => $e) {
103                                         if ($ext == $e) {
104                                                 $type = $m;
105                                         }
106                                 }
107                         }
108                 }
109
110                 Logger::info('Image: guessType: type=' . $type);
111                 return $type;
112         }
113
114
115         /**
116          * @param string $url
117          * @return array
118          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
119          */
120         public static function getInfoFromURLCached($url)
121         {
122                 $data = [];
123
124                 if (empty($url)) {
125                         return $data;
126                 }
127
128                 $data = Cache::get($url);
129
130                 if (empty($data) || !is_array($data)) {
131                         $data = self::getInfoFromURL($url);
132
133                         Cache::set($url, $data);
134                 }
135
136                 return $data;
137         }
138
139         /**
140          * @param string $url
141          * @return array
142          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
143          */
144         public static function getInfoFromURL($url)
145         {
146                 $data = [];
147
148                 if (empty($url)) {
149                         return $data;
150                 }
151
152                 $img_str = Network::fetchUrl($url, true, 4);
153
154                 if (!$img_str) {
155                         return [];
156                 }
157
158                 $filesize = strlen($img_str);
159
160                 try {
161                         if (function_exists("getimagesizefromstring")) {
162                                 $data = @getimagesizefromstring($img_str);
163                         } else {
164                                 $tempfile = tempnam(get_temppath(), "cache");
165
166                                 $stamp1 = microtime(true);
167                                 file_put_contents($tempfile, $img_str);
168                                 BaseObject::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack());
169
170                                 $data = getimagesize($tempfile);
171                                 unlink($tempfile);
172                         }
173                 } catch (\Exception $e) {
174                         return [];
175                 }
176
177                 if ($data) {
178                         $data['size'] = $filesize;
179                 }
180
181                 return $data;
182         }
183
184         /**
185          * @param integer $width
186          * @param integer $height
187          * @param integer $max
188          * @return array
189          */
190         public static function getScalingDimensions($width, $height, $max)
191         {
192                 if ((!$width) || (!$height)) {
193                         return ['width' => 0, 'height' => 0];
194                 }
195
196                 if ($width > $max && $height > $max) {
197                         // very tall image (greater than 16:9)
198                         // constrain the width - let the height float.
199
200                         if ((($height * 9) / 16) > $width) {
201                                 $dest_width = $max;
202                                 $dest_height = intval(($height * $max) / $width);
203                         } elseif ($width > $height) {
204                                 // else constrain both dimensions
205                                 $dest_width = $max;
206                                 $dest_height = intval(($height * $max) / $width);
207                         } else {
208                                 $dest_width = intval(($width * $max) / $height);
209                                 $dest_height = $max;
210                         }
211                 } else {
212                         if ($width > $max) {
213                                 $dest_width = $max;
214                                 $dest_height = intval(($height * $max) / $width);
215                         } else {
216                                 if ($height > $max) {
217                                         // very tall image (greater than 16:9)
218                                         // but width is OK - don't do anything
219
220                                         if ((($height * 9) / 16) > $width) {
221                                                 $dest_width = $width;
222                                                 $dest_height = $height;
223                                         } else {
224                                                 $dest_width = intval(($width * $max) / $height);
225                                                 $dest_height = $max;
226                                         }
227                                 } else {
228                                         $dest_width = $width;
229                                         $dest_height = $height;
230                                 }
231                         }
232                 }
233
234                 return ['width' => $dest_width, 'height' => $dest_height];
235         }
236 }