Skip to content

Commit 776b2b1

Browse files
committed
ext/gd: bug #80828 partial HEIF support.
1 parent 5a03ff4 commit 776b2b1

13 files changed

+240
-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: 76 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,15 @@ 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+
case PHP_GDIMG_TYPE_HEIF:
1490+
abort();
1491+
im = _php_image_create_from_string(data, "HEIF", gdImageCreateFromHeifCtx);
1492+
break;
1493+
#else
1494+
php_error_docref(NULL, E_WARNING, "No HEIF support in this PHP build");
1495+
RETURN_FALSE;
1496+
#endif
14731497
default:
14741498
php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
14751499
RETURN_FALSE;
@@ -1674,6 +1698,12 @@ PHP_FUNCTION(imagecreatefromwbmp)
16741698
_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageCreateFromWBMP, gdImageCreateFromWBMPCtx);
16751699
}
16761700
/* }}} */
1701+
#ifdef HAVE_GD_HEIF
1702+
PHP_FUNCTION(imagecreatefromheif)
1703+
{
1704+
_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_HEIF, "HEIF", gdImageCreateFromHeif, gdImageCreateFromHeifCtx);
1705+
}
1706+
#endif
16771707

16781708
/* {{{ Create a new image from GD file or URL */
16791709
PHP_FUNCTION(imagecreatefromgd)
@@ -1900,6 +1930,12 @@ PHP_FUNCTION(imagejpeg)
19001930
}
19011931
/* }}} */
19021932
#endif /* HAVE_GD_JPG */
1933+
#ifdef HAVE_GD_HEIF
1934+
PHP_FUNCTION(imageheif)
1935+
{
1936+
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_HEIF, "HEIF");
1937+
}
1938+
#endif
19031939

19041940
/* {{{ Output WBMP image to browser or file */
19051941
PHP_FUNCTION(imagewbmp)
@@ -4071,10 +4107,13 @@ static gdIOCtx *create_output_context(void) {
40714107
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn)
40724108
{
40734109
zval *imgind;
4074-
zend_long quality = -1, basefilter = -1, speed = -1;
4110+
zend_long quality = -1, basefilter = -1, speed = -1, codec = -1;
40754111
gdImagePtr im;
40764112
gdIOCtx *ctx = NULL;
40774113
zval *to_zval = NULL;
4114+
char *chroma = NULL;
4115+
size_t chroma_len;
4116+
bool codec_is_null = true;
40784117

40794118
if (image_type == PHP_GDIMG_TYPE_GIF) {
40804119
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!", &imgind, gd_image_ce, &to_zval) == FAILURE) {
@@ -4088,6 +4127,10 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
40884127
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &speed) == FAILURE) {
40894128
RETURN_THROWS();
40904129
}
4130+
} else if (image_type == PHP_GDIMG_TYPE_HEIF) {
4131+
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) {
4132+
RETURN_THROWS();
4133+
}
40914134
} else {
40924135
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) {
40934136
RETURN_THROWS();
@@ -4143,6 +4186,37 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
41434186
gdImageAvifCtx(im, ctx, (int) quality, (int) speed);
41444187
break;
41454188
#endif
4189+
#ifdef HAVE_GD_HEIF
4190+
case PHP_GDIMG_TYPE_HEIF:
4191+
if (quality < -1) {
4192+
zend_argument_value_error(3, "must be greater than or equal to -1");
4193+
ctx->gd_free(ctx);
4194+
RETURN_THROWS();
4195+
}
4196+
if (codec_is_null) {
4197+
codec = GD_HEIF_CODEC_HEVC;
4198+
}
4199+
if (codec < GD_HEIF_CODEC_HEVC || codec > GD_HEIF_CODEC_AV1) {
4200+
zend_argument_value_error(4, "must be between HEIF_CODEC_HEVC or HEIF_CODEC_AV1");
4201+
ctx->gd_free(ctx);
4202+
RETURN_THROWS();
4203+
}
4204+
if (chroma == NULL) {
4205+
chroma = GD_HEIF_CHROMA_420;
4206+
chroma_len = strlen(chroma);
4207+
}
4208+
if (chroma_len != 3 ||
4209+
(strcmp(chroma, GD_HEIF_CHROMA_420) &&
4210+
strcmp(chroma, GD_HEIF_CHROMA_422) &&
4211+
strcmp(chroma, GD_HEIF_CHROMA_444))) {
4212+
zend_argument_value_error(5, "must be between HEIF_CHROMA_420, HEIF_CHROMA_422 or HEIF_CHROMA_444");
4213+
ctx->gd_free(ctx);
4214+
RETURN_THROWS();
4215+
}
4216+
4217+
gdImageHeifCtx(im, ctx, (int) quality, (gdHeifCodec)codec, chroma);
4218+
break;
4219+
#endif
41464220
#ifdef HAVE_GD_PNG
41474221
case PHP_GDIMG_TYPE_PNG:
41484222
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)