3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Util;
24 use Friendica\Core\Logger;
25 use Friendica\Core\System;
35 * Maps Mime types to Imagick formats
39 public static function getFormatsMap()
42 'image/jpeg' => 'JPG',
51 * Returns supported image mimetypes and corresponding file extensions
55 public static function supportedTypes()
60 if (class_exists('Imagick')) {
61 // Imagick::queryFormats won't help us a lot there...
62 // At least, not yet, other parts of friendica uses this array
67 } elseif (imagetypes() & IMG_PNG) {
77 * Guess image mimetype from filename or from Content-Type header
79 * @param string $filename Image filename
80 * @param boolean $fromcurl Check Content-Type header from curl request
81 * @param string $header passed headers to take into account
86 public static function guessType($filename, $fromcurl = false, $header = '')
88 Logger::info('Image: guessType: ' . $filename . ($fromcurl ? ' from curl headers' : ''));
92 $h = explode("\n", $header);
94 $data = array_map("trim", explode(":", trim($l), 2));
95 if (count($data) > 1) {
101 if (array_key_exists('Content-Type', $headers)) {
102 $type = $headers['Content-Type'];
106 if (is_null($type)) {
107 // Guessing from extension? Isn't that... dangerous?
108 if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) {
110 * Well, this not much better,
111 * but at least it comes from the data inside the image,
112 * we won't be tricked by a manipulated extension
114 $image = new Imagick($filename);
115 $type = $image->getImageMimeType();
117 $ext = pathinfo($filename, PATHINFO_EXTENSION);
118 $types = self::supportedTypes();
119 $type = 'image/jpeg';
120 foreach ($types as $m => $e) {
128 Logger::info('Image: guessType: type=' . $type);
136 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
138 public static function getInfoFromURLCached($url)
146 $data = DI::cache()->get($url);
148 if (empty($data) || !is_array($data)) {
149 $data = self::getInfoFromURL($url);
151 DI::cache()->set($url, $data);
160 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
162 public static function getInfoFromURL($url)
170 $img_str = Network::fetchUrl($url, true, 4);
176 $filesize = strlen($img_str);
179 if (function_exists("getimagesizefromstring")) {
180 $data = @getimagesizefromstring($img_str);
182 $tempfile = tempnam(get_temppath(), "cache");
184 $stamp1 = microtime(true);
185 file_put_contents($tempfile, $img_str);
186 DI::profiler()->saveTimestamp($stamp1, "file", System::callstack());
188 $data = getimagesize($tempfile);
191 } catch (\Exception $e) {
196 $data['size'] = $filesize;
203 * @param integer $width
204 * @param integer $height
205 * @param integer $max
208 public static function getScalingDimensions($width, $height, $max)
210 if ((!$width) || (!$height)) {
211 return ['width' => 0, 'height' => 0];
214 if ($width > $max && $height > $max) {
215 // very tall image (greater than 16:9)
216 // constrain the width - let the height float.
218 if ((($height * 9) / 16) > $width) {
220 $dest_height = intval(($height * $max) / $width);
221 } elseif ($width > $height) {
222 // else constrain both dimensions
224 $dest_height = intval(($height * $max) / $width);
226 $dest_width = intval(($width * $max) / $height);
232 $dest_height = intval(($height * $max) / $width);
234 if ($height > $max) {
235 // very tall image (greater than 16:9)
236 // but width is OK - don't do anything
238 if ((($height * 9) / 16) > $width) {
239 $dest_width = $width;
240 $dest_height = $height;
242 $dest_width = intval(($width * $max) / $height);
246 $dest_width = $width;
247 $dest_height = $height;
252 return ['width' => $dest_width, 'height' => $dest_height];