diff --git a/app/Core/Image/ImagickDriver.php b/app/Core/Image/ImagickDriver.php index 3bb8fae2..e4c12651 100644 --- a/app/Core/Image/ImagickDriver.php +++ b/app/Core/Image/ImagickDriver.php @@ -10,9 +10,11 @@ declare(strict_types=1); namespace ForkBB\Core\Image; +use Imagick; use ForkBB\Core\Files; use ForkBB\Core\Image\DefaultDriver; use ForkBB\Core\Exceptions\FileException; +use Exception; class ImagickDriver extends DefaultDriver { @@ -25,5 +27,103 @@ class ImagickDriver extends DefaultDriver $this->ready = \extension_loaded('imagick') && \class_exists('\\Imagick'); } + public function readFromStr(string $data) /* : mixed|false */ + { + if ($this->ready) { + try { + $imagick = new Imagick(); + $imagick->readImageBlob($data); + return $imagick; + } catch (Exception $e) { + } + } + + return false; + } + + public function readFromPath(string $path) /* : mixed|false */ + { + if ( + ! $this->ready + || $this->files->isBadPath($path) + ) { + return false; + } else { + try { + return new Imagick(\realpath($path)); + } catch (Exception $e) { + return false; + } + } + } + + public function writeToPath(/* mixed */ $imagick, string $path, int $quality): ?bool + { + if (! $this->ready) { + return null; + } + + try { + $type = \pathinfo($path, \PATHINFO_EXTENSION); + + switch ($type) { + case 'png': + $imagick->setImageCompressionQuality(0); // ???? пересчитать как в GD? + break; + default: + $imagick->setImageCompressionQuality($quality); + break; + } + + return $imagick->writeImages($path, true); + } catch (\Exception $e) { + return false; + } + } + + public function resize(/* mixed */ $imagick, int $maxW, int $maxH) /* : mixed */ + { + if (! $this->ready) { + throw new FileException('ImageMagick library not enabled'); + } + + try { + $oldW = $imagick->getImageWidth(); + $oldH = $imagick->getImageHeight(); + $wr = $maxW < 16 ? 1 : $maxW / $oldW; + $hr = $maxH < 16 ? 1 : $maxH / $oldH; + $r = \min($wr, $hr, 1); + + if (1 == $r) { + return $imagick; + } + + $width = (int) \round($oldW * $r); + $height = (int) \round($oldH * $r); + + // есть анимация + if ($imagick->getImageDelay() > 0) { + $images = $imagick->coalesceImages(); + + foreach ($images as $frame) { + $frame->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); + $frame->setImagePage($width, $height, 0, 0); + } + + return $images->deconstructImages(); + // нет анимации + } else { + $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); + + return $imagick; + } + } catch (Exception $e) { + throw new FileException($e->getMessage()); + } + } + + public function destroy(/* mixed */ $imagick): void + { + } }