diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
index e567ea4..d43c803 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
@@ -3,6 +3,7 @@
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
 use Drupal\Component\Utility\Color;
+use Drupal\Component\Utility\Rectangle;
 
 /**
  * Defines GD2 rotate operation.
@@ -96,6 +97,13 @@ protected function execute(array $arguments) {
     // Stores the original GD resource.
     $original_res = $this->getToolkit()->getResource();
 
+    // Get expected width and height resulting from the rotation.
+    $rect = new Rectangle($this->getToolkit()->getWidth(), $this->getToolkit()->getHeight());
+    $rect = $rect->rotate($arguments['degrees']);
+    $expected_width = $rect->getBoundingWidth();
+    $expected_height = $rect->getBoundingHeight();
+
+    // Rotate the image.
     if ($new_res = imagerotate($this->getToolkit()->getResource(), 360 - $arguments['degrees'], $arguments['background_idx'])) {
       $this->getToolkit()->setResource($new_res);
       imagedestroy($original_res);
@@ -108,6 +116,67 @@ protected function execute(array $arguments) {
         imagecolortransparent($this->getToolkit()->getResource(), $transparent_idx);
       }
 
+      // Resizes the image if width and height are not as expected.
+      // PHP 7.0.25+ and 7.1.11+ GD rotates differently then it did in PHP 5.5
+      // and above, resulting in different dimensions. Here we are harmonizing
+      // final size across PHP versions by resizing the image to the dimensions
+      // we expect.
+      // @see https://bugs.php.net/bug.php?id=65148
+      if ($this->getToolkit()->getWidth() != $expected_width || $this->getToolkit()->getHeight() != $expected_height) {
+        // If either dimension of the current image is bigger than expected,
+        // crop the image.
+        if ($this->getToolkit()->getWidth() > $expected_width || $this->getToolkit()->getHeight() > $expected_height) {
+          $crop_width = min($expected_width, $this->getToolkit()->getWidth());
+          $crop_height = min($expected_height, $this->getToolkit()->getHeight());
+          if (!$this->getToolkit()->apply('crop', [
+            'x' => $this->getToolkit()->getWidth() / 2 - $crop_width / 2,
+            'y' => $this->getToolkit()->getHeight() / 2 - $crop_height /2,
+            'width' => $crop_width,
+            'height' => $crop_height,
+          ])) {
+            return FALSE;
+          }
+        }
+        // If the image at this point is smaller than expected, place it above
+        // a canvas of the expected dimensions.
+        if ($this->getToolkit()->getWidth() < $expected_width || $this->getToolkit()->getHeight() < $expected_height) {
+          // Store the current GD resource.
+          $temp_res = $this->getToolkit()->getResource();
+
+          // Prepare the canvas.
+          $data = [
+            'width' => $expected_width,
+            'height' => $expected_height,
+            'extension' => image_type_to_extension($this->getToolkit()->getType(), FALSE),
+            'transparent_color' => $this->getToolkit()->getTransparentColor(),
+            'is_temp' => TRUE,
+          ];
+          if (!$this->getToolkit()->apply('create_new', $data)) {
+            return FALSE;
+          }
+
+          // Fill the canvas with the required background color.
+          imagefill($this->getToolkit()->getResource(), 0, 0, $arguments['background_idx']);
+
+          // Overlay the current image on the canvas.
+          imagealphablending($temp_res, TRUE);
+          imagesavealpha($temp_res, TRUE);
+          imagealphablending($this->getToolkit()->getResource(), TRUE);
+          imagesavealpha($this->getToolkit()->getResource(), TRUE);
+          $x_pos = (int) ($expected_width / 2 - imagesx($temp_res) / 2);
+          $y_pos = (int) ($expected_height / 2 - imagesy($temp_res) / 2);
+          if (imagecopy($this->getToolkit()->getResource(), $temp_res, $x_pos, $y_pos, 0, 0, imagesx($temp_res), imagesy($temp_res))) {
+            imagedestroy($temp_res);
+          }
+          else {
+            // In case of failure, destroy the temporary resource and restore
+            // the original one.
+            imagedestroy($this->getToolkit()->getResource());
+            $this->getToolkit()->setResource($temp_res);
+            return FALSE;
+          }
+        }
+      }
       return TRUE;
     }
 
