diff --git a/core/modules/simpletest/files/img-test.webp b/core/modules/simpletest/files/img-test.webp
new file mode 100644
index 0000000000000000000000000000000000000000..5ce8b65757af4dd84971b214ef8445334295741a
GIT binary patch
literal 114
zcmV-&0FD1rNk&F$00012MM6+kP&iCo0000lC%^;{FCY*|+8=t2`4<or`9IqH2OwL@
z21acpIokM-1a=s#hQcg?#GlKBehq+#{;O@<hM{+-oFO7D!whED;QoTmr|Ie2S{Y+f
U&hcp?qLp)hnsh=xg-{d#0B1cfcK`qY

literal 0
HcmV?d00001

diff --git a/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php b/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php
index 7b195cc..56bc01d 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php
@@ -235,12 +235,21 @@ public function save($destination) {
       $success = $function($this->getResource(), $destination, $this->configFactory->get('system.image.gd')->get('jpeg_quality'));
     }
     else {
-      // Always save PNG images with full transparency.
-      if ($this->getType() == IMAGETYPE_PNG) {
+      // Image types that support alpha need to be saved accordingly.
+      $alpha_supporting_types = [IMAGETYPE_PNG];
+      if (static::isWebpSupported()) {
+        $alpha_supporting_types[] = IMAGETYPE_WEBP;
+      }
+      if (in_array($this->getType(), $alpha_supporting_types)) {
         imagealphablending($this->getResource(), FALSE);
         imagesavealpha($this->getResource(), TRUE);
       }
-      $success = $function($this->getResource(), $destination);
+      if ($function === 'imagewebp') {
+        $success = $function($this->getResource(), $destination, 100);
+      }
+      else {
+        $success = $function($this->getResource(), $destination);
+      }
     }
     // Move temporary local file to remote destination.
     if (isset($permanent_destination) && $success) {
@@ -440,7 +449,21 @@ public function extensionToImageType($extension) {
    *   IMAGETYPE_* constant (e.g. IMAGETYPE_JPEG, IMAGETYPE_PNG, etc.).
    */
   protected static function supportedTypes() {
-    return array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
+    $supported_types = [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF];
+    if (static::isWebpSupported()) {
+      $supported_types[] = IMAGETYPE_WEBP;
+    }
+    return $supported_types;
+  }
+
+  /**
+   * Checks if WEBP images can be supported.
+   *
+   * @return bool
+   *   TRUE if WEBP images can be processed by GD, FALSE otherwise.
+   */
+  public static function isWebpSupported() {
+    return PHP_VERSION_ID >= 70100 && function_exists('imagewebp') ? TRUE : FALSE;
   }
 
 }
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
index 0d1c5a6..7d63d2d 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
@@ -90,9 +90,13 @@ protected function execute(array $arguments) {
       return FALSE;
     }
 
+    // Handles IMAGETYPE_WEBP as it is missing before PHP 7.1.
+    $webp = $this->getToolkit()->isWebpSupported() ? IMAGETYPE_WEBP : -1;
+
     // Fill the resource with transparency as possible.
     switch ($type) {
       case IMAGETYPE_PNG:
+      case $webp:
         imagealphablending($res, FALSE);
         $transparency = imagecolorallocatealpha($res, 0, 0, 0, 127);
         imagefill($res, 0, 0, $transparency);
diff --git a/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php b/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
index fe36c3d..51a7ad4 100644
--- a/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
@@ -107,8 +107,14 @@ function testManipulations() {
     // Test that the image factory is set to use the GD toolkit.
     $this->assertEqual($this->imageFactory->getToolkitId(), 'gd', 'The image factory is set to use the \'gd\' image toolkit.');
 
+    // Get a blank Image object.
+    $image = $this->imageFactory->get();
+
     // Test the list of supported extensions.
     $expected_extensions = ['png', 'gif', 'jpeg', 'jpg', 'jpe'];
+    if ($image->getToolkit()->isWebpSupported()) {
+      $expected_extensions[] = 'webp';
+    }
     $supported_extensions = $this->imageFactory->getSupportedExtensions();
     $this->assertEqual($expected_extensions, array_intersect($expected_extensions, $supported_extensions));
 
@@ -121,7 +127,9 @@ function testManipulations() {
       'jpg' => IMAGETYPE_JPEG,
       'jpe' => IMAGETYPE_JPEG
     ];
-    $image = $this->imageFactory->get();
+    if ($image->getToolkit()->isWebpSupported()) {
+      $expected_image_types['webp'] = IMAGETYPE_WEBP;
+    }
     foreach ($expected_image_types as $extension => $expected_image_type) {
       $image_type = $image->getToolkit()->extensionToImageType($extension);
       $this->assertSame($expected_image_type, $image_type);
@@ -138,6 +146,9 @@ function testManipulations() {
       'image-test-no-transparency.gif',
       'image-test.jpg',
     );
+    if ($image->getToolkit()->isWebpSupported()) {
+      $files[] = 'img-test.webp';
+    }
 
     // Setup a list of tests to perform on each type.
     $operations = array(
@@ -212,6 +223,17 @@ function testManipulations() {
         'corners' => $default_corners,
       ),
     );
+    if ($image->getToolkit()->isWebpSupported()) {
+      $operations += [
+        'convert_webp' => [
+          'function' => 'convert',
+          'width' => 40,
+          'height' => 20,
+          'arguments' => array('extension' => 'webp'),
+          'corners' => $default_corners,
+        ],
+      ];
+    }
 
     // Systems using non-bundled GD2 don't have imagerotate. Test if available.
     if (function_exists('imagerotate')) {
@@ -364,8 +386,9 @@ function testManipulations() {
             // conversion. The convert operation cannot handle that correctly.
             if ($image->getToolkit()->getType() == $image_original_type || $corner != $this->transparent) {
               $correct_colors = $this->colorsAreEqual($color, $corner);
-              $this->assertTrue($correct_colors, SafeMarkup::format('Image %file object after %action action has the correct color placement at corner %corner.',
-                array('%file'   => $file, '%action' => $op, '%corner' => $key)));
+              $actual_color = implode(',', $color);
+              $expected_color = implode(',', $corner);
+              $this->assertTrue($correct_colors, "Color of image '{$file}' after '{$op}' operation at corner {$key} is ({$actual_color}), expected ({$expected_color}).");
             }
           }
         }
@@ -377,7 +400,11 @@ function testManipulations() {
     }
 
     // Test creation of image from scratch, and saving to storage.
-    foreach (array(IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_JPEG) as $type) {
+    $image_types = [IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_JPEG];
+    if ($image->getToolkit()->isWebpSupported()) {
+      $image_types[] = IMAGETYPE_WEBP;
+    }
+    foreach ($image_types as $type) {
       $image = $this->imageFactory->get();
       $image->createNew(50, 20, image_type_to_extension($type, FALSE), '#ffff00');
       $file = 'from_null' . image_type_to_extension($type);
