From 918ff0e0f0e18d8977f74ad44b0771aba51beb77 Mon Sep 17 00:00:00 2001 From: celestora Date: Tue, 13 Dec 2022 00:47:25 +0200 Subject: [PATCH] Experiment(Photo): use imagick+cloning instead of gd2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit АААААААААААА --- Web/Models/Entities/Photo.php | 70 +++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/Web/Models/Entities/Photo.php b/Web/Models/Entities/Photo.php index 628589db..f6019633 100644 --- a/Web/Models/Entities/Photo.php +++ b/Web/Models/Entities/Photo.php @@ -1,6 +1,8 @@ getWidth() / $image->getHeight()) > ($px / $py)) { - # For some weird reason using resize with EXACT flag causes system to consume an unholy amount of RAM - $image->crop(0, 0, "100%", (int) ceil(($px * $image->getWidth()) / $py)); + if(($image->getImageWidth() / $image->getImageHeight()) > ($px / $py)) { + $height = ceil(($px * $image->getImageWidth()) / $py); + $image->cropImage($image->getImageWidth(), $height, 0, 0); $res[0] = true; } } - + if(isset($size["maxSize"])) { $maxSize = (int) $size["maxSize"]; - $image->resize($maxSize, $maxSize, Image::SHRINK_ONLY | Image::FIT); + $sizes = Image::calculateSize($image->getImageWidth(), $image->getImageHeight(), $maxSize, $maxSize, Image::SHRINK_ONLY | Image::FIT); + $image->resizeImage($sizes[0], $sizes[1], \Imagick::FILTER_POINT, 1); } else if(isset($size["maxResolution"])) { $resolution = explode("x", (string) $size["maxResolution"]); - $image->resize((int) $resolution[0], (int) $resolution[1], Image::SHRINK_ONLY | Image::FIT); + $sizes = Image::calculateSize( + $image->getImageWidth(), $image->getImageHeight(), (int) $resolution[0], (int) $resolution[1], Image::SHRINK_ONLY | Image::FIT + ); + $image->resizeImage($sizes[0], $sizes[1], \Imagick::FILTER_POINT, 1); } else { throw new \RuntimeException("Malformed size description: " . (string) $size["id"]); } - - $res[1] = $image->getWidth(); - $res[2] = $image->getHeight(); + + $res[1] = $image->getImageWidth(); + $res[2] = $image->getImageHeight(); if($res[1] <= 300 || $res[2] <= 300) - $image->save("$outputDir/" . (string) $size["id"] . ".gif"); + $image->writeImage("$outputDir/$size[id].gif"); else - $image->save("$outputDir/" . (string) $size["id"] . ".jpeg"); - - imagedestroy($image->getImageResource()); + $image->writeImage("$outputDir/$size[id].jpeg"); + + $image->destroy(); unset($image); - + return $res; } - private function saveImageResizedCopies(string $filename, string $hash): void + private function saveImageResizedCopies(\Imagick $image, string $filename, string $hash): void { $dir = dirname($this->pathFromHash($hash)); $dir = "$dir/$hash" . "_cropped"; @@ -68,7 +78,7 @@ class Photo extends Media $sizesMeta = []; foreach($sizes->Size as $size) - $sizesMeta[(string) $size["id"]] = $this->resizeImage($filename, $dir, $size); + $sizesMeta[(string) $size["id"]] = $this->resizeImage(clone $image, $filename, $dir, $size); $sizesMeta = MessagePack::pack($sizesMeta); $this->stateChanges("sizes", $sizesMeta); @@ -76,13 +86,19 @@ class Photo extends Media protected function saveFile(string $filename, string $hash): bool { - $image = Image::fromFile($filename); - if(($image->height >= ($image->width * Photo::ALLOWED_SIDE_MULTIPLIER)) || ($image->width >= ($image->height * Photo::ALLOWED_SIDE_MULTIPLIER))) + $image = new \Imagick; + $image->readImage($filename); + $h = $image->getImageHeight(); + $w = $image->getImageWidth(); + if(($h >= ($w * Photo::ALLOWED_SIDE_MULTIPLIER)) || ($w >= ($h * Photo::ALLOWED_SIDE_MULTIPLIER))) throw new ISE("Invalid layout: image is too wide/short"); - - $image->resize(8192, 4320, Image::SHRINK_ONLY | Image::FIT); - $image->save($this->pathFromHash($hash), 92, Image::JPEG); - $this->saveImageResizedCopies($filename, $hash); + + $sizes = Image::calculateSize( + $image->getImageWidth(), $image->getImageHeight(), 8192, 4320, Image::SHRINK_ONLY | Image::FIT + ); + $image->resizeImage($sizes[0], $sizes[1], \Imagick::FILTER_POINT, 1); + $image->writeImage($this->pathFromHash($hash)); + $this->saveImageResizedCopies($image, $filename, $hash); return true; }