Skip to content

Commit 14d4ee9

Browse files
committed
Implement #65038: IMAGETYPE_WEBP constant missing
We add WebP support for getimagesize(), getimagesizefromstring)(), image_type_to_extension() and image_type_to_mime_type(). For now we care only about the simple lossy WebP format (VP8) and ignore the lossless (VP8L) and extended (VP8X) formats. We use image/webp as MIME type as it appears to be pretty common, even though it is not yet registered with IANA. Relevant specifications: * <https://developers.google.com/speed/webp/docs/riff_container> * <https://tools.ietf.org/html/rfc6386>
1 parent 61bf62a commit 14d4ee9

9 files changed

+82
-4
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ PHP 7.1 UPGRADE NOTES
383383
PGSQL_NOTICE_ALL
384384
PGSQL_NOTICE_CLEAR
385385

386+
- Standard:
387+
. IMAGETYPE_WEBP
388+
386389
========================================
387390
11. Changes to INI File Handling
388391
========================================

ext/standard/image.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ PHPAPI const char php_sig_jp2[12] = {(char)0x00, (char)0x00, (char)0x00, (char)0
5555
(char)0x0d, (char)0x0a, (char)0x87, (char)0x0a};
5656
PHPAPI const char php_sig_iff[4] = {'F','O','R','M'};
5757
PHPAPI const char php_sig_ico[4] = {(char)0x00, (char)0x00, (char)0x01, (char)0x00};
58+
PHPAPI const char php_sig_riff[4] = {'R', 'I', 'F', 'F'};
59+
PHPAPI const char php_sig_webp[4] = {'W', 'E', 'B', 'P'};
5860

5961
/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
6062
/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
@@ -92,6 +94,7 @@ PHP_MINIT_FUNCTION(imagetypes)
9294
REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG2000",IMAGE_FILETYPE_JPC, CONST_CS | CONST_PERSISTENT); /* keep alias */
9395
REGISTER_LONG_CONSTANT("IMAGETYPE_XBM", IMAGE_FILETYPE_XBM, CONST_CS | CONST_PERSISTENT);
9496
REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_CS | CONST_PERSISTENT);
97+
REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_CS | CONST_PERSISTENT);
9598
REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_CS | CONST_PERSISTENT);
9699
REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_CS | CONST_PERSISTENT);
97100
return SUCCESS;
@@ -1119,6 +1122,32 @@ static struct gfxinfo *php_handle_ico(php_stream * stream)
11191122
}
11201123
/* }}} */
11211124

1125+
/* {{{ php_handle_webp
1126+
*/
1127+
static struct gfxinfo *php_handle_webp(php_stream * stream)
1128+
{
1129+
struct gfxinfo *result = NULL;
1130+
const char sig[4] = {'V', 'P', '8', ' '};
1131+
unsigned char buf[18];
1132+
1133+
if (php_stream_read(stream, (char *) buf, 18) != 18)
1134+
return NULL;
1135+
1136+
if (memcmp(buf, sig, 4)) { /* simple lossy WebP only */
1137+
return NULL;
1138+
}
1139+
1140+
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
1141+
1142+
result->width = (buf[14]) + ((buf[15] & 0x3F) << 8);
1143+
result->height = (buf[16]) + ((buf[17] & 0x3F) << 8);
1144+
result->bits = 8; /* always 1 byte */
1145+
result->channels = 3; /* always YUV */
1146+
1147+
return result;
1148+
}
1149+
/* }}} */
1150+
11221151
/* {{{ php_image_type_to_mime_type
11231152
* Convert internal image_type to mime type */
11241153
PHPAPI char * php_image_type_to_mime_type(int image_type)
@@ -1152,6 +1181,8 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
11521181
return "image/xbm";
11531182
case IMAGE_FILETYPE_ICO:
11541183
return "image/vnd.microsoft.icon";
1184+
case IMAGE_FILETYPE_WEBP:
1185+
return "image/webp";
11551186
default:
11561187
case IMAGE_FILETYPE_UNKNOWN:
11571188
return "application/octet-stream"; /* suppose binary format */
@@ -1216,6 +1247,8 @@ PHP_FUNCTION(image_type_to_extension)
12161247
RETURN_STRING(".xbm" + !inc_dot);
12171248
case IMAGE_FILETYPE_ICO:
12181249
RETURN_STRING(".ico" + !inc_dot);
1250+
case IMAGE_FILETYPE_WEBP:
1251+
RETURN_STRING(".webp" + !inc_dot);
12191252
}
12201253

12211254
RETURN_FALSE;
@@ -1261,6 +1294,16 @@ PHPAPI int php_getimagetype(php_stream * stream, char *filetype)
12611294
return IMAGE_FILETYPE_BMP;
12621295
} else if (!memcmp(filetype, php_sig_jpc, 3)) {
12631296
return IMAGE_FILETYPE_JPC;
1297+
} else if (!memcmp(filetype, php_sig_riff, 3)) {
1298+
if (php_stream_read(stream, filetype+3, 9) != 9) {
1299+
php_error_docref(NULL, E_NOTICE, "Read error!");
1300+
return IMAGE_FILETYPE_UNKNOWN;
1301+
}
1302+
if (!memcmp(filetype+8, php_sig_webp, 4)) {
1303+
return IMAGE_FILETYPE_WEBP;
1304+
} else {
1305+
return IMAGE_FILETYPE_UNKNOWN;
1306+
}
12641307
}
12651308

12661309
if (php_stream_read(stream, filetype+3, 1) != 1) {
@@ -1365,6 +1408,9 @@ static void php_getimagesize_from_stream(php_stream *stream, zval *info, INTERNA
13651408
case IMAGE_FILETYPE_ICO:
13661409
result = php_handle_ico(stream);
13671410
break;
1411+
case IMAGE_FILETYPE_WEBP:
1412+
result = php_handle_webp(stream);
1413+
break;
13681414
default:
13691415
case IMAGE_FILETYPE_UNKNOWN:
13701416
break;

ext/standard/php_image.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ typedef enum
5252
/* IMAGE_FILETYPE_JPEG2000 is a userland alias for IMAGE_FILETYPE_JPC */
5353
IMAGE_FILETYPE_XBM,
5454
IMAGE_FILETYPE_ICO,
55+
IMAGE_FILETYPE_WEBP,
5556
/* WHEN EXTENDING: PLEASE ALSO REGISTER IN image.c:PHP_MINIT_FUNCTION(imagetypes) */
5657
IMAGE_FILETYPE_COUNT
5758
} image_filetype;

ext/standard/tests/image/getimagesize.phpt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ GetImageSize()
2323
var_dump($result);
2424
?>
2525
--EXPECT--
26-
array(13) {
26+
array(14) {
2727
["test-1pix.bmp"]=>
2828
array(6) {
2929
[0]=>
@@ -137,6 +137,23 @@ array(13) {
137137
["mime"]=>
138138
string(9) "image/gif"
139139
}
140+
["test3pix.webp"]=>
141+
array(7) {
142+
[0]=>
143+
int(1)
144+
[1]=>
145+
int(3)
146+
[2]=>
147+
int(18)
148+
[3]=>
149+
string(20) "width="1" height="3""
150+
["bits"]=>
151+
int(8)
152+
["channels"]=>
153+
int(3)
154+
["mime"]=>
155+
string(10) "image/webp"
156+
}
140157
["test4pix.gif"]=>
141158
array(7) {
142159
[0]=>

ext/standard/tests/image/image_type_to_extension.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ image_type_to_extension()
2323
"IMAGETYPE_IFF" => IMAGETYPE_IFF,
2424
"IMAGETYPE_WBMP" => IMAGETYPE_WBMP,
2525
"IMAGETYPE_JPEG2000" => IMAGETYPE_JPEG2000,
26-
"IMAGETYPE_XBM" => IMAGETYPE_XBM
26+
"IMAGETYPE_XBM" => IMAGETYPE_XBM,
27+
"IMAGETYPE_WEBP" => IMAGETYPE_WEBP
2728
);
2829
foreach($constants as $name => $constant) {
2930
printf("Constant: %s\n\tWith dot: %s\n\tWithout dot: %s\n", $name, image_type_to_extension($constant), image_type_to_extension($constant, false));
@@ -86,6 +87,9 @@ Constant: IMAGETYPE_JPEG2000
8687
Constant: IMAGETYPE_XBM
8788
With dot: .xbm
8889
Without dot: xbm
90+
Constant: IMAGETYPE_WEBP
91+
With dot: .webp
92+
Without dot: webp
8993

9094
Warning: image_type_to_extension() expects parameter 2 to be boolean, array given in %s on line %d
9195
bool(false)

ext/standard/tests/image/image_type_to_mime_type.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ image_type_to_mime_type()
2525
var_dump($result);
2626
?>
2727
--EXPECT--
28-
array(13) {
28+
array(14) {
2929
["test-1pix.bmp"]=>
3030
string(14) "image/x-ms-bmp"
3131
["test1bpix.bmp"]=>
@@ -40,6 +40,8 @@ array(13) {
4040
string(10) "image/jpeg"
4141
["test2pix.gif"]=>
4242
string(9) "image/gif"
43+
["test3pix.webp"]=>
44+
string(10) "image/webp"
4345
["test4pix.gif"]=>
4446
string(9) "image/gif"
4547
["test4pix.iff"]=>

ext/standard/tests/image/image_type_to_mime_type_basic.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ $image_types = array (
3131
IMAGETYPE_IFF,
3232
IMAGETYPE_WBMP,
3333
IMAGETYPE_JPEG2000,
34-
IMAGETYPE_XBM
34+
IMAGETYPE_XBM,
35+
IMAGETYPE_WEBP
3536
);
3637

3738
foreach($image_types as $image_type) {
@@ -59,5 +60,6 @@ string(9) "image/iff"
5960
string(18) "image/vnd.wap.wbmp"
6061
string(24) "application/octet-stream"
6162
string(9) "image/xbm"
63+
string(10) "image/webp"
6264

6365
Done image_type_to_mime_type() test

ext/standard/tests/image/image_type_to_mime_type_variation3.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,8 @@ string\(9\) "image\/xbm"
7575
string\(24\) "image\/vnd.microsoft.icon"
7676

7777
-- Iteration 18 --
78+
string\(10\) "image\/webp"
79+
80+
-- Iteration 19 --
7881
string\(24\) "application\/octet-stream"
7982
===DONE===
44 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)