Skip to content

Added suport for AVIF to getimagesize(). #5127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
109 changes: 109 additions & 0 deletions ext/standard/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ PHPAPI const char php_sig_iff[4] = {'F','O','R','M'};
PHPAPI const char php_sig_ico[4] = {(char)0x00, (char)0x00, (char)0x01, (char)0x00};
PHPAPI const char php_sig_riff[4] = {'R', 'I', 'F', 'F'};
PHPAPI const char php_sig_webp[4] = {'W', 'E', 'B', 'P'};
PHPAPI const char php_sig_avif[4] = {'a', 'v', 'i', 'f'};

/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
Expand Down Expand Up @@ -88,6 +89,7 @@ PHP_MINIT_FUNCTION(imagetypes)
REGISTER_LONG_CONSTANT("IMAGETYPE_XBM", IMAGE_FILETYPE_XBM, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
Expand Down Expand Up @@ -1148,6 +1150,103 @@ static struct gfxinfo *php_handle_webp(php_stream * stream)
}
/* }}} */

/* {{{ php_handle_avif
*/
static struct gfxinfo *php_handle_avif(php_stream * stream) {
struct gfxinfo *result = NULL;
unsigned int width = 0, height = 0;
unsigned char channels = 0, bits = 0, i, bits_tmp;
unsigned int size, type;
size_t begin, end, pos = 0;
int check_ispe = 0, check_pixi = 0, eof;

if (php_stream_seek(stream, 0, SEEK_SET)) {
return NULL;
}
for(;;) {
eof = php_stream_eof(stream);
if (eof == -1) {
return NULL;
} else if ((check_ispe == 1 && check_pixi == 1) || eof == 1) {
break;
}

begin = pos;
size = php_read4(stream); pos += 4;
type = php_read4(stream); pos += 4;
end = begin + size;

switch (type) {
case 1835365473u: /* meta */
if (php_stream_seek(stream, 4, SEEK_CUR)) {
return NULL;
}
pos += 4;
continue;

case 1768977008u: /* iprp */
case 1768973167u: /* ipco */
continue;

case 1769173093u: /* ispe */
if (php_stream_seek(stream, 4, SEEK_CUR)) {
return NULL;
}
pos += 4;
width = php_read4(stream); pos += 4;
height = php_read4(stream); pos += 4;
check_ispe = 1;
break;

case 1885960297u: /* pixi */
if (php_stream_seek(stream, 4, SEEK_CUR)) {
return NULL;
}
pos += 4;

/* channels */
if (php_stream_read(stream, (char *)&channels, 1) != 1) {
return NULL;
}
pos++;

/* bits */
for (i = 0; i < channels; i++) {
if (php_stream_read(stream, (char *)&bits_tmp, 1) != 1) {
return NULL;
}
pos++;

if (bits_tmp > bits) {
bits = bits_tmp;
}
}
check_pixi = 1;
break;

default:
break;
}

pos = end;
if (php_stream_seek(stream, end, SEEK_SET)) {
return NULL;
}
}

result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
if (result == NULL) {
return NULL;
}

result->width = width;
result->height = height;
result->bits = bits;
result->channels = channels;
return result;
}
/* }}} */

/* {{{ php_image_type_to_mime_type
* Convert internal image_type to mime type */
PHPAPI char * php_image_type_to_mime_type(int image_type)
Expand Down Expand Up @@ -1183,6 +1282,8 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
return "image/vnd.microsoft.icon";
case IMAGE_FILETYPE_WEBP:
return "image/webp";
case IMAGE_FILETYPE_AVIF:
return "image/avif";
default:
case IMAGE_FILETYPE_UNKNOWN:
return "application/octet-stream"; /* suppose binary format */
Expand Down Expand Up @@ -1265,6 +1366,9 @@ PHP_FUNCTION(image_type_to_extension)
case IMAGE_FILETYPE_WEBP:
imgext = ".webp";
break;
case IMAGE_FILETYPE_AVIF:
imgext = ".avif";
break;
}

if (imgext) {
Expand Down Expand Up @@ -1347,6 +1451,8 @@ PHPAPI int php_getimagetype(php_stream * stream, const char *input, char *filety
/* BYTES READ: 12 */
if (twelve_bytes_read && !memcmp(filetype, php_sig_jp2, 12)) {
return IMAGE_FILETYPE_JP2;
} else if (twelve_bytes_read && !memcmp(filetype+8, php_sig_avif, 4)) {
return IMAGE_FILETYPE_AVIF;
}

/* AFTER ALL ABOVE FAILED */
Expand Down Expand Up @@ -1431,6 +1537,9 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
case IMAGE_FILETYPE_WEBP:
result = php_handle_webp(stream);
break;
case IMAGE_FILETYPE_AVIF:
result = php_handle_avif(stream);
break;
default:
case IMAGE_FILETYPE_UNKNOWN:
break;
Expand Down
1 change: 1 addition & 0 deletions ext/standard/php_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef enum
IMAGE_FILETYPE_XBM,
IMAGE_FILETYPE_ICO,
IMAGE_FILETYPE_WEBP,
IMAGE_FILETYPE_AVIF,
/* WHEN EXTENDING: PLEASE ALSO REGISTER IN image.c:PHP_MINIT_FUNCTION(imagetypes) */
IMAGE_FILETYPE_COUNT
} image_filetype;
Expand Down
19 changes: 18 additions & 1 deletion ext/standard/tests/image/getimagesize.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ GetImageSize()
var_dump($result);
?>
--EXPECT--
array(16) {
array(17) {
["test-1pix.bmp"]=>
array(6) {
[0]=>
Expand Down Expand Up @@ -268,4 +268,21 @@ array(16) {
["mime"]=>
string(10) "image/tiff"
}
["test8pix.avif"]=>
array(7) {
[0]=>
int(8)
[1]=>
int(1)
[2]=>
int(19)
[3]=>
string(20) "width="8" height="1""
["bits"]=>
int(8)
["channels"]=>
int(3)
["mime"]=>
string(10) "image/avif"
}
}
34 changes: 34 additions & 0 deletions ext/standard/tests/image/getimagesize_avif_monochrome.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
--TEST--
GetImageSize() for avif using monochrome format
--FILE--
<?php
/* Prototype : proto array getimagesize(string imagefile [, array info])
* Description: Get the size of an image as 4-element array
* Source code: ext/standard/image.c
* Alias to functions:
*/

echo "*** Testing getimagesize() : avif using monochrome format ***\n";
var_dump(getimagesize(__DIR__ . "/monochrome.avif", $arr));
var_dump($arr);
?>
--EXPECT--
*** Testing getimagesize() : avif using monochrome format ***
array(7) {
[0]=>
int(8)
[1]=>
int(1)
[2]=>
int(19)
[3]=>
string(20) "width="8" height="1""
["bits"]=>
int(8)
["channels"]=>
int(1)
["mime"]=>
string(10) "image/avif"
}
array(0) {
}
6 changes: 5 additions & 1 deletion ext/standard/tests/image/image_type_to_extension.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ image_type_to_extension()
"IMAGETYPE_WBMP" => IMAGETYPE_WBMP,
"IMAGETYPE_JPEG2000" => IMAGETYPE_JPEG2000,
"IMAGETYPE_XBM" => IMAGETYPE_XBM,
"IMAGETYPE_WEBP" => IMAGETYPE_WEBP
"IMAGETYPE_WEBP" => IMAGETYPE_WEBP,
"IMAGETYPE_AVIF" => IMAGETYPE_AVIF
);
foreach($constants as $name => $constant) {
printf("Constant: %s\n\tWith dot: %s\n\tWithout dot: %s\n", $name, image_type_to_extension($constant), image_type_to_extension($constant, false));
Expand Down Expand Up @@ -85,6 +86,9 @@ Constant: IMAGETYPE_XBM
Constant: IMAGETYPE_WEBP
With dot: .webp
Without dot: webp
Constant: IMAGETYPE_AVIF
With dot: .avif
Without dot: avif
bool(false)
bool(false)
Done
4 changes: 3 additions & 1 deletion ext/standard/tests/image/image_type_to_mime_type.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ image_type_to_mime_type()
var_dump($result);
?>
--EXPECT--
array(16) {
array(17) {
["test-1pix.bmp"]=>
string(9) "image/bmp"
["test12pix.webp"]=>
Expand Down Expand Up @@ -57,4 +57,6 @@ array(16) {
string(29) "application/x-shockwave-flash"
["test4pix.tiff"]=>
string(10) "image/tiff"
["test8pix.avif"]=>
string(10) "image/avif"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ $image_types = array (
IMAGETYPE_WBMP,
IMAGETYPE_JPEG2000,
IMAGETYPE_XBM,
IMAGETYPE_WEBP
IMAGETYPE_WEBP,
IMAGETYPE_AVIF
);

foreach($image_types as $image_type) {
Expand Down Expand Up @@ -51,5 +52,6 @@ string(18) "image/vnd.wap.wbmp"
string(24) "application/octet-stream"
string(9) "image/xbm"
string(10) "image/webp"
string(10) "image/avif"

Done image_type_to_mime_type() test
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@ string\(24\) "image\/vnd.microsoft.icon"
string\(10\) "image\/webp"

-- Iteration 19 --
string\(10\) "image\/avif"

-- Iteration 20 --
string\(24\) "application\/octet-stream"
Binary file added ext/standard/tests/image/monochrome.avif
Binary file not shown.
Binary file added ext/standard/tests/image/test8pix.avif
Binary file not shown.