diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a994337483..bcf645de58 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -162,8 +162,6 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi │ ├── Extend │ ├── Network │ ├── OpenSSL -│ ├── Resize -│ ├── Storage │ ├── Task │ ├── Template │ ├── URL diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index fe2b53f71f..a094dc672a 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1,28 +1,28 @@ load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */); + $cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size + $data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */); if ($data) { //$output = (empty($output)) ? $type : $output; @@ -60,24 +60,23 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response) ; } - $resize = new Resize(\file_get_contents($path)); + $image = new Image(\file_get_contents($path)); - $resize->crop((int) $width, (int) $height); + $image->crop((int) $width, (int) $height); $output = (empty($output)) ? $type : $output; - $data = $resize->output($output, $quality); - + $data = $image->output($output, $quality); + $cache->save($key, $data); - + $response ->setContentType('image/png') ->addHeader('Expires', $date) ->addHeader('X-Appwrite-Cache', 'miss') ->send($data, null); - ; - unset($resize); + unset($image); }; App::get('/v1/avatars/credit-cards/:code') @@ -91,7 +90,7 @@ App::get('/v1/avatars/credit-cards/:code') ->label('sdk.description', '/docs/references/avatars/get-credit-card.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) - ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.') + ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true) @@ -160,11 +159,11 @@ App::get('/v1/avatars/image') $quality = 80; $output = 'png'; - $date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache - $key = \md5('/v2/avatars/images-'.$url.'-'.$width.'/'.$height.'/'.$quality); + $date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache + $key = \md5('/v2/avatars/images-' . $url . '-' . $width . '/' . $height . '/' . $quality); $type = 'png'; - $cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size - $data = $cache->load($key, 60 * 60 * 24 * 7 /* 1 week */); + $cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size + $data = $cache->load($key, 60 * 60 * 24 * 7/* 1 week */); if ($data) { return $response @@ -186,17 +185,17 @@ App::get('/v1/avatars/image') } try { - $resize = new Resize($fetch); - } catch (\Exception $exception) { + $image = new Image($fetch); + } catch (\Exception$exception) { throw new Exception('Unable to parse image', 500); } - $resize->crop((int) $width, (int) $height); + $image->crop((int) $width, (int) $height); $output = (empty($output)) ? $type : $output; - - $data = $resize->output($output, $quality); - + + $data = $image->output($output, $quality); + $cache->save($key, $data); $response @@ -206,7 +205,7 @@ App::get('/v1/avatars/image') ->send($data); ; - unset($resize); + unset($image); }); App::get('/v1/avatars/favicon') @@ -229,11 +228,11 @@ App::get('/v1/avatars/favicon') $height = 56; $quality = 80; $output = 'png'; - $date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache - $key = \md5('/v2/avatars/favicon-'.$url); + $date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache + $key = \md5('/v2/avatars/favicon-' . $url); $type = 'png'; - $cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size - $data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */); + $cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size + $data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */); if ($data) { return $response @@ -316,7 +315,7 @@ App::get('/v1/avatars/favicon') if (empty($outputHref) || empty($outputExt)) { $default = \parse_url($url); - $outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico'; + $outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico'; $outputExt = 'ico'; } @@ -343,13 +342,13 @@ App::get('/v1/avatars/favicon') throw new Exception('Icon not found', 404); } - $resize = new Resize($fetch); + $image = new Image($fetch); - $resize->crop((int) $width, (int) $height); + $image->crop((int) $width, (int) $height); $output = (empty($output)) ? $type : $output; - $data = $resize->output($output, $quality); + $data = $image->output($output, $quality); $cache->save($key, $data); @@ -359,7 +358,7 @@ App::get('/v1/avatars/favicon') ->addHeader('X-Appwrite-Cache', 'miss') ->send($data); - unset($resize); + unset($image); }); App::get('/v1/avatars/qr') @@ -394,14 +393,14 @@ App::get('/v1/avatars/qr') $response->addHeader('Content-Disposition', 'attachment; filename="qr.png"'); } - $resize = new Resize($qrcode->render($text)); + $image = new Image($qrcode->render($text)); - $resize->crop((int) $size, (int) $size); + $image->crop((int) $size, (int) $size); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') - ->send($resize->output('png', 9)) + ->send($image->output('png', 9)) ; }); @@ -437,10 +436,10 @@ App::get('/v1/avatars/initials') ['color' => '#610038', 'background' => '#f5d1e6'], // PINK ['color' => '#386100', 'background' => '#dcf1bd'], // LIME ['color' => '#615800', 'background' => '#f1ecba'], // YELLOW - ['color' => '#610008', 'background' => '#f6d2d5'] // RED + ['color' => '#610008', 'background' => '#f6d2d5'], // RED ]; - $rand = \rand(0, \count($themes)-1); + $rand = \rand(0, \count($themes) - 1); $name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); $words = \explode(' ', \strtoupper($name)); @@ -457,23 +456,23 @@ App::get('/v1/avatars/initials') } $length = \count($words); - $rand = \substr($code,-1); - $background = (!empty($background)) ? '#'.$background : $themes[$rand]['background']; - $color = (!empty($color)) ? '#'.$color : $themes[$rand]['color']; + $rand = \substr($code, -1); + $background = (!empty($background)) ? '#' . $background : $themes[$rand]['background']; + $color = (!empty($color)) ? '#' . $color : $themes[$rand]['color']; $image = new \Imagick(); $draw = new \ImagickDraw(); $fontSize = \min($width, $height) / 2; - - $draw->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf"); - $image->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf"); + + $draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf"); + $image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf"); $draw->setFillColor(new \ImagickPixel($color)); $draw->setFontSize($fontSize); - + $draw->setTextAlignment(\Imagick::ALIGN_CENTER); $draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials); - + $image->newImage($width, $height, $background); $image->setImageFormat("png"); $image->drawImage($draw); @@ -481,7 +480,7 @@ App::get('/v1/avatars/initials') //$image->setImageCompressionQuality(9 - round(($quality / 100) * 9)); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->send($image->getImageBlob()) ; diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 98980fd6bd..d4500e95aa 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -18,7 +18,7 @@ use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; use Utopia\Storage\Compression\Algorithms\GZIP; -use Appwrite\Resize\Resize; +use Utopia\Image\Image; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Response; use Utopia\Config\Config; @@ -332,17 +332,17 @@ App::get('/v1/storage/files/:fileId/preview') $source = $compressor->decompress($source); } - $resize = new Resize($source); + $image = new Image($source); - $resize->crop((int) $width, (int) $height); + $image->crop((int) $width, (int) $height); if (!empty($background)) { - $resize->setBackground('#'.$background); + $image->setBackground('#'.$background); } $output = (empty($output)) ? $type : $output; - $data = $resize->output($output, $quality); + $data = $image->output($output, $quality); $cache->save($key, $data); @@ -353,7 +353,7 @@ App::get('/v1/storage/files/:fileId/preview') ->send($data) ; - unset($resize); + unset($image); }); App::get('/v1/storage/files/:fileId/download') diff --git a/composer.json b/composer.json index 811923c31b..b4370e7c2f 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,8 @@ "utopia-php/domains": "0.2.*", "utopia-php/swoole": "0.2.*", "utopia-php/system": "0.4.*", - "utopia-php/storage": "0.2.*", + "utopia-php/storage": "0.4.*", + "utopia-php/image": "0.1.*", "resque/php-resque": "1.3.6", "matomo/device-detector": "4.1.0", diff --git a/composer.lock b/composer.lock index 96c6fbbb0a..85b0932c93 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "01173c3bd9d5d01922432165ebcf1ce2", + "content-hash": "4f58de92fb64af44d915387895472881", "packages": [ { "name": "adhocore/jwt", @@ -1691,6 +1691,59 @@ }, "time": "2020-12-26T12:02:39+00:00" }, + { + "name": "utopia-php/image", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/image.git", + "reference": "66e38db211b1d6fe93de09d82606641e0f996e42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/image/zipball/66e38db211b1d6fe93de09d82606641e0f996e42", + "reference": "66e38db211b1d6fe93de09d82606641e0f996e42", + "shasum": "" + }, + "require": { + "chillerlan/php-qrcode": "4.3.0", + "ext-imagick": "*", + "php": ">=7.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "vimeo/psalm": "4.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Image\\": "src/Image" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eldad Fux", + "email": "eldad@appwrite.io" + } + ], + "description": "A simple Image manipulation library", + "keywords": [ + "framework", + "image", + "php", + "upf", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/image/issues", + "source": "https://github.com/utopia-php/image/tree/0.1.0" + }, + "time": "2021-02-19T05:09:46+00:00" + }, { "name": "utopia-php/locale", "version": "0.3.3", @@ -1849,16 +1902,16 @@ }, { "name": "utopia-php/storage", - "version": "0.2.0", + "version": "0.4.1", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "27bfd663c9b2a17ac0911522a87f42bee834df95" + "reference": "86f749f2d79268528732e560f77dde0155e162ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/27bfd663c9b2a17ac0911522a87f42bee834df95", - "reference": "27bfd663c9b2a17ac0911522a87f42bee834df95", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/86f749f2d79268528732e560f77dde0155e162ca", + "reference": "86f749f2d79268528732e560f77dde0155e162ca", "shasum": "" }, "require": { @@ -1895,9 +1948,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.2.0" + "source": "https://github.com/utopia-php/storage/tree/0.4.1" }, - "time": "2021-01-27T12:21:27+00:00" + "time": "2021-02-19T05:04:44+00:00" }, { "name": "utopia-php/swoole", @@ -2653,12 +2706,12 @@ "source": { "type": "git", "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "85e83cacd2ed573238678c6875f8f0d7ec699541" + "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/85e83cacd2ed573238678c6875f8f0d7ec699541", - "reference": "85e83cacd2ed573238678c6875f8f0d7ec699541", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730", + "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730", "shasum": "" }, "require": { @@ -2700,9 +2753,9 @@ ], "support": { "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.0" + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1" }, - "time": "2020-10-23T13:55:30+00:00" + "time": "2021-02-22T14:02:09+00:00" }, { "name": "matthiasmullie/minify", @@ -3117,16 +3170,16 @@ }, { "name": "phar-io/version", - "version": "3.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" + "reference": "bae7c545bef187884426f042434e561ab1ddb182" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", "shasum": "" }, "require": { @@ -3162,9 +3215,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.0.4" + "source": "https://github.com/phar-io/version/tree/3.1.0" }, - "time": "2020-12-13T23:18:30+00:00" + "time": "2021-02-23T14:00:09+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -3477,12 +3530,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "499be26d3f45b1d12b4903a772ea22f858a48eb3" + "reference": "dae425925709122f7584cadeeb838edcaa491bb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/499be26d3f45b1d12b4903a772ea22f858a48eb3", - "reference": "499be26d3f45b1d12b4903a772ea22f858a48eb3", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/dae425925709122f7584cadeeb838edcaa491bb1", + "reference": "dae425925709122f7584cadeeb838edcaa491bb1", "shasum": "" }, "require": { @@ -3530,7 +3583,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:05+00:00" + "time": "2021-02-23T15:48:43+00:00" }, { "name": "phpunit/php-invoker", @@ -3538,12 +3591,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c" + "reference": "5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c", - "reference": "e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40", + "reference": "5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40", "shasum": "" }, "require": { @@ -3594,7 +3647,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:14+00:00" + "time": "2021-02-23T15:48:51+00:00" }, { "name": "phpunit/php-text-template", @@ -3602,12 +3655,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "8de0286bd8c4988bc20fbd7c246d1662e5c2efe2" + "reference": "4ec5a2ac79a19b35d0cf83cce30604f77743067a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/8de0286bd8c4988bc20fbd7c246d1662e5c2efe2", - "reference": "8de0286bd8c4988bc20fbd7c246d1662e5c2efe2", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/4ec5a2ac79a19b35d0cf83cce30604f77743067a", + "reference": "4ec5a2ac79a19b35d0cf83cce30604f77743067a", "shasum": "" }, "require": { @@ -3654,7 +3707,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:47+00:00" + "time": "2021-02-23T15:49:24+00:00" }, { "name": "phpunit/php-timer", @@ -3662,12 +3715,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "bb859edc295be92317a9161ddb0d5cae03c4e164" + "reference": "705821b0927b5e69e9e016c84de68dc6195c71b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/bb859edc295be92317a9161ddb0d5cae03c4e164", - "reference": "bb859edc295be92317a9161ddb0d5cae03c4e164", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/705821b0927b5e69e9e016c84de68dc6195c71b9", + "reference": "705821b0927b5e69e9e016c84de68dc6195c71b9", "shasum": "" }, "require": { @@ -3714,7 +3767,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:22+00:00" + "time": "2021-02-23T15:48:59+00:00" }, { "name": "phpunit/phpunit", @@ -3879,12 +3932,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "83a4f03a3fce4f613fa2662aa7357246c7bb6860" + "reference": "3a42d843af4d27ca1155e1d926881af162733655" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/83a4f03a3fce4f613fa2662aa7357246c7bb6860", - "reference": "83a4f03a3fce4f613fa2662aa7357246c7bb6860", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/3a42d843af4d27ca1155e1d926881af162733655", + "reference": "3a42d843af4d27ca1155e1d926881af162733655", "shasum": "" }, "require": { @@ -3928,7 +3981,7 @@ "type": "github" } ], - "time": "2021-02-21T06:40:12+00:00" + "time": "2021-02-23T15:49:50+00:00" }, { "name": "sebastian/code-unit", @@ -3992,12 +4045,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "b0e1cc9a057295d75ec7c03e6e89094fa0787ca4" + "reference": "5f5db0b35f586eb5bca0581a10bb42dd56575986" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/b0e1cc9a057295d75ec7c03e6e89094fa0787ca4", - "reference": "b0e1cc9a057295d75ec7c03e6e89094fa0787ca4", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5f5db0b35f586eb5bca0581a10bb42dd56575986", + "reference": "5f5db0b35f586eb5bca0581a10bb42dd56575986", "shasum": "" }, "require": { @@ -4040,7 +4093,7 @@ "type": "github" } ], - "time": "2021-02-21T06:37:59+00:00" + "time": "2021-02-23T15:47:39+00:00" }, { "name": "sebastian/comparator", @@ -4048,12 +4101,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "56f15c16d786947d3fbb9df2788ae14049d34286" + "reference": "dbc5fb421f242a5749845dc8dd0dc8cde2979dd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/56f15c16d786947d3fbb9df2788ae14049d34286", - "reference": "56f15c16d786947d3fbb9df2788ae14049d34286", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dbc5fb421f242a5749845dc8dd0dc8cde2979dd9", + "reference": "dbc5fb421f242a5749845dc8dd0dc8cde2979dd9", "shasum": "" }, "require": { @@ -4115,7 +4168,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:07+00:00" + "time": "2021-02-23T15:47:47+00:00" }, { "name": "sebastian/complexity", @@ -4180,12 +4233,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "33d65ae1c50be986bfbddd876d23ea3042bc2b5f" + "reference": "93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/33d65ae1c50be986bfbddd876d23ea3042bc2b5f", - "reference": "33d65ae1c50be986bfbddd876d23ea3042bc2b5f", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90", + "reference": "93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90", "shasum": "" }, "require": { @@ -4239,7 +4292,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:16+00:00" + "time": "2021-02-23T15:47:55+00:00" }, { "name": "sebastian/environment", @@ -4247,12 +4300,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "d5a0fb77ea34154ab24cc9ada037e9f2b5715842" + "reference": "6e1743b808be9cfd33a716583ccb94b7d4d32e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d5a0fb77ea34154ab24cc9ada037e9f2b5715842", - "reference": "d5a0fb77ea34154ab24cc9ada037e9f2b5715842", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e1743b808be9cfd33a716583ccb94b7d4d32e94", + "reference": "6e1743b808be9cfd33a716583ccb94b7d4d32e94", "shasum": "" }, "require": { @@ -4303,7 +4356,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:24+00:00" + "time": "2021-02-23T15:48:03+00:00" }, { "name": "sebastian/exporter", @@ -4311,12 +4364,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "36878bc8e65b75bdd37fe65ed6939e6374164b06" + "reference": "eca7281ab29075df68b113a37a83be616b629b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/36878bc8e65b75bdd37fe65ed6939e6374164b06", - "reference": "36878bc8e65b75bdd37fe65ed6939e6374164b06", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/eca7281ab29075df68b113a37a83be616b629b12", + "reference": "eca7281ab29075df68b113a37a83be616b629b12", "shasum": "" }, "require": { @@ -4381,7 +4434,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:32+00:00" + "time": "2021-02-23T15:48:12+00:00" }, { "name": "sebastian/global-state", @@ -4389,12 +4442,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9" + "reference": "0ac702e6d13725242edb9b294c5d20b92fcfb8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9", - "reference": "48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ac702e6d13725242edb9b294c5d20b92fcfb8b4", + "reference": "0ac702e6d13725242edb9b294c5d20b92fcfb8b4", "shasum": "" }, "require": { @@ -4446,7 +4499,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:40+00:00" + "time": "2021-02-23T15:48:19+00:00" }, { "name": "sebastian/lines-of-code", @@ -4511,12 +4564,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527" + "reference": "8cc80b4bda00a4c5997c3fc597a34872f3a1007d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527", - "reference": "00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/8cc80b4bda00a4c5997c3fc597a34872f3a1007d", + "reference": "8cc80b4bda00a4c5997c3fc597a34872f3a1007d", "shasum": "" }, "require": { @@ -4561,7 +4614,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:48+00:00" + "time": "2021-02-23T15:48:28+00:00" }, { "name": "sebastian/object-reflector", @@ -4569,12 +4622,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "13af24fcef1a0857804d8f1896e95af4f01c37f0" + "reference": "1d33587c2c3e636936f895e103a9e82dd8102a8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/13af24fcef1a0857804d8f1896e95af4f01c37f0", - "reference": "13af24fcef1a0857804d8f1896e95af4f01c37f0", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d33587c2c3e636936f895e103a9e82dd8102a8e", + "reference": "1d33587c2c3e636936f895e103a9e82dd8102a8e", "shasum": "" }, "require": { @@ -4617,7 +4670,7 @@ "type": "github" } ], - "time": "2021-02-21T06:38:56+00:00" + "time": "2021-02-23T15:48:35+00:00" }, { "name": "sebastian/recursion-context", @@ -4625,12 +4678,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "43746c15374dba48c7c81f8e993b21888c943a83" + "reference": "43f58a51e8f853aadb228ba818d2be388af7237b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/43746c15374dba48c7c81f8e993b21888c943a83", - "reference": "43746c15374dba48c7c81f8e993b21888c943a83", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/43f58a51e8f853aadb228ba818d2be388af7237b", + "reference": "43f58a51e8f853aadb228ba818d2be388af7237b", "shasum": "" }, "require": { @@ -4681,7 +4734,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:30+00:00" + "time": "2021-02-23T15:49:08+00:00" }, { "name": "sebastian/resource-operations", @@ -4745,12 +4798,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "819c8e7fba19e9c2137b238040b906f1586cc7cc" + "reference": "557863473c1de00e165a288d5b547f1f83652e7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/819c8e7fba19e9c2137b238040b906f1586cc7cc", - "reference": "819c8e7fba19e9c2137b238040b906f1586cc7cc", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/557863473c1de00e165a288d5b547f1f83652e7e", + "reference": "557863473c1de00e165a288d5b547f1f83652e7e", "shasum": "" }, "require": { @@ -4794,7 +4847,7 @@ "type": "github" } ], - "time": "2021-02-21T06:39:38+00:00" + "time": "2021-02-23T15:49:16+00:00" }, { "name": "sebastian/version", @@ -4893,12 +4946,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "539148499aaafa5058d534582f61ce2a66480987" + "reference": "c08d7d0d458eceb62996d81d3be8d9fbf5564ec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/539148499aaafa5058d534582f61ce2a66480987", - "reference": "539148499aaafa5058d534582f61ce2a66480987", + "url": "https://api.github.com/repos/symfony/console/zipball/c08d7d0d458eceb62996d81d3be8d9fbf5564ec4", + "reference": "c08d7d0d458eceb62996d81d3be8d9fbf5564ec4", "shasum": "" }, "require": { @@ -4983,7 +5036,7 @@ "type": "tidelift" } ], - "time": "2021-02-18T11:02:40+00:00" + "time": "2021-02-23T10:10:15+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -5403,12 +5456,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bf99754c6182a126968b1c2709d18548489f27eb" + "reference": "e830e6ceebd6377b019e4c9a523d6f2c27007e4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bf99754c6182a126968b1c2709d18548489f27eb", - "reference": "bf99754c6182a126968b1c2709d18548489f27eb", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e830e6ceebd6377b019e4c9a523d6f2c27007e4a", + "reference": "e830e6ceebd6377b019e4c9a523d6f2c27007e4a", "shasum": "" }, "require": { @@ -5422,7 +5475,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.3-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -5475,7 +5528,7 @@ "type": "tidelift" } ], - "time": "2021-01-27T16:27:53+00:00" + "time": "2021-02-25T16:38:04+00:00" }, { "name": "symfony/string", @@ -5617,12 +5670,12 @@ "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "429f90a02d3bd4a06787ac9bc48c56c4320b58a0" + "reference": "728c611e8643a5dd44839ffa791e21763b04a694" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/429f90a02d3bd4a06787ac9bc48c56c4320b58a0", - "reference": "429f90a02d3bd4a06787ac9bc48c56c4320b58a0", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/728c611e8643a5dd44839ffa791e21763b04a694", + "reference": "728c611e8643a5dd44839ffa791e21763b04a694", "shasum": "" }, "require": { @@ -5688,7 +5741,7 @@ "type": "tidelift" } ], - "time": "2021-02-08T09:50:07+00:00" + "time": "2021-02-22T11:56:05+00:00" }, { "name": "vimeo/psalm", diff --git a/src/Appwrite/Resize/Resize.php b/src/Appwrite/Resize/Resize.php deleted file mode 100644 index a9257b6e48..0000000000 --- a/src/Appwrite/Resize/Resize.php +++ /dev/null @@ -1,220 +0,0 @@ -image = new Imagick(); - - $this->image->readImageBlob($data); - - $this->width = $this->image->getImageWidth(); - $this->height = $this->image->getImageHeight(); - } - - /** - * @param int $width - * @param int $height - * - * @return Resize - * - * @throws \Throwable - */ - public function crop(int $width, int $height) - { - $originalAspect = $this->width / $this->height; - - if (empty($width)) { - $width = $height * $originalAspect; - } - - if (empty($height)) { - $height = $width / $originalAspect; - } - - if (empty($height) && empty($width)) { - $height = $this->height; - $width = $this->width; - } - - if ($this->image->getImageFormat() == 'GIF') { - $this->image = $this->image->coalesceImages(); - - foreach ($this->image as $frame) { - $frame->cropThumbnailImage($width, $height); - } - - $this->image->deconstructImages(); - } else { - $this->image->cropThumbnailImage($width, $height); - } - - return $this; - } - - /** - * @param $color - * - * @return Resize - * - * @throws \Throwable - */ - public function setBackground($color) - { - $this->image->setImageBackgroundColor($color); - $this->image = $this->image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN); - - return $this; - } - - /** - * Output. - * - * Prints manipulated image. - * - * @param string $type - * @param int $quality - * - * @return string - * - * @throws Exception - */ - public function output(string $type, int $quality = 75) - { - return $this->save(null, $type, $quality); - } - - /** - * @param string $path - * @param $type - * @param int $quality - * - * @return string - * - * @throws Exception - */ - public function save(string $path = null, string $type = '', int $quality = 75) - { - // Create directory with write permissions - if (null !== $path && !\file_exists(\dirname($path))) { - if (!@\mkdir(\dirname($path), 0755, true)) { - throw new Exception('Can\'t create directory '.\dirname($path)); - } - } - - switch ($type) { - case 'jpg': - case 'jpeg': - $this->image->setImageCompressionQuality($quality); - - $this->image->setImageFormat('jpg'); - break; - - case 'gif': - $this->image->setImageFormat('gif'); - break; - - case 'webp': - try { - $this->image->setImageFormat('webp'); - } catch (\Throwable $th) { - $signature = $this->image->getImageSignature(); - $temp = '/tmp/temp-'.$signature.'.'.\strtolower($this->image->getImageFormat()); - $output = '/tmp/output-'.$signature.'.webp'; - - // save temp - $this->image->writeImages($temp, true); - - // convert temp - \exec("cwebp -quiet -metadata none -q $quality $temp -o $output"); - - $data = \file_get_contents($output); - - //load webp - if (empty($path)) { - return $data; - } else { - \file_put_contents($path, $data, LOCK_EX); - } - - $this->image->clear(); - $this->image->destroy(); - - //delete webp - \unlink($output); - \unlink($temp); - - return; - } - - break; - - case 'png': - /* Scale quality from 0-100 to 0-9 */ - $scaleQuality = \round(($quality / 100) * 9); - - /* Invert quality setting as 0 is best, not 9 */ - $invertScaleQuality = 9 - $scaleQuality; - - $this->image->setImageCompressionQuality($invertScaleQuality); - - $this->image->setImageFormat('png'); - break; - - default: - throw new Exception('Invalid output type given'); - break; - } - - if (empty($path)) { - return $this->image->getImagesBlob(); - } else { - $this->image->writeImages($path, true); - } - - $this->image->clear(); - $this->image->destroy(); - } - - /** - * @param int $newHeight - * - * @return int - */ - protected function getSizeByFixedHeight(int $newHeight):int - { - $ratio = $this->width / $this->height; - $newWidth = $newHeight * $ratio; - - return $newWidth; - } - - /** - * @param int $newWidth - * - * @return int - */ - protected function getSizeByFixedWidth(int $newWidth):int - { - $ratio = $this->height / $this->width; - $newHeight = $newWidth * $ratio; - - return $newHeight; - } -} \ No newline at end of file diff --git a/tests/resources/resize/100x100-q30.jpg b/tests/resources/resize/100x100-q30.jpg deleted file mode 100644 index 23933efc86..0000000000 Binary files a/tests/resources/resize/100x100-q30.jpg and /dev/null differ diff --git a/tests/resources/resize/100x100.gif b/tests/resources/resize/100x100.gif deleted file mode 100644 index 864dc7c024..0000000000 Binary files a/tests/resources/resize/100x100.gif and /dev/null differ diff --git a/tests/resources/resize/100x100.jpg b/tests/resources/resize/100x100.jpg deleted file mode 100644 index 21a69c0e60..0000000000 Binary files a/tests/resources/resize/100x100.jpg and /dev/null differ diff --git a/tests/resources/resize/100x100.png b/tests/resources/resize/100x100.png deleted file mode 100644 index 14288e2019..0000000000 Binary files a/tests/resources/resize/100x100.png and /dev/null differ diff --git a/tests/resources/resize/100x100.webp b/tests/resources/resize/100x100.webp deleted file mode 100644 index c0e1cc922f..0000000000 Binary files a/tests/resources/resize/100x100.webp and /dev/null differ diff --git a/tests/resources/resize/100x400.jpg b/tests/resources/resize/100x400.jpg deleted file mode 100644 index 0515c98d52..0000000000 Binary files a/tests/resources/resize/100x400.jpg and /dev/null differ diff --git a/tests/resources/resize/400x100.jpg b/tests/resources/resize/400x100.jpg deleted file mode 100644 index caa6cd18f5..0000000000 Binary files a/tests/resources/resize/400x100.jpg and /dev/null differ diff --git a/tests/unit/Resize/ResizeTest.php b/tests/unit/Resize/ResizeTest.php deleted file mode 100644 index eeb089f8cd..0000000000 --- a/tests/unit/Resize/ResizeTest.php +++ /dev/null @@ -1,170 +0,0 @@ -crop(100, 100); - - $resize->save($target, 'jpg', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertEquals('JPEG', $image->getImageFormat()); - - \unlink($target); - } - - public function testCrop100x400() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $target = __DIR__.'/100x400.jpg'; - - $resize->crop(100, 400); - - $resize->save($target, 'jpg', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(400, $image->getImageHeight()); - $this->assertEquals('JPEG', $image->getImageFormat()); - - \unlink($target); - } - - public function testCrop400x100() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $target = __DIR__.'/400x100.jpg'; - - $resize->crop(400, 100); - - $resize->save($target, 'jpg', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(400, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertEquals('JPEG', $image->getImageFormat()); - - \unlink($target); - } - - public function testCrop100x100WEBP() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $target = __DIR__.'/100x100.webp'; - $original = __DIR__.'/../../resources/resize/100x100.webp'; - - $resize->crop(100, 100); - - $resize->save($target, 'webp', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertTrue(in_array($image->getImageFormat(), ['PAM', 'WEBP'])); - - \unlink($target); - } - - public function testCrop100x100PNG() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $target = __DIR__.'/100x100.png'; - $original = __DIR__.'/../../resources/resize/100x100.png'; - - $resize->crop(100, 100); - - $resize->save($target, 'png', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertGreaterThan(15000, \filesize($target)); - $this->assertLessThan(30000, \filesize($target)); - $this->assertEquals(\mime_content_type($target), \mime_content_type($original)); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertEquals('PNG', $image->getImageFormat()); - - \unlink($target); - } - - public function testCrop100x100PNGQuality30() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $target = __DIR__.'/100x100-q30.jpg'; - $original = __DIR__.'/../../resources/resize/100x100-q30.jpg'; - - $resize->crop(100, 100); - - $resize->save($target, 'jpg', 10); - - $this->assertEquals(\is_readable($target), true); - $this->assertGreaterThan(500, \filesize($target)); - $this->assertLessThan(2000, \filesize($target)); - $this->assertEquals(\mime_content_type($target), \mime_content_type($original)); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertEquals('JPEG', $image->getImageFormat()); - - \unlink($target); - } - - public function testCrop100x100GIF() - { - $resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-3.gif')); - $target = __DIR__.'/100x100.gif'; - $original = __DIR__.'/../../resources/resize/100x100.gif'; - - $resize->crop(100, 100); - - $resize->save($target, 'gif', 100); - - $this->assertEquals(\is_readable($target), true); - $this->assertGreaterThan(400000, \filesize($target)); - $this->assertLessThan(800000, \filesize($target)); - $this->assertEquals(\mime_content_type($target), \mime_content_type($original)); - $this->assertNotEmpty(\md5(\file_get_contents($target))); - - $image = new \Imagick($target); - $this->assertEquals(100, $image->getImageWidth()); - $this->assertEquals(100, $image->getImageHeight()); - $this->assertEquals('GIF', $image->getImageFormat()); - \unlink($target); - } -}