mirror of
https://github.com/Intervention/image.git
synced 2025-08-14 01:44:03 +02:00
Merge pull request #1277 from Intervention/feature/1253-add-transparency-param-for-place
Add opacity parameter to PlaceModifier
This commit is contained in:
@@ -5,8 +5,10 @@ declare(strict_types=1);
|
|||||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||||
|
|
||||||
use Intervention\Image\Drivers\DriverSpecialized;
|
use Intervention\Image\Drivers\DriverSpecialized;
|
||||||
|
use Intervention\Image\Interfaces\FrameInterface;
|
||||||
use Intervention\Image\Interfaces\ImageInterface;
|
use Intervention\Image\Interfaces\ImageInterface;
|
||||||
use Intervention\Image\Interfaces\ModifierInterface;
|
use Intervention\Image\Interfaces\ModifierInterface;
|
||||||
|
use Intervention\Image\Interfaces\PointInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method mixed getPosition(ImageInterface $image, ImageInterface $watermark)
|
* @method mixed getPosition(ImageInterface $image, ImageInterface $watermark)
|
||||||
@@ -14,6 +16,7 @@ use Intervention\Image\Interfaces\ModifierInterface;
|
|||||||
* @property string $position
|
* @property string $position
|
||||||
* @property int $offset_x
|
* @property int $offset_x
|
||||||
* @property int $offset_y
|
* @property int $offset_y
|
||||||
|
* @property int $opacity
|
||||||
*/
|
*/
|
||||||
class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
||||||
{
|
{
|
||||||
@@ -24,18 +27,93 @@ class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
|||||||
|
|
||||||
foreach ($image as $frame) {
|
foreach ($image as $frame) {
|
||||||
imagealphablending($frame->native(), true);
|
imagealphablending($frame->native(), true);
|
||||||
imagecopy(
|
|
||||||
$frame->native(),
|
if ($this->opacity === 100) {
|
||||||
$watermark->core()->native(),
|
$this->placeOpaque($frame, $watermark, $position);
|
||||||
$position->x(),
|
} else {
|
||||||
$position->y(),
|
$this->placeTransparent($frame, $watermark, $position);
|
||||||
0,
|
}
|
||||||
0,
|
|
||||||
$watermark->width(),
|
|
||||||
$watermark->height()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $image;
|
return $image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert watermark with 100% opacity
|
||||||
|
*
|
||||||
|
* @param FrameInterface $frame
|
||||||
|
* @param ImageInterface $watermark
|
||||||
|
* @param PointInterface $position
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function placeOpaque(FrameInterface $frame, ImageInterface $watermark, PointInterface $position): void
|
||||||
|
{
|
||||||
|
imagecopy(
|
||||||
|
$frame->native(),
|
||||||
|
$watermark->core()->native(),
|
||||||
|
$position->x(),
|
||||||
|
$position->y(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
$watermark->width(),
|
||||||
|
$watermark->height()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert watermark transparent with current opacity
|
||||||
|
*
|
||||||
|
* Unfortunately, the original PHP function imagecopymerge does not work reliably.
|
||||||
|
* For example, any transparency of the image to be inserted is not applied correctly.
|
||||||
|
* For this reason, a new GDImage is created into which the original image is inserted
|
||||||
|
* in the first step and the watermark is inserted with 100% opacity in the second
|
||||||
|
* step. This combination is then transferred to the original image again with the
|
||||||
|
* respective opacity.
|
||||||
|
*
|
||||||
|
* Please note: Unfortunately, there is still an edge case, when a transparent image
|
||||||
|
* is placed on a transparent background, the "double" transparent areas appear opaque!
|
||||||
|
*
|
||||||
|
* @param FrameInterface $frame
|
||||||
|
* @param ImageInterface $watermark
|
||||||
|
* @param PointInterface $position
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function placeTransparent(FrameInterface $frame, ImageInterface $watermark, PointInterface $position): void
|
||||||
|
{
|
||||||
|
$cut = imagecreatetruecolor($watermark->width(), $watermark->height());
|
||||||
|
|
||||||
|
imagecopy(
|
||||||
|
$cut,
|
||||||
|
$frame->native(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
$position->x(),
|
||||||
|
$position->y(),
|
||||||
|
imagesx($cut),
|
||||||
|
imagesy($cut)
|
||||||
|
);
|
||||||
|
|
||||||
|
imagecopy(
|
||||||
|
$cut,
|
||||||
|
$watermark->core()->native(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
imagesx($cut),
|
||||||
|
imagesy($cut)
|
||||||
|
);
|
||||||
|
|
||||||
|
imagecopymerge(
|
||||||
|
$frame->native(),
|
||||||
|
$cut,
|
||||||
|
$position->x(),
|
||||||
|
$position->y(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
$watermark->width(),
|
||||||
|
$watermark->height(),
|
||||||
|
$this->opacity
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ use Intervention\Image\Interfaces\ModifierInterface;
|
|||||||
* @property string $position
|
* @property string $position
|
||||||
* @property int $offset_x
|
* @property int $offset_x
|
||||||
* @property int $offset_y
|
* @property int $offset_y
|
||||||
|
* @property int $opacity
|
||||||
*/
|
*/
|
||||||
class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
||||||
{
|
{
|
||||||
@@ -23,6 +24,15 @@ class PlaceModifier extends DriverSpecialized implements ModifierInterface
|
|||||||
$watermark = $this->driver()->handleInput($this->element);
|
$watermark = $this->driver()->handleInput($this->element);
|
||||||
$position = $this->getPosition($image, $watermark);
|
$position = $this->getPosition($image, $watermark);
|
||||||
|
|
||||||
|
// set opacity of watermark
|
||||||
|
if ($this->opacity < 100) {
|
||||||
|
$watermark->core()->native()->evaluateImage(
|
||||||
|
Imagick::EVALUATE_DIVIDE,
|
||||||
|
$this->opacity > 0 ? (100 / $this->opacity) : 1000,
|
||||||
|
Imagick::CHANNEL_ALPHA,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($image as $frame) {
|
foreach ($image as $frame) {
|
||||||
$frame->native()->compositeImage(
|
$frame->native()->compositeImage(
|
||||||
$watermark->core()->native(),
|
$watermark->core()->native(),
|
||||||
|
@@ -744,9 +744,10 @@ final class Image implements ImageInterface
|
|||||||
mixed $element,
|
mixed $element,
|
||||||
string $position = 'top-left',
|
string $position = 'top-left',
|
||||||
int $offset_x = 0,
|
int $offset_x = 0,
|
||||||
int $offset_y = 0
|
int $offset_y = 0,
|
||||||
|
int $opacity = 100
|
||||||
): ImageInterface {
|
): ImageInterface {
|
||||||
return $this->modify(new PlaceModifier($element, $position, $offset_x, $offset_y));
|
return $this->modify(new PlaceModifier($element, $position, $offset_x, $offset_y, $opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||||||
namespace Intervention\Image\Interfaces;
|
namespace Intervention\Image\Interfaces;
|
||||||
|
|
||||||
use Countable;
|
use Countable;
|
||||||
use Intervention\Image\EncodedImage;
|
|
||||||
use Intervention\Image\Origin;
|
use Intervention\Image\Origin;
|
||||||
use IteratorAggregate;
|
use IteratorAggregate;
|
||||||
|
|
||||||
@@ -522,13 +521,15 @@ interface ImageInterface extends IteratorAggregate, Countable
|
|||||||
* @param string $position
|
* @param string $position
|
||||||
* @param int $offset_x
|
* @param int $offset_x
|
||||||
* @param int $offset_y
|
* @param int $offset_y
|
||||||
|
* @param int $opacity
|
||||||
* @return ImageInterface
|
* @return ImageInterface
|
||||||
*/
|
*/
|
||||||
public function place(
|
public function place(
|
||||||
mixed $element,
|
mixed $element,
|
||||||
string $position = 'top-left',
|
string $position = 'top-left',
|
||||||
int $offset_x = 0,
|
int $offset_x = 0,
|
||||||
int $offset_y = 0
|
int $offset_y = 0,
|
||||||
|
int $opacity = 100
|
||||||
): ImageInterface;
|
): ImageInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -13,7 +13,8 @@ class PlaceModifier extends SpecializableModifier
|
|||||||
public mixed $element,
|
public mixed $element,
|
||||||
public string $position,
|
public string $position,
|
||||||
public int $offset_x,
|
public int $offset_x,
|
||||||
public int $offset_y
|
public int $offset_y,
|
||||||
|
public int $opacity = 100
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,4 +24,12 @@ class PlaceModifierTest extends TestCase
|
|||||||
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0));
|
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0));
|
||||||
$this->assertEquals('32250d', $image->pickColor(300, 25)->toHex());
|
$this->assertEquals('32250d', $image->pickColor(300, 25)->toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testColorChangeOpacity(): void
|
||||||
|
{
|
||||||
|
$image = $this->readTestImage('test.jpg');
|
||||||
|
$this->assertEquals('febc44', $image->pickColor(300, 25)->toHex());
|
||||||
|
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0, 50));
|
||||||
|
$this->assertEquals('987028', $image->pickColor(300, 25)->toHex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,4 +24,12 @@ class PlaceModifierTest extends TestCase
|
|||||||
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0));
|
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0));
|
||||||
$this->assertEquals('33260e', $image->pickColor(300, 25)->toHex());
|
$this->assertEquals('33260e', $image->pickColor(300, 25)->toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testColorChangeOpacity(): void
|
||||||
|
{
|
||||||
|
$image = $this->readTestImage('test.jpg');
|
||||||
|
$this->assertEquals('febc44', $image->pickColor(300, 25)->toHex());
|
||||||
|
$image->modify(new PlaceModifier(__DIR__ . '/../../../images/circle.png', 'top-right', 0, 0, 50));
|
||||||
|
$this->assertEquals('987129', $image->pickColor(300, 25)->toHex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user