Add support for HEIF/HEIC to getimagesize

Signed-off-by: Benstone Zhang <benstonezhang@gmail.com>
This commit is contained in:
Benstone Zhang 2025-06-25 17:09:36 +08:00 committed by Jakub Zelenka
parent dd3a098a9b
commit dfac2da7fb
No known key found for this signature in database
GPG key ID: 1C0779DC5C0A9DE4
12 changed files with 63 additions and 4 deletions

3
NEWS
View file

@ -14,6 +14,9 @@ PHP NEWS
. socket_set_option for multicast context throws a ValueError . socket_set_option for multicast context throws a ValueError
when the socket family is not of AF_INET/AF_INET6 family. (David Carlier) when the socket family is not of AF_INET/AF_INET6 family. (David Carlier)
- Standard:
. Add HEIF/HEIC support to getimagesize. (Benstone Zhang)
- URI: - URI:
. Empty host handling is fixed. (Máté Kocsis) . Empty host handling is fixed. (Máté Kocsis)
. Error handling of Uri\WhatWg\Url::withHost() is fixed when the input . Error handling of Uri\WhatWg\Url::withHost() is fixed when the input

View file

@ -244,6 +244,7 @@ PHP 8.5 UPGRADE NOTES
process was terminated unexpectedly. In such cases, a warning is emitted process was terminated unexpectedly. In such cases, a warning is emitted
and the function returns false. Previously, these errors were silently and the function returns false. Previously, these errors were silently
ignored. This change affects only the sendmail transport. ignored. This change affects only the sendmail transport.
. getimagesize() now supports HEIF/HEIC images.
- XSL: - XSL:
. The $namespace argument of XSLTProcessor::getParameter(), . The $namespace argument of XSLTProcessor::getParameter(),

View file

@ -646,6 +646,11 @@ const IMAGETYPE_WEBP = UNKNOWN;
* @cvalue IMAGE_FILETYPE_AVIF * @cvalue IMAGE_FILETYPE_AVIF
*/ */
const IMAGETYPE_AVIF = UNKNOWN; const IMAGETYPE_AVIF = UNKNOWN;
/**
* @var int
* @cvalue IMAGE_FILETYPE_HEIF
*/
const IMAGETYPE_HEIF = UNKNOWN;
/** /**
* @var int * @var int
* @cvalue IMAGE_FILETYPE_UNKNOWN * @cvalue IMAGE_FILETYPE_UNKNOWN

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: b9958c8f2f643e072ba7c6ee33ad238ea8dd702e */ * Stub hash: 33629477a13fc7b675fe47eeaaac0d9e15dd2e17 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@ -3645,6 +3645,7 @@ static void register_basic_functions_symbols(int module_number)
REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_HEIF", IMAGE_FILETYPE_HEIF, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("INFO_GENERAL", PHP_INFO_GENERAL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INFO_GENERAL", PHP_INFO_GENERAL, CONST_PERSISTENT);

View file

@ -51,6 +51,10 @@ 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_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_riff[4] = {'R', 'I', 'F', 'F'};
PHPAPI const char php_sig_webp[4] = {'W', 'E', 'B', 'P'}; PHPAPI const char php_sig_webp[4] = {'W', 'E', 'B', 'P'};
PHPAPI const char php_sig_ftyp[4] = {'f', 't', 'y', 'p'};
PHPAPI const char php_sig_mif1[4] = {'m', 'i', 'f', '1'};
PHPAPI const char php_sig_heic[4] = {'h', 'e', 'i', 'c'};
PHPAPI const char php_sig_heix[4] = {'h', 'e', 'i', 'x'};
/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */ /* 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 */ /* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
@ -1254,6 +1258,8 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
return "image/webp"; return "image/webp";
case IMAGE_FILETYPE_AVIF: case IMAGE_FILETYPE_AVIF:
return "image/avif"; return "image/avif";
case IMAGE_FILETYPE_HEIF:
return "image/heif";
default: default:
case IMAGE_FILETYPE_UNKNOWN: case IMAGE_FILETYPE_UNKNOWN:
return "application/octet-stream"; /* suppose binary format */ return "application/octet-stream"; /* suppose binary format */
@ -1339,6 +1345,10 @@ PHP_FUNCTION(image_type_to_extension)
case IMAGE_FILETYPE_AVIF: case IMAGE_FILETYPE_AVIF:
imgext = ".avif"; imgext = ".avif";
break; break;
case IMAGE_FILETYPE_HEIF:
imgext = ".heif";
break;
break;
} }
if (imgext) { if (imgext) {
@ -1423,6 +1433,11 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
return IMAGE_FILETYPE_JP2; return IMAGE_FILETYPE_JP2;
} }
if (twelve_bytes_read && !memcmp(filetype + 4, php_sig_ftyp, 4) &&
(!memcmp(filetype + 8, php_sig_mif1, 4) || !memcmp(filetype + 8, php_sig_heic, 4) || !memcmp(filetype + 8, php_sig_heix, 4))) {
return IMAGE_FILETYPE_HEIF;
}
if (!php_stream_rewind(stream) && php_is_image_avif(stream)) { if (!php_stream_rewind(stream) && php_is_image_avif(stream)) {
return IMAGE_FILETYPE_AVIF; return IMAGE_FILETYPE_AVIF;
} }
@ -1515,6 +1530,11 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
case IMAGE_FILETYPE_AVIF: case IMAGE_FILETYPE_AVIF:
result = php_handle_avif(stream); result = php_handle_avif(stream);
break; break;
case IMAGE_FILETYPE_HEIF:
if (!php_stream_rewind(stream)) {
result = php_handle_avif(stream);
}
break;
default: default:
case IMAGE_FILETYPE_UNKNOWN: case IMAGE_FILETYPE_UNKNOWN:
break; break;

View file

@ -44,6 +44,7 @@ typedef enum
IMAGE_FILETYPE_ICO, IMAGE_FILETYPE_ICO,
IMAGE_FILETYPE_WEBP, IMAGE_FILETYPE_WEBP,
IMAGE_FILETYPE_AVIF, IMAGE_FILETYPE_AVIF,
IMAGE_FILETYPE_HEIF,
/* WHEN EXTENDING: PLEASE ALSO REGISTER IN basic_function.stub.php */ /* WHEN EXTENDING: PLEASE ALSO REGISTER IN basic_function.stub.php */
IMAGE_FILETYPE_COUNT IMAGE_FILETYPE_COUNT
} image_filetype; } image_filetype;

View file

@ -23,7 +23,7 @@ GetImageSize()
var_dump($result); var_dump($result);
?> ?>
--EXPECT-- --EXPECT--
array(17) { array(18) {
["test-1pix.bmp"]=> ["test-1pix.bmp"]=>
array(6) { array(6) {
[0]=> [0]=>
@ -216,6 +216,23 @@ array(17) {
["mime"]=> ["mime"]=>
string(9) "image/gif" string(9) "image/gif"
} }
["test4pix.heic"]=>
array(7) {
[0]=>
int(54)
[1]=>
int(84)
[2]=>
int(20)
[3]=>
string(22) "width="54" height="84""
["bits"]=>
int(8)
["channels"]=>
int(3)
["mime"]=>
string(10) "image/heif"
}
["test4pix.iff"]=> ["test4pix.iff"]=>
array(6) { array(6) {
[0]=> [0]=>

View file

@ -25,6 +25,7 @@ image_type_to_extension()
"IMAGETYPE_XBM" => IMAGETYPE_XBM, "IMAGETYPE_XBM" => IMAGETYPE_XBM,
"IMAGETYPE_WEBP" => IMAGETYPE_WEBP, "IMAGETYPE_WEBP" => IMAGETYPE_WEBP,
"IMAGETYPE_AVIF" => IMAGETYPE_AVIF, "IMAGETYPE_AVIF" => IMAGETYPE_AVIF,
"IMAGETYPE_HEIF" => IMAGETYPE_HEIF,
); );
foreach($constants as $name => $constant) { 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)); printf("Constant: %s\n\tWith dot: %s\n\tWithout dot: %s\n", $name, image_type_to_extension($constant), image_type_to_extension($constant, false));
@ -89,6 +90,9 @@ Constant: IMAGETYPE_WEBP
Constant: IMAGETYPE_AVIF Constant: IMAGETYPE_AVIF
With dot: .avif With dot: .avif
Without dot: avif Without dot: avif
Constant: IMAGETYPE_HEIF
With dot: .heif
Without dot: heif
bool(false) bool(false)
bool(false) bool(false)
Done Done

View file

@ -24,7 +24,7 @@ image_type_to_mime_type()
var_dump($result); var_dump($result);
?> ?>
--EXPECT-- --EXPECT--
array(17) { array(18) {
["test-1pix.bmp"]=> ["test-1pix.bmp"]=>
string(9) "image/bmp" string(9) "image/bmp"
["test12pix.webp"]=> ["test12pix.webp"]=>
@ -49,6 +49,8 @@ array(17) {
string(10) "image/webp" string(10) "image/webp"
["test4pix.gif"]=> ["test4pix.gif"]=>
string(9) "image/gif" string(9) "image/gif"
["test4pix.heic"]=>
string(10) "image/heif"
["test4pix.iff"]=> ["test4pix.iff"]=>
string(9) "image/iff" string(9) "image/iff"
["test4pix.png"]=> ["test4pix.png"]=>

View file

@ -22,7 +22,8 @@ $image_types = array (
IMAGETYPE_WBMP, IMAGETYPE_WBMP,
IMAGETYPE_JPEG2000, IMAGETYPE_JPEG2000,
IMAGETYPE_XBM, IMAGETYPE_XBM,
IMAGETYPE_WEBP IMAGETYPE_WEBP,
IMAGETYPE_HEIF,
); );
foreach($image_types as $image_type) { foreach($image_types as $image_type) {
@ -51,5 +52,6 @@ string(18) "image/vnd.wap.wbmp"
string(24) "application/octet-stream" string(24) "application/octet-stream"
string(9) "image/xbm" string(9) "image/xbm"
string(10) "image/webp" string(10) "image/webp"
string(10) "image/heif"
Done image_type_to_mime_type() test Done image_type_to_mime_type() test

View file

@ -75,4 +75,7 @@ string\(10\) "image\/webp"
string\(10\) "image\/avif" string\(10\) "image\/avif"
-- Iteration 20 -- -- Iteration 20 --
string\(10\) "image\/heif"
-- Iteration 21 --
string\(24\) "application\/octet-stream" string\(24\) "application\/octet-stream"

Binary file not shown.