Skip to content

Commit 3f8df41

Browse files
committed
ext/gd: bug #80828 HEIF support.
1 parent 5a03ff4 commit 3f8df41

13 files changed

+232
-5
lines changed

Zend/Optimizer/zend_func_infos.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ static const func_info_t func_infos[] = {
121121
#endif
122122
#if defined(HAVE_GD_WEBP)
123123
F1("imagecreatefromwebp", MAY_BE_OBJECT|MAY_BE_FALSE),
124+
#endif
125+
#if defined(HAVE_GD_HEIF)
126+
F1("imagecreatefromheif", MAY_BE_OBJECT|MAY_BE_FALSE),
124127
#endif
125128
F1("imagecreatefromxbm", MAY_BE_OBJECT|MAY_BE_FALSE),
126129
#if defined(HAVE_GD_XPM)

ext/gd/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ AC_DEFUN([PHP_GD_CHECK_VERSION],[
195195
PHP_GD_CHECK_FORMAT([Xpm], [HAVE_GD_XPM])
196196
PHP_GD_CHECK_FORMAT([Bmp], [HAVE_GD_BMP])
197197
PHP_GD_CHECK_FORMAT([Tga], [HAVE_GD_TGA])
198+
PHP_GD_CHECK_FORMAT([Heif], [HAVE_GD_HEIF])
198199
PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_FREETYPE, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
199200
PHP_CHECK_LIBRARY(gd, gdVersionString, [AC_DEFINE(HAVE_GD_LIBVERSION, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
200201
PHP_CHECK_LIBRARY(gd, gdImageGetInterpolationMethod, [AC_DEFINE(HAVE_GD_GET_INTERPOLATION, 1, [ ])], [], [ $GD_SHARED_LIBADD ])

ext/gd/gd.c

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ PHP_MINFO_FUNCTION(gd)
458458
#endif
459459
#ifdef HAVE_GD_TGA
460460
php_info_print_table_row(2, "TGA Read Support", "enabled");
461+
#endif
462+
#ifdef HAVE_GD_HEIF
463+
php_info_print_table_row(2, "HEIF Support", "enabled");
461464
#endif
462465
php_info_print_table_end();
463466
DISPLAY_INI_ENTRIES();
@@ -520,6 +523,11 @@ PHP_FUNCTION(gd_info)
520523
#else
521524
add_assoc_bool(return_value, "TGA Read Support", 0);
522525
#endif
526+
#ifdef HAVE_GD_HEIF
527+
add_assoc_bool(return_value, "HEIF Support", 1);
528+
#else
529+
add_assoc_bool(return_value, "HEIF Support", 0);
530+
#endif
523531
#ifdef USE_GD_JISX0208
524532
add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1);
525533
#else
@@ -1300,6 +1308,9 @@ PHP_FUNCTION(imagetypes)
13001308
#ifdef HAVE_GD_AVIF
13011309
ret |= PHP_IMG_AVIF;
13021310
#endif
1311+
#ifdef HAVE_GD_HEIF
1312+
ret |= PHP_IMG_HEIF;
1313+
#endif
13031314

13041315
if (zend_parse_parameters_none() == FAILURE) {
13051316
RETURN_THROWS();
@@ -1351,6 +1362,11 @@ static int _php_image_type(zend_string *data)
13511362
return PHP_GDIMG_TYPE_BMP;
13521363
} else if(!memcmp(ZSTR_VAL(data), php_sig_riff, sizeof(php_sig_riff)) && !memcmp(ZSTR_VAL(data) + sizeof(php_sig_riff) + sizeof(uint32_t), php_sig_webp, sizeof(php_sig_webp))) {
13531364
return PHP_GDIMG_TYPE_WEBP;
1365+
} else if (!memcmp(ZSTR_VAL(data), php_sig_heifheic, sizeof(php_sig_heifheic)) ||
1366+
!memcmp(ZSTR_VAL(data), php_sig_heifheix, sizeof(php_sig_heifheix)) ||
1367+
!memcmp(ZSTR_VAL(data), php_sig_heifmif1, sizeof(php_sig_heifmif1)) ||
1368+
!memcmp(ZSTR_VAL(data), php_sig_heifmsf1, sizeof(php_sig_heifmsf1))) {
1369+
return PHP_GDIMG_TYPE_HEIF;
13541370
}
13551371

13561372
php_stream *image_stream = php_stream_memory_open(TEMP_STREAM_READONLY, data);
@@ -1469,7 +1485,13 @@ PHP_FUNCTION(imagecreatefromstring)
14691485
php_error_docref(NULL, E_WARNING, "No AVIF support in this PHP build");
14701486
RETURN_FALSE;
14711487
#endif
1472-
1488+
#ifdef HAVE_GD_HEIF
1489+
im = _php_image_create_from_string(data, "HEIF", gdImageCreateFromHeifCtx);
1490+
break;
1491+
#else
1492+
php_error_docref(NULL, E_WARNING, "No HEIF support in this PHP build");
1493+
RETURN_FALSE;
1494+
#endif
14731495
default:
14741496
php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
14751497
RETURN_FALSE;
@@ -1674,6 +1696,12 @@ PHP_FUNCTION(imagecreatefromwbmp)
16741696
_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageCreateFromWBMP, gdImageCreateFromWBMPCtx);
16751697
}
16761698
/* }}} */
1699+
#ifdef HAVE_GD_HEIF
1700+
PHP_FUNCTION(imagecreatefromheif)
1701+
{
1702+
_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_HEIF, "HEIF", gdImageCreateFromHeif, gdImageCreateFromHeifCtx);
1703+
}
1704+
#endif
16771705

16781706
/* {{{ Create a new image from GD file or URL */
16791707
PHP_FUNCTION(imagecreatefromgd)
@@ -1900,6 +1928,12 @@ PHP_FUNCTION(imagejpeg)
19001928
}
19011929
/* }}} */
19021930
#endif /* HAVE_GD_JPG */
1931+
#ifdef HAVE_GD_HEIF
1932+
PHP_FUNCTION(imageheif)
1933+
{
1934+
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_HEIF, "HEIF");
1935+
}
1936+
#endif
19031937

19041938
/* {{{ Output WBMP image to browser or file */
19051939
PHP_FUNCTION(imagewbmp)
@@ -4071,10 +4105,13 @@ static gdIOCtx *create_output_context(void) {
40714105
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn)
40724106
{
40734107
zval *imgind;
4074-
zend_long quality = -1, basefilter = -1, speed = -1;
4108+
zend_long quality = -1, basefilter = -1, speed = -1, codec = -1;
40754109
gdImagePtr im;
40764110
gdIOCtx *ctx = NULL;
40774111
zval *to_zval = NULL;
4112+
char *chroma = NULL;
4113+
size_t chroma_len;
4114+
bool codec_is_null = true;
40784115

40794116
if (image_type == PHP_GDIMG_TYPE_GIF) {
40804117
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!", &imgind, gd_image_ce, &to_zval) == FAILURE) {
@@ -4088,6 +4125,10 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
40884125
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &speed) == FAILURE) {
40894126
RETURN_THROWS();
40904127
}
4128+
} else if (image_type == PHP_GDIMG_TYPE_HEIF) {
4129+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!l!ls", &imgind, gd_image_ce, &to_zval, &quality, &codec, &codec_is_null, &chroma, &chroma_len) == FAILURE) {
4130+
RETURN_THROWS();
4131+
}
40914132
} else {
40924133
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) {
40934134
RETURN_THROWS();
@@ -4143,6 +4184,37 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
41434184
gdImageAvifCtx(im, ctx, (int) quality, (int) speed);
41444185
break;
41454186
#endif
4187+
#ifdef HAVE_GD_HEIF
4188+
case PHP_GDIMG_TYPE_HEIF:
4189+
if (quality < -1) {
4190+
zend_argument_value_error(3, "must be greater than or equal to -1");
4191+
ctx->gd_free(ctx);
4192+
RETURN_THROWS();
4193+
}
4194+
if (codec_is_null) {
4195+
codec = GD_HEIF_CODEC_HEVC;
4196+
}
4197+
if (codec < GD_HEIF_CODEC_HEVC || codec > GD_HEIF_CODEC_AV1) {
4198+
zend_argument_value_error(4, "must be between HEIF_CODEC_HEVC or HEIF_CODEC_AV1");
4199+
ctx->gd_free(ctx);
4200+
RETURN_THROWS();
4201+
}
4202+
if (chroma == NULL) {
4203+
chroma = GD_HEIF_CHROMA_420;
4204+
chroma_len = strlen(chroma);
4205+
}
4206+
if (chroma_len != 3 ||
4207+
(strcmp(chroma, GD_HEIF_CHROMA_420) &&
4208+
strcmp(chroma, GD_HEIF_CHROMA_422) &&
4209+
strcmp(chroma, GD_HEIF_CHROMA_444))) {
4210+
zend_argument_value_error(5, "must be between HEIF_CHROMA_420, HEIF_CHROMA_422 or HEIF_CHROMA_444");
4211+
ctx->gd_free(ctx);
4212+
RETURN_THROWS();
4213+
}
4214+
4215+
gdImageHeifCtx(im, ctx, (int) quality, (gdHeifCodec)codec, chroma);
4216+
break;
4217+
#endif
41464218
#ifdef HAVE_GD_PNG
41474219
case PHP_GDIMG_TYPE_PNG:
41484220
if (quality < -1 || quality > 9) {

ext/gd/gd.stub.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@
5353
*/
5454
const IMG_TGA = UNKNOWN;
5555

56+
/**
57+
* @var int
58+
* @cvalue PHP_IMG_HEIF
59+
*/
60+
const IMG_HEIF = UNKNOWN;
5661
/* constant for webp encoding */
5762

5863
#ifdef gdWebpLossless
@@ -412,6 +417,39 @@
412417
*/
413418
const IMG_FILTER_SCATTER = UNKNOWN;
414419

420+
#ifdef HAVE_GD_HEIF
421+
/**
422+
* @var string
423+
* @cvalue GD_HEIF_CHROMA_420
424+
*/
425+
const HEIF_CHROMA_420 = UNKNOWN;
426+
/**
427+
* @var string
428+
* @cvalue GD_HEIF_CHROMA_422
429+
*/
430+
const HEIF_CHROMA_422 = UNKNOWN;
431+
/**
432+
* @var string
433+
* @cvalue GD_HEIF_CHROMA_444
434+
*/
435+
const HEIF_CHROMA_444 = UNKNOWN;
436+
/**
437+
* @var int
438+
* @cvalue GD_HEIF_CODEC_UNKNOWN
439+
*/
440+
const HEIF_CODEC_UNKNOWN = UNKNOWN;
441+
/**
442+
* @var int
443+
* @cvalue GD_HEIF_CODEC_HEVC
444+
*/
445+
const HEIF_CODEC_HEVC = UNKNOWN;
446+
/**
447+
* @var int
448+
* @cvalue GD_HEIF_CODEC_AV1
449+
*/
450+
const HEIF_CODEC_AV1 = UNKNOWN;
451+
#endif
452+
415453
#ifdef GD_VERSION_STRING
416454
/**
417455
* @var string
@@ -569,6 +607,11 @@ function imagecreatefrompng(string $filename): GdImage|false {}
569607
function imagecreatefromwebp(string $filename): GdImage|false {}
570608
#endif
571609

610+
#ifdef HAVE_GD_HEIF
611+
/** @refcount 1 */
612+
function imagecreatefromheif(string $filename): GdImage|false {}
613+
#endif
614+
572615
/** @refcount 1 */
573616
function imagecreatefromxbm(string $filename): GdImage|false {}
574617

@@ -626,6 +669,11 @@ function imagejpeg(GdImage $image, $file = null, int $quality = -1): bool {}
626669
/** @param resource|string|null $file */
627670
function imagewbmp(GdImage $image, $file = null, ?int $foreground_color = null): bool {}
628671

672+
#ifdef HAVE_GD_HEIF
673+
/** @param resource|string|null $file */
674+
function imageheif(GdImage $image, $file = null, int $quality = -1, ?int $codec = null, ?string $chroma = null): bool {}
675+
#endif
676+
629677
function imagegd(GdImage $image, ?string $file = null): bool {}
630678

631679
function imagegd2(GdImage $image, ?string $file = null, int $chunk_size = 128, int $mode = IMG_GD2_RAW): bool {}

ext/gd/gd_arginfo.h

Lines changed: 48 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/gd/php_gd.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define PHP_GDIMG_TYPE_BMP 12
4444
#define PHP_GDIMG_TYPE_TGA 13
4545
#define PHP_GDIMG_TYPE_AVIF 14
46+
#define PHP_GDIMG_TYPE_HEIF 15
4647

4748
#define PHP_IMG_GIF 1
4849
#define PHP_IMG_JPG 2
@@ -54,6 +55,7 @@
5455
#define PHP_IMG_BMP 64
5556
#define PHP_IMG_TGA 128
5657
#define PHP_IMG_AVIF 256
58+
#define PHP_IMG_HEIF 384
5759

5860
/* Section Filters Declarations */
5961
/* IMPORTANT NOTE FOR NEW FILTER
@@ -103,6 +105,10 @@ PHPAPI extern const char php_sig_bmp[2];
103105
PHPAPI extern const char php_sig_riff[4];
104106
PHPAPI extern const char php_sig_webp[4];
105107
PHPAPI extern const char php_sig_avif[4];
108+
PHPAPI extern const char php_sig_heifheic[12];
109+
PHPAPI extern const char php_sig_heifheix[12];
110+
PHPAPI extern const char php_sig_heifmif1[12];
111+
PHPAPI extern const char php_sig_heifmsf1[12];
106112

107113
extern zend_module_entry gd_module_entry;
108114
#define phpext_gd_ptr &gd_module_entry

0 commit comments

Comments
 (0)