Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/main/php/img/io/AvifStreamReader.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php namespace img\io;

use img\ImagingException;

/**
* Reads Avif from an image
*
* @ext gd
* @see https://www.php.net/manual/en/function.imagecreatefromavif.php
* @see img.io.StreamReader
*/
class AvifStreamReader extends StreamReader implements UriReader {

/**
* Read image
*
* @param string uri
* @return resource
* @throws img.ImagingException
*/
public function readImageFromUri($uri) {
if (false === ($r= imagecreatefromavif($uri))) {
$e= new ImagingException('Cannot read image from "'.$uri.'"');
\xp::gc(__FILE__);
throw $e;
}
return $r;
}
}
45 changes: 45 additions & 0 deletions src/main/php/img/io/AvifStreamWriter.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php namespace img\io;

/**
* Writes Avif to a stream
*
* @ext gd
* @see https://www.php.net/manual/en/function.imageavif.php
* @see img.io.StreamWriter
*/
class AvifStreamWriter extends StreamWriter {
public $quality;

/**
* Constructor
*
* @param io.Stream stream
* @param int quality default -1
*/
public function __construct($stream, $quality= -1) {
parent::__construct($stream);
$this->quality= $quality;
}

/**
* Output an image
*
* @param resource handle
* @return bool
*/
public function output($handle) {
if (imageistruecolor($handle)) return imageavif($handle, null, $this->quality);

// Prevent "imageavif(): avif error - avif doesn't support palette images"
$width= imagesx($handle);
$height= imagesy($handle);
$copy= imagecreatetruecolor($width, $height);
imagecopy($copy, $handle, 0, 0, 0, 0, $width, $height);

try {
return imageavif($copy, null, $this->quality);
} finally {
PHP_VERSION_ID <= 80000 && imagedestroy($copy);
}
}
}
16 changes: 16 additions & 0 deletions src/test/php/img/unittest/AvifImageReaderTest.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php namespace img\unittest;

use img\Image;
use img\io\AvifStreamReader;
use io\streams\MemoryInputStream;
use test\Test;

#[ImageTypeSupport('avif')]
class AvifImageReaderTest {
const BYTES= 'AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABoAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAABAA0AAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACJtZGF0EgAKCBgABggIaAwgMgwXgAkkkkQAAHlM1uhudWxsCg==';

#[Test]
public function read() {
Image::loadFrom(new AvifStreamReader(new MemoryInputStream(base64_decode(self::BYTES))));
}
}
27 changes: 27 additions & 0 deletions src/test/php/img/unittest/AvifImageWriterTest.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php namespace img\unittest;

use img\ImagingException;
use img\io\AvifStreamWriter;
use io\OperationFailed;
use io\streams\{MemoryOutputStream, OutputStream};
use test\{Assert, Expect, Test};

#[ImageTypeSupport('avif')]
class AvifImageWriterTest extends AbstractImageWriterTest {

#[Test, Expect(ImagingException::class)]
public function write_error() {
$this->image->saveTo(new AvifStreamWriter(new class() implements OutputStream {
public function write($arg) { throw new OperationFailed('Could not write: Intentional exception'); }
public function flush() { }
public function close() { }
}));
}

#[Test]
public function write() {
$s= new MemoryOutputStream();
$this->image->saveTo(new AvifStreamWriter($s));
Assert::notEquals('', $s->bytes());
}
}
2 changes: 1 addition & 1 deletion src/test/php/img/unittest/ImageTypeSupport.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function assertions(Context $context) {
$supported= imagetypes();
foreach ($this->types as $type) {
yield new Assertion(
$supported & constant('IMG_'.strtoupper($type)),
$supported & defined('IMG_'.strtoupper($type)),
new Verify('Image type "'.$type.'" is supported')
);
}
Expand Down
Loading