diff --git a/core/core.services.yml b/core/core.services.yml
index 7f9ed9b..9b78f48 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -892,7 +892,7 @@ services:
     parent: default_plugin_manager
   image.toolkit.operation.manager:
     class: Drupal\Core\ImageToolkit\ImageToolkitOperationManager
-    arguments: ['@logger.channel.image']
+    arguments: ['@logger.channel.image', '@image.toolkit.manager']
     parent: default_plugin_manager
   image.factory:
     class: Drupal\Core\Image\ImageFactory
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
index dc4abaa..111085d 100644
--- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\ImageToolkit;
 
+use Drupal\Component\Plugin\DerivativeInspectionInterface;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
@@ -33,6 +34,13 @@ class ImageToolkitOperationManager extends DefaultPluginManager implements Image
   protected $logger;
 
   /**
+   * The image toolkit manager.
+   *
+   * @var \Drupal\Core\ImageToolkit\ImageToolkitManager
+   */
+  protected $toolkitManager;
+
+  /**
    * Constructs the ImageToolkitOperationManager object.
    *
    * @param \Traversable $namespaces
@@ -44,20 +52,23 @@ class ImageToolkitOperationManager extends DefaultPluginManager implements Image
    *   The module handler to invoke the alter hook with.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
+   * @param \Drupal\Core\ImageToolkit\ImageToolkitManager $toolkit_manager
+   *   The image toolkit manager.
    */
-  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger) {
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger, ImageToolkitManager $toolkit_manager) {
     parent::__construct('Plugin/ImageToolkit/Operation', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\ImageToolkitOperationInterface', 'Drupal\Core\ImageToolkit\Annotation\ImageToolkitOperation');
 
     $this->alterInfo('image_toolkit_operation');
     $this->setCacheBackend($cache_backend, 'image_toolkit_operation_plugins');
     $this->logger = $logger;
+    $this->toolkitManager = $toolkit_manager;
   }
 
   /**
    * Returns the plugin ID for a given toolkit and operation.
    *
-   * @param string $toolkit_id
-   *   The toolkit plugin ID.
+   * @param \Drupal\Core\ImageToolkit\ImageToolkitInterface $toolkit
+   *   The toolkit instance.
    * @param string $operation
    *   The operation (e.g. "crop").
    *
@@ -67,7 +78,8 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
    * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
    *   When no plugin is available.
    */
-  protected function getToolkitOperationPluginId($toolkit_id, $operation) {
+  protected function getToolkitOperationPluginId(ImageToolkitInterface $toolkit, $operation) {
+    $toolkit_id = $toolkit->getPluginId();
     $definitions = $this->getDefinitions();
 
     $definitions = array_filter($definitions,
@@ -77,6 +89,15 @@ function ($definition) use ($toolkit_id, $operation) {
     );
 
     if (!$definitions) {
+      // If this image toolkit plugin is a derivative and returns no operation,
+      // try once again with its base plugin.
+      $base_toolkit_id = $toolkit->getBaseId();
+      if (($toolkit_id != $base_toolkit_id) && !empty($base_toolkit_id)) {
+        $base_toolkit = $this->toolkitManager->createInstance($base_toolkit_id);
+
+        return $this->getToolkitOperationPluginId($base_toolkit, $operation);
+      }
+
       $message = String::format("No image operation plugin for '@toolkit' toolkit and '@operation' operation.", array('@toolkit' => $toolkit_id, '@operation' => $operation));
       throw new PluginNotFoundException($toolkit_id . '.' . $operation, $message);
     }
@@ -92,17 +113,17 @@ function ($definition) use ($toolkit_id, $operation) {
   /**
    * {@inheritdoc}
    */
-  public function createInstance($plugin_id, array $configuration = array(), ImageToolkitInterface $toolkit = NULL) {
+  public function createInstance($plugin_id, array $configuration = array(), ImageToolkitInterface $toolkit = NULL, ImageToolkitManager $toolkit_manager = NULL) {
     $plugin_definition = $this->getDefinition($plugin_id);
     $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
-    return new $plugin_class($configuration, $plugin_id, $plugin_definition, $toolkit, $this->logger);
+    return new $plugin_class($configuration, $plugin_id, $plugin_definition, $toolkit, $this->logger, $this->toolkitManager);
   }
 
   /**
    * {@inheritdoc}
    */
   public function getToolkitOperation(ImageToolkitInterface $toolkit, $operation) {
-    $plugin_id = $this->getToolkitOperationPluginId($toolkit->getPluginId(), $operation);
+    $plugin_id = $this->getToolkitOperationPluginId($toolkit, $operation);
     return $this->createInstance($plugin_id, array(), $toolkit);
   }
 
diff --git a/core/modules/system/src/Tests/Image/ToolkitTest.php b/core/modules/system/src/Tests/Image/ToolkitTest.php
index 35686bf..caaed9f 100644
--- a/core/modules/system/src/Tests/Image/ToolkitTest.php
+++ b/core/modules/system/src/Tests/Image/ToolkitTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\system\Tests\Image\ToolkitTest.
+ * Contains \Drupal\system\Tests\Image\ToolkitTest.
  */
 
 namespace Drupal\system\Tests\Image;
@@ -21,6 +21,7 @@ function testGetAvailableToolkits() {
     $manager = $this->container->get('image.toolkit.manager');
     $toolkits = $manager->getAvailableToolkits();
     $this->assertTrue(isset($toolkits['test']), 'The working toolkit was returned.');
+    $this->assertTrue(isset($toolkits['test:derived_toolkit']), 'The derived toolkit was returned.');
     $this->assertFalse(isset($toolkits['broken']), 'The toolkit marked unavailable was not returned');
     $this->assertToolkitOperationsCalled(array());
   }
@@ -71,4 +72,27 @@ function testApplyNoParameters() {
     $this->assertEqual($calls['apply'][0][0], 'my_operation', "'my_operation' was passed correctly as operation");
     $this->assertEqual($calls['apply'][0][1], array(), 'passing no parameters was handled correctly');
   }
+
+  /**
+   * Tests image toolkit operations inheritance by derivative toolkits.
+   */
+  public function testDerivative() {
+    /** @var \Drupal\Core\ImageToolkit\ImageToolkitManager $manager */
+    $manager = $this->container->get('image.toolkit.manager');
+
+    /** @var \Drupal\Core\ImageToolkit\ImageToolkitInterface $toolkit */
+    $toolkit = $manager->createInstance('test:derived_toolkit');
+
+    /** @var \Drupal\Core\ImageToolkit\ImageToolkitOperationManager $operation */
+    $operation = $this->container->get('image.toolkit.operation.manager');
+
+    /** @var \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface $blur */
+    $blur = $operation->getToolkitOperation($toolkit, 'blur');
+    /** @var \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface $invert */
+    $invert = $operation->getToolkitOperation($toolkit, 'invert');
+
+    $this->assertEqual('foo_derived', $blur->getPluginId(), "'Blur' operation overwritten by derivative.");
+    $this->assertEqual('bar', $invert->getPluginId(), '"Invert" operation inherited from base plugin.');
+  }
+
 }
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/DerivedToolkit.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/DerivedToolkit.php
new file mode 100644
index 0000000..2df5c2b
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/DerivedToolkit.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_test\Plugin\ImageToolkit\DerivedToolkit.
+ */
+
+namespace Drupal\image_test\Plugin\ImageToolkit;
+
+/**
+ * Provides a derivative of TestToolkit.
+ *
+ * @ImageToolkit(
+ *   id = "test:derived_toolkit",
+ *   title = @Translation("A dummy toolkit, derivative of 'test'.")
+ * )
+ */
+class DerivedToolkit extends TestToolkit { }
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Bar.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Bar.php
new file mode 100644
index 0000000..780dbe5
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Bar.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_test\Plugin\ImageToolkit\Operation\Bar
+ */
+
+namespace Drupal\image_test\Plugin\ImageToolkit\Operation;
+
+/**
+ * Builds an image toolkit operation.
+ *
+ * @ImageToolkitOperation(
+ *   id = "bar",
+ *   toolkit = "test",
+ *   operation = "invert",
+ *   label = @Translation("Invert"),
+ *   description = @Translation("Bar.")
+ * )
+ */
+class Bar extends OperationBase { }
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Foo.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Foo.php
new file mode 100644
index 0000000..67938f1
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/Foo.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_test\Plugin\ImageToolkit\Operation\Foo
+ */
+
+namespace Drupal\image_test\Plugin\ImageToolkit\Operation;
+
+/**
+ * Builds an image toolkit operation.
+ *
+ * @ImageToolkitOperation(
+ *   id = "foo",
+ *   toolkit = "test",
+ *   operation = "blur",
+ *   label = @Translation("Blur"),
+ *   description = @Translation("Foo.")
+ * )
+ */
+class Foo extends OperationBase { }
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/FooDerived.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/FooDerived.php
new file mode 100644
index 0000000..fed0d53
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/FooDerived.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_test\Plugin\ImageToolkit\Operation\FooDerived
+ */
+
+namespace Drupal\image_test\Plugin\ImageToolkit\Operation;
+
+/**
+ * Builds an image toolkit operation.
+ *
+ * @ImageToolkitOperation(
+ *   id = "foo_derived",
+ *   toolkit = "test:derived_toolkit",
+ *   operation = "blur",
+ *   label = @Translation("Blur Derived"),
+ *   description = @Translation("Foo derived.")
+ * )
+ */
+class FooDerived extends OperationBase { }
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/OperationBase.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/OperationBase.php
new file mode 100644
index 0000000..1d9d012
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/OperationBase.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_test\Plugin\ImageToolkit\Operation\OperationBase.
+ */
+
+namespace Drupal\image_test\Plugin\ImageToolkit\Operation;
+
+use Drupal\Core\ImageToolkit\ImageToolkitOperationBase;
+
+/**
+ * Provides a base class for test operations.
+ */
+abstract class OperationBase extends ImageToolkitOperationBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function arguments() {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute(array $arguments) {
+    // Nothing to do.
+  }
+
+}
