1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-23 14:02:47 +02:00

Add option to encode interlaced PNG format

This commit is contained in:
Oliver Vogel
2024-04-14 09:24:26 +02:00
parent 968f9e498e
commit 490b8ae5c4
6 changed files with 62 additions and 4 deletions

View File

@@ -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');

View File

@@ -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');
}
}

View File

@@ -8,7 +8,7 @@ use Intervention\Image\Drivers\SpecializableEncoder;
class PngEncoder extends SpecializableEncoder
{
public function __construct()
public function __construct(public bool $interlaced = false)
{
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\Traits\CanBuildFilePointer;
trait CanDetectInterlacedPng
{
use CanBuildFilePointer;
/**
* Checks if the given image data is interlaced encoded PNG format
*
* @param string $imagedata
* @return bool
*/
private function isInterlacedPng(string $imagedata): bool
{
$f = $this->buildFilePointer($imagedata);
$contents = fread($f, 32);
fclose($f);
return ord($contents[28]) != 0;
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}