1
0
mirror of https://github.com/Intervention/image.git synced 2025-09-08 21:20:46 +02:00

Add Encoder Options for progressive Jpeg & interlaced GIF format

This commit is contained in:
Oliver Vogel
2024-03-27 15:30:28 +01:00
committed by GitHub
parent c261654599
commit d982359ab8
18 changed files with 203 additions and 39 deletions

View File

@@ -35,4 +35,22 @@ abstract class ImagickTestCase extends BaseTestCase
new Core($imagick)
);
}
public function createTestAnimation(): Image
{
$imagick = new Imagick();
$imagick->setFormat('gif');
for ($i = 0; $i < 3; $i++) {
$frame = new Imagick();
$frame->newImage(3, 2, new ImagickPixel('rgb(255, 0, 0)'), 'gif');
$frame->setImageDelay(10);
$imagick->addImage($frame);
}
return new Image(
new Driver(),
new Core($imagick)
);
}
}

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\Traits\CanBuildFilePointer;
trait CanDetectProgressiveJpeg
{
use CanBuildFilePointer;
/**
* Checks if the given image data is progressive encoded Jpeg format
*
* @param string $imagedata
* @return bool
*/
private function isProgressiveJpeg(string $imagedata): bool
{
$f = $this->buildFilePointer($imagedata);
while (!feof($f)) {
if (unpack('C', fread($f, 1))[1] !== 0xff) {
return false;
}
$blockType = unpack('C', fread($f, 1))[1];
switch (true) {
case $blockType == 0xd8:
case $blockType >= 0xd0 && $blockType <= 0xd7:
break;
case $blockType == 0xc0:
fclose($f);
return false;
case $blockType == 0xc2:
fclose($f);
return true;
case $blockType == 0xd9:
break 2;
default:
$blockSize = unpack('n', fread($f, 2))[1];
fseek($f, $blockSize - 2, SEEK_CUR);
break;
}
}
fclose($f);
return false;
}
}

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Tests\Unit\Drivers\Gd\Encoders;
use Intervention\Gif\Decoder;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use Intervention\Image\Encoders\GifEncoder;
@@ -20,5 +21,30 @@ final class GifEncoderTest extends GdTestCase
$encoder = new GifEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
public function testEncodeInterlaced(): void
{
$image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
public function testEncodeInterlacedAnimation(): void
{
$image = $this->createTestAnimation(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
}

View File

@@ -8,12 +8,15 @@ use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Tests\GdTestCase;
use Intervention\Image\Tests\Traits\CanDetectProgressiveJpeg;
#[RequiresPhpExtension('gd')]
#[CoversClass(\Intervention\Image\Encoders\JpegEncoder::class)]
#[CoversClass(\Intervention\Image\Drivers\Gd\Encoders\JpegEncoder::class)]
final class JpegEncoderTest extends GdTestCase
{
use CanDetectProgressiveJpeg;
public function testEncode(): void
{
$image = $this->createTestImage(3, 2);
@@ -21,4 +24,13 @@ final class JpegEncoderTest extends GdTestCase
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
}
public function testEncodeProgressive(): void
{
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(progressive: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertTrue($this->isProgressiveJpeg((string) $result));
}
}

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Encoders;
use Intervention\Gif\Decoder;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use Intervention\Image\Encoders\GifEncoder;
@@ -20,5 +21,30 @@ final class GifEncoderTest extends ImagickTestCase
$encoder = new GifEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
public function testEncodeInterlaced(): void
{
$image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
public function testEncodeInterlacedAnimation(): void
{
$image = $this->createTestAnimation();
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
}
}

View File

@@ -8,12 +8,15 @@ use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Tests\ImagickTestCase;
use Intervention\Image\Tests\Traits\CanDetectProgressiveJpeg;
#[RequiresPhpExtension('imagick')]
#[CoversClass(\Intervention\Image\Encoders\JpegEncoder::class)]
#[CoversClass(\Intervention\Image\Drivers\Imagick\Encoders\JpegEncoder::class)]
final class JpegEncoderTest extends ImagickTestCase
{
use CanDetectProgressiveJpeg;
public function testEncode(): void
{
$image = $this->createTestImage(3, 2);
@@ -21,4 +24,13 @@ final class JpegEncoderTest extends ImagickTestCase
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
}
public function testEncodeProgressive(): void
{
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(progressive: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertTrue($this->isProgressiveJpeg((string) $result));
}
}