diff --git a/src/Drivers/Gd/Encoders/BmpEncoder.php b/src/Drivers/Gd/Encoders/BmpEncoder.php index 326987a0..a3e95b40 100644 --- a/src/Drivers/Gd/Encoders/BmpEncoder.php +++ b/src/Drivers/Gd/Encoders/BmpEncoder.php @@ -3,15 +3,13 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; -use Intervention\Image\Drivers\Gd\Traits\CanReduceColors; +use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; class BmpEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; - public function __construct(protected int $color_limit = 0) { // @@ -19,9 +17,9 @@ class BmpEncoder extends AbstractEncoder implements EncoderInterface public function encode(ImageInterface $image): EncodedImage { - $gd = $this->maybeReduceColors($image->frame()->core(), $this->color_limit); - $data = $this->getBuffered(function () use ($gd) { - imagebmp($gd, null, false); + $image = $image->modify(new LimitColorsModifier($this->color_limit)); + $data = $this->getBuffered(function () use ($image) { + imagebmp($image->frame()->core(), null, false); }); return new EncodedImage($data, 'image/bmp'); diff --git a/src/Drivers/Gd/Encoders/GifEncoder.php b/src/Drivers/Gd/Encoders/GifEncoder.php index d6979705..5967f5cd 100644 --- a/src/Drivers/Gd/Encoders/GifEncoder.php +++ b/src/Drivers/Gd/Encoders/GifEncoder.php @@ -4,15 +4,13 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use Intervention\Gif\Builder as GifBuilder; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; -use Intervention\Image\Drivers\Gd\Traits\CanReduceColors; +use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; class GifEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; - public function __construct(protected int $color_limit = 0) { // @@ -24,9 +22,9 @@ class GifEncoder extends AbstractEncoder implements EncoderInterface return $this->encodeAnimated($image); } - $gd = $this->maybeReduceColors($image->frame()->core(), $this->color_limit); - $data = $this->getBuffered(function () use ($gd) { - imagegif($gd); + $image = $image->modify(new LimitColorsModifier($this->color_limit)); + $data = $this->getBuffered(function () use ($image) { + imagegif($image->frame()->core()); }); return new EncodedImage($data, 'image/gif'); diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index e74069fd..7daa2dc6 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -3,15 +3,13 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; -use Intervention\Image\Drivers\Gd\Traits\CanReduceColors; +use Intervention\Image\Drivers\Gd\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; class PngEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; - public function __construct(protected int $color_limit = 0) { // @@ -19,9 +17,9 @@ class PngEncoder extends AbstractEncoder implements EncoderInterface public function encode(ImageInterface $image): EncodedImage { - $gd = $this->maybeReduceColors($image->frame()->core(), $this->color_limit); - $data = $this->getBuffered(function () use ($gd) { - imagepng($gd, null, -1); + $image = $image->modify(new LimitColorsModifier($this->color_limit)); + $data = $this->getBuffered(function () use ($image) { + imagepng($image->frame()->core(), null, -1); }); return new EncodedImage($data, 'image/png'); diff --git a/src/Drivers/Gd/Modifiers/LimitColorsModifier.php b/src/Drivers/Gd/Modifiers/LimitColorsModifier.php new file mode 100644 index 00000000..84835ef4 --- /dev/null +++ b/src/Drivers/Gd/Modifiers/LimitColorsModifier.php @@ -0,0 +1,60 @@ +limit === 0) { + return $image; + } + + // limit is over threshold: no reduction + if ($this->limit > $this->threshold) { + return $image; + } + + $width = $image->width(); + $height = $image->height(); + + foreach ($image as $frame) { + // create empty gd + $reduced = imagecreatetruecolor($width, $height); + + // create matte + $matte = imagecolorallocatealpha($reduced, 255, 255, 255, 127); + + // fill with matte + imagefill($reduced, 0, 0, $matte); + + imagealphablending($reduced, false); + + // set transparency and get transparency index + imagecolortransparent($reduced, $matte); + + // copy original image + imagecopy($reduced, $frame->core(), 0, 0, 0, 0, $width, $height); + + // reduce limit by one to include possible transparency in palette + $limit = imagecolortransparent($frame->core()) === -1 ? $this->limit : $this->limit - 1; + + // decrease colors + imagetruecolortopalette($reduced, true, $limit); + + $frame->setCore($reduced); + } + + + return $image; + } +} diff --git a/src/Drivers/Gd/Traits/CanReduceColors.php b/src/Drivers/Gd/Traits/CanReduceColors.php deleted file mode 100644 index 1c110bd9..00000000 --- a/src/Drivers/Gd/Traits/CanReduceColors.php +++ /dev/null @@ -1,59 +0,0 @@ - $threshold) { - return $gd; - } - - // image size - $width = imagesx($gd); - $height = imagesy($gd); - - // create empty gd - $reduced = imagecreatetruecolor($width, $height); - - // create matte - $matte = imagecolorallocatealpha($reduced, 255, 255, 255, 127); - - // fill with matte - imagefill($reduced, 0, 0, $matte); - - imagealphablending($reduced, false); - - // set transparency and get transparency index - imagecolortransparent($reduced, $matte); - - // copy original image - imagecopy($reduced, $gd, 0, 0, 0, 0, $width, $height); - - // reduce limit by one to include possible transparency in palette - $limit = imagecolortransparent($gd) === -1 ? $limit : $limit - 1; - - // decrease colors - imagetruecolortopalette($reduced, true, $limit); - - return $reduced; - } -} diff --git a/src/Drivers/Imagick/Encoders/BmpEncoder.php b/src/Drivers/Imagick/Encoders/BmpEncoder.php index 79767f4d..ad07bdc9 100644 --- a/src/Drivers/Imagick/Encoders/BmpEncoder.php +++ b/src/Drivers/Imagick/Encoders/BmpEncoder.php @@ -4,15 +4,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders; use Imagick; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; -use Intervention\Image\Drivers\Imagick\Traits\CanReduceColors; +use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; class BmpEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; - public function __construct(protected int $color_limit = 0) { // @@ -23,12 +21,12 @@ class BmpEncoder extends AbstractEncoder implements EncoderInterface $format = 'bmp'; $compression = Imagick::COMPRESSION_NO; + $image = $image->modify(new LimitColorsModifier($this->color_limit)); $imagick = $image->frame()->core(); $imagick->setFormat($format); $imagick->setImageFormat($format); $imagick->setCompression($compression); $imagick->setImageCompression($compression); - $this->maybeReduceColors($imagick, $this->color_limit); return new EncodedImage($imagick->getImagesBlob(), 'image/bmp'); } diff --git a/src/Drivers/Imagick/Encoders/GifEncoder.php b/src/Drivers/Imagick/Encoders/GifEncoder.php index ef709b24..2e56158b 100644 --- a/src/Drivers/Imagick/Encoders/GifEncoder.php +++ b/src/Drivers/Imagick/Encoders/GifEncoder.php @@ -5,15 +5,16 @@ namespace Intervention\Image\Drivers\Imagick\Encoders; use Imagick; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; use Intervention\Image\Drivers\Imagick\Image; -use Intervention\Image\Drivers\Imagick\Traits\CanReduceColors; +use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Exceptions\EncoderException; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\Traits\CanCheckType; class GifEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; + use CanCheckType; public function __construct(protected int $color_limit = 0) { @@ -29,13 +30,15 @@ class GifEncoder extends AbstractEncoder implements EncoderInterface throw new EncoderException('Image does not match the current driver.'); } + $image = $this->failIfNotClass($image, Image::class); + + $image = $image->modify(new LimitColorsModifier($this->color_limit)); $imagick = $image->getImagick(); $imagick->setFormat($format); $imagick->setImageFormat($format); $imagick->setCompression($compression); $imagick->setImageCompression($compression); $imagick->optimizeImageLayers(); - $this->maybeReduceColors($imagick, $this->color_limit); $imagick = $imagick->deconstructImages(); return new EncodedImage($imagick->getImagesBlob(), 'image/gif'); diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index aacf6763..4c31ca8b 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -4,15 +4,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders; use Imagick; use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder; -use Intervention\Image\Drivers\Imagick\Traits\CanReduceColors; +use Intervention\Image\Drivers\Imagick\Modifiers\LimitColorsModifier; use Intervention\Image\EncodedImage; use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\ImageInterface; class PngEncoder extends AbstractEncoder implements EncoderInterface { - use CanReduceColors; - public function __construct(protected int $color_limit = 0) { // @@ -23,12 +21,12 @@ class PngEncoder extends AbstractEncoder implements EncoderInterface $format = 'png'; $compression = Imagick::COMPRESSION_ZIP; + $image = $image->modify(new LimitColorsModifier($this->color_limit)); $imagick = $image->frame()->core(); $imagick->setFormat($format); $imagick->setImageFormat($format); $imagick->setCompression($compression); $imagick->setImageCompression($compression); - $this->maybeReduceColors($imagick, $this->color_limit); return new EncodedImage($imagick->getImagesBlob(), 'image/png'); } diff --git a/src/Drivers/Imagick/Modifiers/LimitColorsModifier.php b/src/Drivers/Imagick/Modifiers/LimitColorsModifier.php new file mode 100644 index 00000000..142794f5 --- /dev/null +++ b/src/Drivers/Imagick/Modifiers/LimitColorsModifier.php @@ -0,0 +1,44 @@ +limit === 0) { + return $image; + } + + // limit is over threshold: no reduction + if ($this->limit > $this->threshold) { + return $image; + } + + $image = $this->failIfNotClass($image, Image::class); + foreach ($image->getImagick() as $core) { + $core->quantizeImage( + $this->limit, + $core->getImageColorspace(), + 0, + false, + false + ); + } + + return $image; + } +} diff --git a/src/Drivers/Imagick/Traits/CanReduceColors.php b/src/Drivers/Imagick/Traits/CanReduceColors.php deleted file mode 100644 index 04b62d0b..00000000 --- a/src/Drivers/Imagick/Traits/CanReduceColors.php +++ /dev/null @@ -1,38 +0,0 @@ - $threshold) { - return $imagick; - } - - $imagick->quantizeImage( - $limit, - $imagick->getImageColorspace(), - 0, - false, - false - ); - - return $imagick; - } -}