]> granicus.if.org Git - php/commitdiff
Implement #65038: IMAGETYPE_WEBP constant missing
authorChristoph M. Becker <cmbecker69@gmx.de>
Fri, 7 Oct 2016 17:25:59 +0000 (19:25 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Fri, 7 Oct 2016 22:02:21 +0000 (00:02 +0200)
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>

UPGRADING
ext/standard/image.c
ext/standard/php_image.h
ext/standard/tests/image/getimagesize.phpt
ext/standard/tests/image/image_type_to_extension.phpt
ext/standard/tests/image/image_type_to_mime_type.phpt
ext/standard/tests/image/image_type_to_mime_type_basic.phpt
ext/standard/tests/image/image_type_to_mime_type_variation3.phpt
ext/standard/tests/image/test3pix.webp [new file with mode: 0644]

index 68f3364b104e17f8795778f81e02a5954fb23218..d197f84d71f8738437ae3e08d721bb9f28c0955d 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -383,6 +383,9 @@ PHP 7.1 UPGRADE NOTES
   PGSQL_NOTICE_ALL
   PGSQL_NOTICE_CLEAR
 
+- Standard:
+  . IMAGETYPE_WEBP
+
 ========================================
 11. Changes to INI File Handling
 ========================================
index 480246ab9768c73efb6e1dad3c69c8bf0f3e3eac..10386c3da0b34be65eabf352e3622df51b859724 100644 (file)
@@ -55,6 +55,8 @@ PHPAPI const char php_sig_jp2[12] = {(char)0x00, (char)0x00, (char)0x00, (char)0
                                      (char)0x0d, (char)0x0a, (char)0x87, (char)0x0a};
 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'};
 
 /* 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 */
@@ -92,6 +94,7 @@ PHP_MINIT_FUNCTION(imagetypes)
        REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG2000",IMAGE_FILETYPE_JPC,     CONST_CS | CONST_PERSISTENT); /* keep alias */
        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_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT",   IMAGE_FILETYPE_COUNT,   CONST_CS | CONST_PERSISTENT);
        return SUCCESS;
@@ -1119,6 +1122,32 @@ static struct gfxinfo *php_handle_ico(php_stream * stream)
 }
 /* }}} */
 
+/* {{{ php_handle_webp
+ */
+static struct gfxinfo *php_handle_webp(php_stream * stream)
+{
+       struct gfxinfo *result = NULL;
+       const char sig[4] = {'V', 'P', '8', ' '};
+       unsigned char buf[18];
+
+       if (php_stream_read(stream, (char *) buf, 18) != 18)
+               return NULL;
+
+       if (memcmp(buf, sig, 4)) { /* simple lossy WebP only */
+               return NULL;
+       }
+
+       result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
+       
+       result->width = (buf[14]) + ((buf[15] & 0x3F) << 8);
+       result->height = (buf[16]) + ((buf[17] & 0x3F) << 8);
+       result->bits = 8; /* always 1 byte */
+       result->channels = 3; /* always YUV */
+
+       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)
@@ -1152,6 +1181,8 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
                        return "image/xbm";
                case IMAGE_FILETYPE_ICO:
                        return "image/vnd.microsoft.icon";
+               case IMAGE_FILETYPE_WEBP:
+                       return "image/webp";
                default:
                case IMAGE_FILETYPE_UNKNOWN:
                        return "application/octet-stream"; /* suppose binary format */
@@ -1216,6 +1247,8 @@ PHP_FUNCTION(image_type_to_extension)
                        RETURN_STRING(".xbm" + !inc_dot);
                case IMAGE_FILETYPE_ICO:
                        RETURN_STRING(".ico" + !inc_dot);
+               case IMAGE_FILETYPE_WEBP:
+                       RETURN_STRING(".webp" + !inc_dot);
        }
 
        RETURN_FALSE;
@@ -1261,6 +1294,16 @@ PHPAPI int php_getimagetype(php_stream * stream, char *filetype)
                return IMAGE_FILETYPE_BMP;
        } else if (!memcmp(filetype, php_sig_jpc, 3)) {
                return IMAGE_FILETYPE_JPC;
+       } else if (!memcmp(filetype, php_sig_riff, 3)) {
+               if (php_stream_read(stream, filetype+3, 9) != 9) {
+                       php_error_docref(NULL, E_NOTICE, "Read error!");
+                       return IMAGE_FILETYPE_UNKNOWN;
+               }
+               if (!memcmp(filetype+8, php_sig_webp, 4)) {
+                       return IMAGE_FILETYPE_WEBP;
+               } else {
+                       return IMAGE_FILETYPE_UNKNOWN;
+               }
        }
 
        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
                case IMAGE_FILETYPE_ICO:
                        result = php_handle_ico(stream);
                        break;
+               case IMAGE_FILETYPE_WEBP:
+                       result = php_handle_webp(stream);
+                       break;
                default:
                case IMAGE_FILETYPE_UNKNOWN:
                        break;
index 1b58b075ebd1cdfe8d5d970ca8c6b94df95c2f84..0810b4b2f51d06d25cb125bf8c7092743287df0c 100644 (file)
@@ -52,6 +52,7 @@ typedef enum
   /* IMAGE_FILETYPE_JPEG2000 is a userland alias for IMAGE_FILETYPE_JPC */
   IMAGE_FILETYPE_XBM,
   IMAGE_FILETYPE_ICO,
+  IMAGE_FILETYPE_WEBP,
 /* WHEN EXTENDING: PLEASE ALSO REGISTER IN image.c:PHP_MINIT_FUNCTION(imagetypes) */
   IMAGE_FILETYPE_COUNT
 } image_filetype;
index 04ddd8c82b20db3ad9cc8331a236236c30195a17..e088322104d2a6edbe733acafb67fc538f5f50c1 100644 (file)
@@ -23,7 +23,7 @@ GetImageSize()
        var_dump($result);
 ?>
 --EXPECT--
-array(13) {
+array(14) {
   ["test-1pix.bmp"]=>
   array(6) {
     [0]=>
@@ -137,6 +137,23 @@ array(13) {
     ["mime"]=>
     string(9) "image/gif"
   }
+  ["test3pix.webp"]=>
+  array(7) {
+    [0]=>
+    int(1)
+    [1]=>
+    int(3)
+    [2]=>
+    int(18)
+    [3]=>
+    string(20) "width="1" height="3""
+    ["bits"]=>
+    int(8)
+    ["channels"]=>
+    int(3)
+    ["mime"]=>
+    string(10) "image/webp"
+  }
   ["test4pix.gif"]=>
   array(7) {
     [0]=>
index c668e3408de70f02c6b1c1dbb2ae9f7c7b405b45..0c158905304d995710b8dde6611b27f1f45f841e 100644 (file)
@@ -23,7 +23,8 @@ image_type_to_extension()
         "IMAGETYPE_IFF"      => IMAGETYPE_IFF,
         "IMAGETYPE_WBMP"     => IMAGETYPE_WBMP,
         "IMAGETYPE_JPEG2000" => IMAGETYPE_JPEG2000,
-        "IMAGETYPE_XBM"      => IMAGETYPE_XBM
+        "IMAGETYPE_XBM"      => IMAGETYPE_XBM,
+               "IMAGETYPE_WEBP"     => IMAGETYPE_WEBP
     );
     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));
@@ -86,6 +87,9 @@ Constant: IMAGETYPE_JPEG2000
 Constant: IMAGETYPE_XBM
        With dot: .xbm
        Without dot: xbm
+Constant: IMAGETYPE_WEBP
+       With dot: .webp
+       Without dot: webp
 
 Warning: image_type_to_extension() expects parameter 2 to be boolean, array given in %s on line %d
 bool(false)
index 9f7ffa1aa34b42760422720159b4b4f2f75d85fa..492c8434af9d9ce0547c5d6b1ef2b174b143d405 100644 (file)
@@ -25,7 +25,7 @@ image_type_to_mime_type()
        var_dump($result);
 ?>
 --EXPECT--
-array(13) {
+array(14) {
   ["test-1pix.bmp"]=>
   string(14) "image/x-ms-bmp"
   ["test1bpix.bmp"]=>
@@ -40,6 +40,8 @@ array(13) {
   string(10) "image/jpeg"
   ["test2pix.gif"]=>
   string(9) "image/gif"
+  ["test3pix.webp"]=>
+  string(10) "image/webp"
   ["test4pix.gif"]=>
   string(9) "image/gif"
   ["test4pix.iff"]=>
index b81bdbde5f9f114cc141503fc9d726db55268c67..5506570494f32f7acef7e780df7b35e25d60d22e 100644 (file)
@@ -31,7 +31,8 @@ $image_types = array (
        IMAGETYPE_IFF,     
        IMAGETYPE_WBMP, 
        IMAGETYPE_JPEG2000, 
-       IMAGETYPE_XBM      
+       IMAGETYPE_XBM,
+       IMAGETYPE_WEBP
 );
 
        foreach($image_types as $image_type) {
@@ -59,5 +60,6 @@ string(9) "image/iff"
 string(18) "image/vnd.wap.wbmp"
 string(24) "application/octet-stream"
 string(9) "image/xbm"
+string(10) "image/webp"
 
 Done image_type_to_mime_type() test
index 192f23dcee9627498d0747e01b73b166cbc855ef..7b06c0a145b6523812be4e3896d46bc4622691b2 100644 (file)
@@ -75,5 +75,8 @@ string\(9\) "image\/xbm"
 string\(24\) "image\/vnd.microsoft.icon"
 
 -- Iteration 18 --
+string\(10\) "image\/webp"
+
+-- Iteration 19 --
 string\(24\) "application\/octet-stream"
 ===DONE===
diff --git a/ext/standard/tests/image/test3pix.webp b/ext/standard/tests/image/test3pix.webp
new file mode 100644 (file)
index 0000000..e5c6410
Binary files /dev/null and b/ext/standard/tests/image/test3pix.webp differ