diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0f2b96a9b..adc7d1eab6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -133,8 +133,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 f82d5c3503..b19e2adec5 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": "3.13.0", diff --git a/composer.lock b/composer.lock index 075cf1359c..befcd576c3 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": "5893b378d1dcda91aedf77059f4b0efb", + "content-hash": "90ff57f6e7de570c7bdffad74829f187", "packages": [ { "name": "adhocore/jwt", @@ -1595,6 +1595,48 @@ }, "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", + "reference": "66e38db211b1d6fe93de09d82606641e0f996e42" + }, + "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" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eldad Fux", + "email": "eldad@appwrite.io" + } + ], + "description": "A simple Image manipulation library", + "keywords": [ + "framework", + "image", + "php", + "upf", + "utopia" + ], + "time": "2021-02-19T05:09:46+00:00" + }, { "name": "utopia-php/locale", "version": "0.3.3", @@ -1753,16 +1795,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": { @@ -1799,9 +1841,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", @@ -4738,12 +4780,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2a6f75224a537ee506e9fa1e6fc4200ad411ffd9" + "reference": "539148499aaafa5058d534582f61ce2a66480987" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2a6f75224a537ee506e9fa1e6fc4200ad411ffd9", - "reference": "2a6f75224a537ee506e9fa1e6fc4200ad411ffd9", + "url": "https://api.github.com/repos/symfony/console/zipball/539148499aaafa5058d534582f61ce2a66480987", + "reference": "539148499aaafa5058d534582f61ce2a66480987", "shasum": "" }, "require": { @@ -4828,7 +4870,7 @@ "type": "tidelift" } ], - "time": "2021-02-17T15:27:35+00:00" + "time": "2021-02-18T11:02:40+00:00" }, { "name": "symfony/polyfill-ctype", 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); - } -}