mirror of
https://github.com/Intervention/image.git
synced 2025-08-13 17:34:04 +02:00
Add Image::reduceColors()
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverSpecializedModifier;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
/**
|
||||
* @property int $limit
|
||||
* @property int $threshold
|
||||
*/
|
||||
class LimitColorsModifier extends DriverSpecializedModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
// no color limit: no reduction
|
||||
if ($this->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) {
|
||||
// limitied color image must be palette (indexed) GDImage
|
||||
$reduced = imagecreate($width, $height);
|
||||
|
||||
// save alpha channel
|
||||
imagesavealpha($reduced, true);
|
||||
|
||||
// create matte
|
||||
$matte = imagecolorallocatealpha($reduced, 255, 255, 255, 127);
|
||||
|
||||
// fill with matte
|
||||
imagefill($reduced, 0, 0, $matte);
|
||||
|
||||
// disable alpha blending for the copy process
|
||||
imagealphablending($reduced, false);
|
||||
|
||||
// set transparency and get transparency index
|
||||
imagecolortransparent($reduced, $matte);
|
||||
|
||||
// copy original image (colors are limited automatically in the copy process)
|
||||
imagecopy($reduced, $frame->native(), 0, 0, 0, 0, $width, $height);
|
||||
|
||||
// reduce limit by one to include possible transparency in palette
|
||||
// $limit = imagecolortransparent($frame->native()) === -1 ? $this->limit : $this->limit - 1;
|
||||
|
||||
// decrease colors
|
||||
// imagetruecolortopalette($reduced, true, $limit);
|
||||
|
||||
$frame->setNative($reduced);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
56
src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php
Normal file
56
src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverSpecializedModifier;
|
||||
use Intervention\Image\Exceptions\InputException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
/**
|
||||
* @property int $limit
|
||||
* @property mixed $background
|
||||
*/
|
||||
class QuantizeColorsModifier extends DriverSpecializedModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
if ($this->limit <= 0) {
|
||||
throw new InputException('Quantization limit must be greater than 0.');
|
||||
}
|
||||
|
||||
// no color reduction if the limit is higher than the colors in the img
|
||||
$colorCount = imagecolorstotal($image->core()->native());
|
||||
if ($colorCount > 0 && $this->limit > $colorCount) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$width = $image->width();
|
||||
$height = $image->height();
|
||||
|
||||
$background = $this->driver()->colorProcessor($image->colorspace())->colorToNative(
|
||||
$this->driver()->handleInput($this->background)
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
// create new image for color quantization
|
||||
$reduced = imagecreatetruecolor($width, $height);
|
||||
|
||||
// fill with background
|
||||
imagefill($reduced, 0, 0, $background);
|
||||
|
||||
// set transparency
|
||||
imagecolortransparent($reduced, $background);
|
||||
|
||||
// copy original image (colors are limited automatically in the copy process)
|
||||
imagecopy($reduced, $frame->native(), 0, 0, 0, 0, $width, $height);
|
||||
|
||||
// gd library does not support color quantization directly therefore the
|
||||
// colors are decrease by transforming the image to a palette version
|
||||
imagetruecolortopalette($reduced, true, $this->limit);
|
||||
|
||||
$frame->setNative($reduced);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
@@ -3,23 +3,23 @@
|
||||
namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\DriverSpecializedModifier;
|
||||
use Intervention\Image\Exceptions\InputException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
/**
|
||||
* @property int $limit
|
||||
* @property int $threshold
|
||||
* @property mixed $background
|
||||
*/
|
||||
class LimitColorsModifier extends DriverSpecializedModifier
|
||||
class QuantizeColorsModifier extends DriverSpecializedModifier
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
// no color limit: no reduction
|
||||
if ($this->limit === 0) {
|
||||
return $image;
|
||||
if ($this->limit <= 0) {
|
||||
throw new InputException('Quantization limit must be greater than 0.');
|
||||
}
|
||||
|
||||
// limit is over threshold: no reduction
|
||||
if ($this->limit > $this->threshold) {
|
||||
// no color reduction if the limit is higher than the colors in the img
|
||||
if ($this->limit > $image->core()->native()->getImageColors()) {
|
||||
return $image;
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ use Intervention\Image\Modifiers\PixelateModifier;
|
||||
use Intervention\Image\Modifiers\PlaceModifier;
|
||||
use Intervention\Image\Modifiers\ProfileModifier;
|
||||
use Intervention\Image\Modifiers\ProfileRemovalModifier;
|
||||
use Intervention\Image\Modifiers\QuantizeColorsModifier;
|
||||
use Intervention\Image\Modifiers\RemoveAnimationModifier;
|
||||
use Intervention\Image\Modifiers\ResizeCanvasModifier;
|
||||
use Intervention\Image\Modifiers\ResizeCanvasRelativeModifier;
|
||||
@@ -366,6 +367,16 @@ final class Image implements ImageInterface, Countable
|
||||
return $this->modify(new ProfileRemovalModifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ImageInterface::reduceColors()
|
||||
*/
|
||||
public function reduceColors(int $limit, mixed $background = 'transparent'): ImageInterface
|
||||
{
|
||||
return $this->modify(new QuantizeColorsModifier($limit, $background));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
|
@@ -198,6 +198,14 @@ interface ImageInterface extends IteratorAggregate, Countable
|
||||
*/
|
||||
public function removeProfile(): ImageInterface;
|
||||
|
||||
/**
|
||||
* Apply color quantization to the current image
|
||||
*
|
||||
* @param int $limit
|
||||
* @return ImageInterface
|
||||
*/
|
||||
public function reduceColors(int $limit): ImageInterface;
|
||||
|
||||
/**
|
||||
* Sharpen the current image with given strength
|
||||
*
|
||||
|
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Modifiers;
|
||||
|
||||
class LimitColorsModifier extends AbstractModifier
|
||||
{
|
||||
public function __construct(
|
||||
public int $limit = 0,
|
||||
public int $threshold = 256
|
||||
) {
|
||||
}
|
||||
}
|
12
src/Modifiers/QuantizeColorsModifier.php
Normal file
12
src/Modifiers/QuantizeColorsModifier.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Modifiers;
|
||||
|
||||
class QuantizeColorsModifier extends AbstractModifier
|
||||
{
|
||||
public function __construct(
|
||||
public int $limit,
|
||||
public mixed $background = 'ffffff'
|
||||
) {
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user