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