diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 777e438..8c5ce25 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -32,11 +32,11 @@ function template_preprocess_image_style_preview(&$variables) {
 
   // Set up original file information.
   $original_path = \Drupal::config('image.settings')->get('preview_image');
-  $original_image = $image_factory->get($original_path);
+  $image = $image_factory->get($original_path);
   $variables['original'] = array(
     'url' => file_url_transform_relative(file_create_url($original_path)),
-    'width' => $original_image->getWidth(),
-    'height' => $original_image->getHeight(),
+    'width' => $image->getWidth(),
+    'height' => $image->getHeight(),
   );
   if ($variables['original']['width'] > $variables['original']['height']) {
     $variables['preview']['original']['width'] = min($variables['original']['width'], $sample_width);
@@ -51,13 +51,15 @@ function template_preprocess_image_style_preview(&$variables) {
   $preview_file = $style->buildUri($original_path);
   // Create derivative if necessary.
   if (!file_exists($preview_file)) {
-    $style->createDerivative($original_path, $preview_file);
+    $style->applyAndSave($image, $preview_file);
+  }
+  else {
+    $image = $image_factory->get($preview_file);
   }
-  $preview_image = $image_factory->get($preview_file);
   $variables['derivative'] = array(
     'url' => file_url_transform_relative(file_create_url($preview_file)),
-    'width' => $preview_image->getWidth(),
-    'height' => $preview_image->getHeight(),
+    'width' => $image->getWidth(),
+    'height' => $image->getHeight(),
   );
   if ($variables['derivative']['width'] > $variables['derivative']['height']) {
     $variables['preview']['derivative']['width'] = min($variables['derivative']['width'], $sample_width);
diff --git a/core/modules/image/src/Controller/ImageStyleDownloadController.php b/core/modules/image/src/Controller/ImageStyleDownloadController.php
index 4deea44..c6b2d90 100644
--- a/core/modules/image/src/Controller/ImageStyleDownloadController.php
+++ b/core/modules/image/src/Controller/ImageStyleDownloadController.php
@@ -160,16 +160,23 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
       }
     }
 
-    // Try to generate the image, unless another thread just did it while we
-    // were acquiring the lock.
-    $success = file_exists($derivative_uri) || $image_style->createDerivative($image_uri, $derivative_uri);
+    if (file_exists($derivative_uri)) {
+      // Another thread just generated the derivative image while we were
+      // acquiring the lock.
+      $image = $this->imageFactory->get($derivative_uri);
+      $success = $image->isValid();
+    }
+    else {
+      // Generate the derivative image.
+      $image = $this->imageFactory->get($image_uri);
+      $success = $image_style->applyAndSave($image, $derivative_uri);
+    }
 
     if (!empty($lock_acquired)) {
       $this->lock->release($lock_name);
     }
 
     if ($success) {
-      $image = $this->imageFactory->get($derivative_uri);
       $uri = $image->getSource();
       $headers += array(
         'Content-Type' => $image->getMimeType(),
diff --git a/core/modules/image/src/Entity/ImageStyle.php b/core/modules/image/src/Entity/ImageStyle.php
index 85f4ceb..5d111ab 100644
--- a/core/modules/image/src/Entity/ImageStyle.php
+++ b/core/modules/image/src/Entity/ImageStyle.php
@@ -11,6 +11,8 @@
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\Image\ImageInterface;
 use Drupal\Core\Routing\RequestHelper;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\Url;
@@ -60,6 +62,20 @@
 class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, EntityWithPluginCollectionInterface {
 
   /**
+   * The file system service.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  protected $fileSystem;
+
+  /**
+   * The image factory.
+   *
+   * @var \Drupal\Core\Image\ImageFactory
+   */
+  protected $imageFactory;
+
+  /**
    * The name of the image style.
    *
    * @var string
@@ -266,15 +282,27 @@ public function flush($path = NULL) {
    * {@inheritdoc}
    */
   public function createDerivative($original_uri, $derivative_uri) {
+    return $this->applyAndSave($this->getImageFactory()->get($original_uri), $derivative_uri);
+  }
 
-    // If the source file doesn't exist, return FALSE without creating folders.
-    $image = \Drupal::service('image.factory')->get($original_uri);
+  /**
+   * {@inheritdoc}
+   */
+  public function applyAndSave(ImageInterface $image, $derivative_uri) {
+    // If the image doesn't exist or is invalid, return FALSE without creating
+    // folders.
     if (!$image->isValid()) {
       return FALSE;
     }
 
-    // Get the folder for the final location of this style.
-    $directory = drupal_dirname($derivative_uri);
+    // Apply the style to the image object. Return FALSE without creating
+    // folders in case of failure.
+    if (!$this->apply($image)) {
+      return FALSE;
+    }
+
+    // Get the folder for the final location of this derivative image.
+    $directory = $this->getFileSystem()->dirname($derivative_uri);
 
     // Build the destination folder tree if it doesn't already exist.
     if (!file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
@@ -282,10 +310,7 @@ public function createDerivative($original_uri, $derivative_uri) {
       return FALSE;
     }
 
-    foreach ($this->getEffects() as $effect) {
-      $effect->applyEffect($image);
-    }
-
+    // Save image file at destination.
     if (!$image->save($derivative_uri)) {
       if (file_exists($derivative_uri)) {
         \Drupal::logger('image')->error('Cached image file %destination already exists. There may be an issue with your rewrite configuration.', array('%destination' => $derivative_uri));
@@ -299,6 +324,23 @@ public function createDerivative($original_uri, $derivative_uri) {
   /**
    * {@inheritdoc}
    */
+  public function apply(ImageInterface $image) {
+    // If the image doesn't exist or is invalid, return FALSE immediately.
+    if (!$image->isValid()) {
+      return FALSE;
+    }
+
+    // Apply the effects to the image object.
+    foreach ($this->getEffects() as $effect) {
+      $effect->applyEffect($image);
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function transformDimensions(array &$dimensions, $uri) {
     foreach ($this->getEffects() as $effect) {
       $effect->transformDimensions($dimensions, $uri);
@@ -500,4 +542,29 @@ protected function fileDefaultScheme() {
     return file_default_scheme();
   }
 
+  /**
+   * Returns the image factory service.
+   *
+   * @return \Drupal\Core\Image\ImageFactory
+   *   The image factory service.
+   */
+  protected function getImageFactory() {
+    if (!$this->imageFactory) {
+      $this->imageFactory = \Drupal::service('image.factory');
+    }
+    return $this->imageFactory;
+  }
+
+  /**
+   * Returns the file system service.
+   *
+   * @return \Drupal\Core\File\FileSystemInterface
+   *   The file system service.
+   */
+  protected function getFileSystem() {
+    if (!$this->fileSystem) {
+      $this->fileSystem = \Drupal::service('file_system');
+    }
+    return $this->fileSystem;
+  }
 }
diff --git a/core/modules/image/src/ImageStyleInterface.php b/core/modules/image/src/ImageStyleInterface.php
index 39bb583..684c350 100644
--- a/core/modules/image/src/ImageStyleInterface.php
+++ b/core/modules/image/src/ImageStyleInterface.php
@@ -8,6 +8,7 @@
 namespace Drupal\image;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Image\ImageInterface;
 
 /**
  * Provides an interface defining an image style entity.
@@ -107,7 +108,7 @@ public function getPathToken($uri);
   public function flush($path = NULL);
 
   /**
-   * Creates a new image derivative based on this image style.
+   * Creates a new image derivative from a source image file.
    *
    * Generates an image derivative applying all image effects and saving the
    * resulting image.
@@ -120,10 +121,51 @@ public function flush($path = NULL);
    * @return bool
    *   TRUE if an image derivative was generated, or FALSE if the image
    *   derivative could not be generated.
+   *
+   * @deprecated as of Drupal 8.1.0, will be removed before Drupal 9.0.0.
+   *   Instead, get an Image object from the factory and use the
+   *   ::applyAndSave() method on it.
+   *   @code
+   *     $image = \Drupal::service('image.factory')->get($original_uri);
+   *     $image_style->applyAndSave($image, $derivative_uri);
+   *   @endcode
+   *
+   * @see \Drupal\image\ImageStyleInterface::applyAndSave()
    */
   public function createDerivative($original_uri, $derivative_uri);
 
   /**
+   * Applies the style to an Image object and saves image to file.
+   *
+   * Alter the source image applying all image effects and saving the resulting
+   * image.
+   *
+   * @param \Drupal\Core\Image\ImageInterface $image
+   *   An Image object.
+   * @param string $derivative_uri
+   *   Derivative image file URI.
+   *
+   * @return bool
+   *   TRUE if the image derivative was saved, FALSE otherwise.
+   *
+   * @see \Drupal\image\ImageStyleInterface::apply()
+   */
+  public function applyAndSave(ImageInterface $image, $derivative_uri);
+
+  /**
+   * Applies the style to an Image object.
+   *
+   * Alter the source image applying all image effects.
+   *
+   * @param \Drupal\Core\Image\ImageInterface $image
+   *   An Image object.
+   *
+   * @return bool
+   *   TRUE if an the image was successfully altered, FALSE otherwise.
+   */
+  public function apply(ImageInterface $image);
+
+  /**
    * Determines the dimensions of this image style.
    *
    * Stores the dimensions of this image style into $dimensions associative
diff --git a/core/modules/image/src/Tests/FileMoveTest.php b/core/modules/image/src/Tests/FileMoveTest.php
index 34c54a7..8b5acda 100644
--- a/core/modules/image/src/Tests/FileMoveTest.php
+++ b/core/modules/image/src/Tests/FileMoveTest.php
@@ -36,7 +36,7 @@ function testNormal() {
     $style = reset($styles);
     $original_uri = $file->getFileUri();
     $derivative_uri = $style->buildUri($original_uri);
-    $style->createDerivative($original_uri, $derivative_uri);
+    $style->applyAndSave($this->container->get('image.factory')->get($original_uri), $derivative_uri);
 
     // Check if derivative image exists.
     $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.');
@@ -52,4 +52,43 @@ function testNormal() {
     // Check if derivative image has been flushed.
     $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.');
   }
+
+  /**
+   * Tests creating a derivative from scratch.
+   */
+  function testFromScratch() {
+    // Create scratch image.
+    $image = \Drupal::service('image.factory')->get();
+    $this->assertEqual($image->getSource(), '');
+    $this->assertEqual($image->getMimeType(), '');
+    $this->assertNull($image->getFileSize());
+    $image->createNew(600, 300, 'png');
+    $this->assertEqual($image->getSource(), '');
+    $this->assertEqual($image->getMimeType(), 'image/png');
+    $this->assertNull($image->getFileSize());
+
+    // Create derivative.
+    $style = ImageStyle::load('medium');
+    $desired_filepath = 'public://' . $this->randomMachineName();
+    $derivative_uri = $desired_filepath . '/test_0.png';
+    $style->applyAndSave($image, $derivative_uri);
+
+    // Check if derivative image exists.
+    $this->assertTrue(file_exists($derivative_uri));
+
+    // Check derivative image after saving, with old object.
+    $this->assertEqual($image->getWidth(), 220);
+    $this->assertEqual($image->getHeight(), 110);
+    $this->assertEqual($image->getSource(), $derivative_uri);
+    $this->assertEqual($image->getMimeType(), 'image/png');
+    $this->assertEqual($image->getFileSize(), 174);
+
+    // Check derivative image after reloading from saved image file.
+    $image = \Drupal::service('image.factory')->get($derivative_uri);
+    $this->assertEqual($image->getWidth(), 220);
+    $this->assertEqual($image->getHeight(), 110);
+    $this->assertEqual($image->getSource(), $derivative_uri);
+    $this->assertEqual($image->getMimeType(), 'image/png');
+    $this->assertEqual($image->getFileSize(), 174);
+  }
 }
diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/src/Tests/ImageAdminStylesTest.php
index cf5916c..6773f5b 100644
--- a/core/modules/image/src/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
@@ -410,7 +410,7 @@ public function testFlushUserInterface() {
     $files = $this->drupalGetTestFiles('image');
     $image_uri = $files[0]->uri;
     $derivative_uri = $style->buildUri($image_uri);
-    $this->assertTrue($style->createDerivative($image_uri, $derivative_uri));
+    $this->assertTrue($style->applyAndSave($this->container->get('image.factory')->get($image_uri), $derivative_uri));
     $this->assertEqual($this->getImageCount($style), 1);
 
     // Go to image styles list page and check if the flush operation link
diff --git a/core/modules/image/src/Tests/ImageFieldTestBase.php b/core/modules/image/src/Tests/ImageFieldTestBase.php
index 13b569d..021ea3a 100644
--- a/core/modules/image/src/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/src/Tests/ImageFieldTestBase.php
@@ -15,7 +15,6 @@
  *
  * image.effects.inc:
  *   image_style_generate()
- *   \Drupal\image\ImageStyleInterface::createDerivative()
  *
  * image.module:
  *   image_style_options()
diff --git a/core/modules/image/src/Tests/ImageStyleFlushTest.php b/core/modules/image/src/Tests/ImageStyleFlushTest.php
index 0a6a5fa..2520a38 100644
--- a/core/modules/image/src/Tests/ImageStyleFlushTest.php
+++ b/core/modules/image/src/Tests/ImageStyleFlushTest.php
@@ -31,7 +31,7 @@ function createSampleImage($style, $wrapper) {
     $source_uri = file_unmanaged_copy($file->uri, $wrapper . '://');
     // Build the derivative image.
     $derivative_uri = $style->buildUri($source_uri);
-    $derivative = $style->createDerivative($source_uri, $derivative_uri);
+    $derivative = $style->applyAndSave($this->container->get('image.factory')->get($source_uri), $derivative_uri);
 
     return $derivative ? $derivative_uri : FALSE;
   }
diff --git a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
index e8e7aae..25bd2b6 100644
--- a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
+++ b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
@@ -277,7 +277,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
 
     // Create a derivative so at least one MIME type will be known.
     $large_style = ImageStyle::load('large');
-    $large_style->createDerivative($image_uri, $large_style->buildUri($image_uri));
+    $large_style->applyAndSave($this->container->get('image.factory')->get($image_uri), $large_style->buildUri($image_uri));
 
     // Output should contain all image styles and all breakpoints.
     $this->drupalGet('node/' . $nid);
@@ -502,7 +502,7 @@ private function assertResponsiveImageFieldFormattersLink($link_type) {
     // Create a derivative so at least one MIME type will be known.
     $large_style = ImageStyle::load('large');
     $image_uri = File::load($node->{$field_name}->target_id)->getFileUri();
-    $large_style->createDerivative($image_uri, $large_style->buildUri($image_uri));
+    $large_style->applyAndSave($this->container->get('image.factory')->get($image_uri), $large_style->buildUri($image_uri));
 
     // Output should contain all image styles and all breakpoints.
     $this->drupalGet('node/' . $nid);
