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;
34 * Maps Mime types to Imagick formats
38 public static function getFormatsMap()
41 'image/jpeg' => 'JPG',
50 * Returns supported image mimetypes and corresponding file extensions
54 public static function supportedTypes()
59 if (class_exists('Imagick')) {
60 // Imagick::queryFormats won't help us a lot there...
61 // At least, not yet, other parts of friendica uses this array
66 } elseif (imagetypes() & IMG_PNG) {
76 * Fetch image mimetype from the image data or guessing from the file name
78 * @param string $image_data Image data
79 * @param string $filename File name (for guessing the type via the extension)
80 * @param string[] $mimeTypes possible mime types
85 public static function getMimeTypeByData(string $image_data, string $filename = '', array $mimeTypes = [])
87 foreach ($mimeTypes as $mimeType) {
88 if (substr($mimeType, 0, 6) == 'image/') {
89 Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mimeTypes]);
94 $image = @getimagesizefromstring($image_data);
95 if (!empty($image['mime'])) {
96 Logger::info('Mime type detected via data', ['filename' => $filename, 'default' => $mimeTypes, 'mime' => $image['mime']]);
97 return $image['mime'];
100 return self::guessTypeByExtension($filename);
104 * Fetch image mimetype from the image data or guessing from the file name
106 * @param string $sourcefile Source file of the image
107 * @param string $filename File name (for guessing the type via the extension)
108 * @param string $mime default mime type
113 public static function getMimeTypeBySource(string $sourcefile, string $filename = '', string $mime = '')
115 if (substr($mime, 0, 6) == 'image/') {
116 Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]);
120 $image = @getimagesize($sourcefile);
121 if (!empty($image['mime'])) {
122 Logger::info('Mime type detected via file', ['filename' => $filename, 'default' => $mime, 'image' => $image]);
123 return $image['mime'];
126 return self::guessTypeByExtension($filename);
130 * Guess image mimetype from the filename
132 * @param string $filename Image filename
137 public static function guessTypeByExtension(string $filename)
139 $ext = pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION);
140 $types = self::supportedTypes();
141 $type = 'image/jpeg';
142 foreach ($types as $m => $e) {
148 Logger::info('Mime type guessed via extension', ['filename' => $filename, 'type' => $type]);
155 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
157 public static function getInfoFromURLCached($url)
165 $data = DI::cache()->get($url);
167 if (empty($data) || !is_array($data)) {
168 $data = self::getInfoFromURL($url);
170 DI::cache()->set($url, $data);
179 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
181 public static function getInfoFromURL($url)
189 $img_str = DI::httpRequest()->fetch($url, true, 4);
195 $filesize = strlen($img_str);
198 if (function_exists("getimagesizefromstring")) {
199 $data = @getimagesizefromstring($img_str);
201 $tempfile = tempnam(get_temppath(), "cache");
203 $stamp1 = microtime(true);
204 file_put_contents($tempfile, $img_str);
205 DI::profiler()->saveTimestamp($stamp1, "file");
207 $data = getimagesize($tempfile);
210 } catch (\Exception $e) {
215 $data['size'] = $filesize;
222 * @param integer $width
223 * @param integer $height
224 * @param integer $max
227 public static function getScalingDimensions($width, $height, $max)
229 if ((!$width) || (!$height)) {
230 return ['width' => 0, 'height' => 0];
233 if ($width > $max && $height > $max) {
234 // very tall image (greater than 16:9)
235 // constrain the width - let the height float.
237 if ((($height * 9) / 16) > $width) {
239 $dest_height = intval(($height * $max) / $width);
240 } elseif ($width > $height) {
241 // else constrain both dimensions
243 $dest_height = intval(($height * $max) / $width);
245 $dest_width = intval(($width * $max) / $height);
251 $dest_height = intval(($height * $max) / $width);
253 if ($height > $max) {
254 // very tall image (greater than 16:9)
255 // but width is OK - don't do anything
257 if ((($height * 9) / 16) > $width) {
258 $dest_width = $width;
259 $dest_height = $height;
261 $dest_width = intval(($width * $max) / $height);
265 $dest_width = $width;
266 $dest_height = $height;
271 return ['width' => $dest_width, 'height' => $dest_height];