diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index 8a94b63e..6b20ea91 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -13,8 +13,11 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $data = $this->buffered(function () use ($image) { - imagepng($image->core()->native(), null, -1); + $gd = $image->core()->native(); + $data = $this->buffered(function () use ($gd) { + imageinterlace($gd, $this->interlaced); + imagepng($gd, null, -1); + imageinterlace($gd, false); }); return new EncodedImage($data, 'image/png'); diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index adc70d7d..b6614ba1 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -23,6 +23,10 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface $imagick->setCompression($compression); $imagick->setImageCompression($compression); + if ($this->interlaced) { + $imagick->setInterlaceScheme(Imagick::INTERLACE_LINE); + } + return new EncodedImage($imagick->getImagesBlob(), 'image/png'); } } diff --git a/src/Encoders/PngEncoder.php b/src/Encoders/PngEncoder.php index cff27945..b6bb6cb5 100644 --- a/src/Encoders/PngEncoder.php +++ b/src/Encoders/PngEncoder.php @@ -8,7 +8,7 @@ use Intervention\Image\Drivers\SpecializableEncoder; class PngEncoder extends SpecializableEncoder { - public function __construct() + public function __construct(public bool $interlaced = false) { } } diff --git a/tests/Traits/CanDetectInterlacedPng.php b/tests/Traits/CanDetectInterlacedPng.php new file mode 100644 index 00000000..19fffe46 --- /dev/null +++ b/tests/Traits/CanDetectInterlacedPng.php @@ -0,0 +1,27 @@ +buildFilePointer($imagedata); + $contents = fread($f, 32); + fclose($f); + + return ord($contents[28]) != 0; + } +} diff --git a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php index 715ba1e3..f49bfb14 100644 --- a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php @@ -8,12 +8,15 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; use Intervention\Image\Tests\GdTestCase; +use Intervention\Image\Tests\Traits\CanDetectInterlacedPng; #[RequiresPhpExtension('gd')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] #[CoversClass(\Intervention\Image\Drivers\Gd\Encoders\PngEncoder::class)] final class PngEncoderTest extends GdTestCase { + use CanDetectInterlacedPng; + public function testEncode(): void { $image = $this->createTestImage(3, 2); @@ -21,4 +24,13 @@ final class PngEncoderTest extends GdTestCase $result = $encoder->encode($image); $this->assertMediaType('image/png', (string) $result); } + + public function testEncodeInterlaced(): void + { + $image = $this->createTestImage(3, 2); + $encoder = new PngEncoder(interlaced: true); + $result = $encoder->encode($image); + $this->assertMediaType('image/png', (string) $result); + $this->assertTrue($this->isInterlacedPng((string) $result)); + } } diff --git a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php index 1be4a09f..304cf4e0 100644 --- a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php @@ -8,17 +8,29 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; use Intervention\Image\Tests\ImagickTestCase; +use Intervention\Image\Tests\Traits\CanDetectInterlacedPng; #[RequiresPhpExtension('imagick')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] #[CoversClass(\Intervention\Image\Drivers\Imagick\Encoders\PngEncoder::class)] final class PngEncoderTest extends ImagickTestCase { + use CanDetectInterlacedPng; + public function testEncode(): void { $image = $this->createTestImage(3, 2); - $encoder = new PngEncoder(75); + $encoder = new PngEncoder(); $result = $encoder->encode($image); $this->assertMediaType('image/png', (string) $result); } + + public function testEncodeInterlaced(): void + { + $image = $this->createTestImage(3, 2); + $encoder = new PngEncoder(interlaced: true); + $result = $encoder->encode($image); + $this->assertMediaType('image/png', (string) $result); + $this->assertTrue($this->isInterlacedPng((string) $result)); + } }