diff --git a/core/modules/image/config/schema/image.source.schema.yml b/core/modules/image/config/schema/image.source.schema.yml
new file mode 100644
index 0000000..1230023
--- /dev/null
+++ b/core/modules/image/config/schema/image.source.schema.yml
@@ -0,0 +1,3 @@
+migrate.source.d6_imagecache_presets:
+  type: migrate_source_sql
+  label: 'Drupal 6 ImageCache Presets'
diff --git a/core/modules/image/migration_templates/d6_imagecache_presets.yml b/core/modules/image/migration_templates/d6_imagecache_presets.yml
new file mode 100644
index 0000000..91e1201
--- /dev/null
+++ b/core/modules/image/migration_templates/d6_imagecache_presets.yml
@@ -0,0 +1,24 @@
+id: d6_imagecache_presets
+label: Drupal 6 ImageCache Presets
+migration_tags:
+  - Drupal 6
+source:
+  plugin: d6_imagecache_presets
+process:
+  name:
+    -
+      plugin: machine_name
+      source: presetname
+    -
+      plugin: dedupe_entity
+      entity_type: image_style
+      field: name
+      length: 32
+  label: presetname
+  effects:
+    plugin: d6_imagecache_actions
+    source:
+      - @plugin
+      - data
+destination:
+  plugin: entity:image_style
diff --git a/core/modules/image/src/Plugin/migrate/destination/EntityImageStyle.php b/core/modules/image/src/Plugin/migrate/destination/EntityImageStyle.php
new file mode 100644
index 0000000..35de88e
--- /dev/null
+++ b/core/modules/image/src/Plugin/migrate/destination/EntityImageStyle.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\Plugin\migrate\destination\EntityImageStyle.
+ */
+
+namespace Drupal\image\Plugin\migrate\destination;
+
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
+use Drupal\migrate\Row;
+
+/**
+ * Every migration that uses this destination must have an optional
+ * dependency on the d6_file migration to ensure it runs first.
+ *
+ * @MigrateDestination(
+ *   id = "entity:image_style"
+ * )
+ */
+class EntityImageStyle extends EntityConfigBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function import(Row $row, array $old_destination_id_values = []) {
+    $effects = [];
+
+    // Need to set the effects property to null on the row before the ImageStyle
+    // is created, this prevents improper effect plugin initialization.
+    if ($row->getDestinationProperty('effects')) {
+      $effects = $row->getDestinationProperty('effects');
+      $row->setDestinationProperty('effects', []);
+    }
+
+    /** @var \Drupal\Image\Entity\ImageStyle $style */
+    $style = $this->getEntity($row, $old_destination_id_values);
+
+    // Iterate the effects array so each effect plugin can be initialized.
+    // Catch any missing plugin exceptions.
+    foreach ($effects as $effect) {
+      try {
+        $style->addImageEffect($effect);
+      }
+      catch (PluginNotFoundException $e) {
+        throw new MigrateException($e->getMessage(), 0, $e);
+      }
+    }
+
+    $style->save();
+
+    return array($style->id());
+  }
+
+}
diff --git a/core/modules/image/src/Plugin/migrate/process/d6/ImageCacheActions.php b/core/modules/image/src/Plugin/migrate/process/d6/ImageCacheActions.php
new file mode 100644
index 0000000..deb9934
--- /dev/null
+++ b/core/modules/image/src/Plugin/migrate/process/d6/ImageCacheActions.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * contains \Drupal\image\Plugin\migrate\process\d6\ImageCacheActions.
+ */
+
+namespace Drupal\image\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\MigrateSkipRowException;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_imagecache_actions"
+ * )
+ */
+class ImageCacheActions extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    $effects = [];
+
+    foreach($row->getSourceProperty('actions') as $action) {
+      $id = preg_replace('/^imagecache/', 'image', $action['action']);
+
+      if ($id === 'image_crop') {
+        $action['data']['anchor'] = $action['data']['xoffset'] . '-' . $action['data']['yoffset'];
+
+        if (!preg_match('/^[a-z]*\-[a-z]*/', $action['data']['anchor'])) {
+          $migrate_executable->message->display(
+            'The Drupal 8 image crop effect does not support numeric values for x and y offsets. Use keywords to set crop effect offsets instead.',
+            'error'
+          );
+        }
+
+        unset($action['data']['xoffset']);
+        unset($action['data']['yoffset']);
+      }
+
+      $effects[] = [
+        'id'     => $id,
+        'weight' => $action['weight'],
+        'data'   => $action['data'],
+      ];
+    }
+
+    return $effects;
+  }
+
+}
diff --git a/core/modules/image/src/Plugin/migrate/source/d6/ImageCachePreset.php b/core/modules/image/src/Plugin/migrate/source/d6/ImageCachePreset.php
new file mode 100644
index 0000000..8c563f0
--- /dev/null
+++ b/core/modules/image/src/Plugin/migrate/source/d6/ImageCachePreset.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\Plugin\migrate\source\d6\ImageCachePreset.
+ */
+
+namespace Drupal\image\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+use Drupal\migrate\Row;
+
+/**
+ * Drupal 6 imagecache presets source from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_imagecache_presets"
+ * )
+ */
+class ImageCachePreset extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('imagecache_preset', 'icp')
+      ->fields('icp');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    $fields = [
+      'presetid' => $this->t('Preset ID'),
+      'presetname' => $this->t('Preset Name'),
+    ];
+    return $fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['presetid']['type'] = 'integer';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $actions = array();
+
+    $results = $this->select('imagecache_action', 'ica')
+      ->fields('ica')
+      ->condition('presetid', $row->getSourceProperty('presetid'))
+      ->execute();
+
+    foreach($results as $key => $result) {
+      $actions[$key] = $result;
+      $actions[$key]['data'] = unserialize($result['data']);
+    }
+
+    $row->setSourceProperty('actions', $actions);
+    return parent::prepareRow($row);
+  }
+
+}
diff --git a/core/modules/image/src/Tests/Migrate/d6/MigrateImageCacheTest.php b/core/modules/image/src/Tests/Migrate/d6/MigrateImageCacheTest.php
new file mode 100644
index 0000000..68efb34
--- /dev/null
+++ b/core/modules/image/src/Tests/Migrate/d6/MigrateImageCacheTest.php
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateImageCacheTest.
+ */
+
+namespace Drupal\image\Tests\Migrate\d6;
+
+use Drupal\Core\Database\Database;
+use Drupal\image\Entity\ImageStyle;
+use \Drupal\image\ConfigurableImageEffectBase;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
+
+/**
+ * Migrate ImageCache presets to Image styles
+ *
+ * @group image
+ */
+class MigrateImageCacheTest extends MigrateDrupal6TestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('image');
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->prepareMigrations(array(
+      'd6_imagecache_presets' => [],
+    ));
+    $this->installConfig(['image']);
+  }
+
+  /**
+   * Override parent to setup migration prior to run.
+   */
+  public function testSourcePlugin() {
+    $this->executeMigration('d6_imagecache_presets');
+    parent::testSourcePlugin();
+  }
+
+  /**
+   * Test basic passing migrations.
+   */
+  public function testPassingMigration() {
+    $this->executeMigration('d6_imagecache_presets');
+
+    /** @var \Drupal\image\Entity\ImageStyle $style */
+    $style = ImageStyle::load('big_blue_cheese');
+
+    // Check basic Style info.
+    $this->assertIdentical('big_blue_cheese', $style->get('name'), 'ImageStyle name set correctly');
+    $this->assertIdentical('big_blue_cheese', $style->get('label'), 'ImageStyle label set correctly');
+
+    // Test effects.
+    $effects = $style->getEffects();
+
+    // Check crop effect.
+    $this->assertImageEffect($effects, 'image_crop', [
+      'width' => 555,
+      'height' => 5555,
+      'anchor' => 'center-center',
+    ]);
+
+    // Check resize effect.
+    $this->assertImageEffect($effects, 'image_resize', [
+      'width' => 55,
+      'height' => 55,
+    ]);
+
+    // Check rotate effect.
+    $this->assertImageEffect($effects, 'image_rotate', [
+      'degrees' => 55,
+      'random' => FALSE,
+      'bgcolor' => '',
+    ]);
+  }
+
+  /**
+   * Test that missing actions causes failures.
+   */
+   public function testMissingEffectPlugin() {
+     Database::getConnection('default', 'migrate')->insert("imagecache_action")
+       ->fields([
+         'presetid',
+         'weight',
+         'module',
+         'action',
+         'data',
+       ])
+       ->values([
+         'presetid' => '1',
+         'weight' => '0',
+         'module' => 'imagecache',
+         'action' => 'imagecache_deprecated_scale',
+         'data' => 'a:3:{s:3:"fit";s:7:"outside";s:5:"width";s:3:"200";s:6:"height";s:3:"200";}',
+       ])->execute();
+
+     $this->startCollectingMessages();
+     $this->executeMigration('d6_imagecache_presets');
+     $this->assertEqual(['error' => [
+       'The "image_deprecated_scale" plugin does not exist.'
+     ]], $this->migrateMessages);
+  }
+
+  /**
+   * Test that missing action's causes failures.
+   */
+   public function testInvalidCropValues() {
+     Database::getConnection('default', 'migrate')->insert("imagecache_action")
+       ->fields([
+         'presetid',
+         'weight',
+         'module',
+         'action',
+         'data',
+       ])
+       ->values([
+         'presetid' => '1',
+         'weight' => '0',
+         'module' => 'imagecache',
+         'action' => 'imagecache_crop',
+         'data' => serialize([
+           'xoffset' => '10',
+           'yoffset' => '10',
+         ]),
+       ])->execute();
+
+     $this->startCollectingMessages();
+     $this->executeMigration('d6_imagecache_presets');
+     $this->assertEqual(['error' => [
+       'The Drupal 8 image crop effect does not support numeric values for x and y offsets. Use keywords to set crop effect offsets instead.'
+     ]], $this->migrateMessages);
+  }
+
+  /**
+   * Assert that a given image effect is migrated.
+   *
+   * @param array $collection
+   *   Collection of effects
+   * @param $id
+   *   Id that should exist in the collection.
+   * @param $config
+   *   Expected configuration for the collection.
+   *
+   * @return bool
+   */
+  protected function assertImageEffect($collection, $id, $config) {
+    /** @var \Drupal\image\ConfigurableImageEffectBase $effect */
+    foreach ($collection as $key => $effect) {
+      $effect_config = $effect->getConfiguration();
+
+      if ($effect_config['id'] == $id && $effect_config['data'] == $config) {
+        // We found this effect so succeed and return.
+        return $this->pass('Effect ' . $id . ' imported correctly');
+      }
+    }
+    // The loop did not find the effect so we it was not imported correctly.
+    return $this->fail('Effect ' . $id . ' did not import correctly');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php
new file mode 100644
index 0000000..194cc93
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Table\d6\ImagecacheAction.
+ *
+ * THIS IS A GENERATED FILE. DO NOT EDIT.
+ *
+ * @see core/scripts/migrate-db.sh
+ * @see https://www.drupal.org/sandbox/benjy/2405029
+ */
+
+namespace Drupal\migrate_drupal\Tests\Table\d6;
+
+use Drupal\migrate_drupal\Tests\Dump\DrupalDumpBase;
+
+/**
+ * Generated file to represent the imagecache_action table.
+ */
+class ImagecacheAction extends DrupalDumpBase {
+
+  public function load() {
+    $this->createTable("imagecache_action", array(
+      'primary key' => array(
+        'actionid',
+      ),
+      'fields' => array(
+        'actionid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'length' => '10',
+          'unsigned' => TRUE,
+        ),
+        'presetid' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'length' => '10',
+          'default' => '0',
+          'unsigned' => TRUE,
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'length' => '11',
+          'default' => '0',
+        ),
+        'module' => array(
+          'type' => 'varchar',
+          'not null' => TRUE,
+          'length' => '255',
+        ),
+        'action' => array(
+          'type' => 'varchar',
+          'not null' => TRUE,
+          'length' => '255',
+        ),
+        'data' => array(
+          'type' => 'text',
+          'not null' => TRUE,
+          'length' => 100,
+        ),
+      ),
+      'mysql_character_set' => 'utf8',
+    ));
+    $this->database->insert("imagecache_action")->fields(array(
+      'actionid',
+      'presetid',
+      'weight',
+      'module',
+      'action',
+      'data',
+    ))
+    ->values(array(
+      'actionid' => '3',
+      'presetid' => '1',
+      'weight' => '0',
+      'module' => 'imagecache',
+      'action' => 'imagecache_scale_and_crop',
+      'data' => 'a:2:{s:5:"width";s:4:"100%";s:6:"height";s:4:"100%";}',
+    ))->values(array(
+      'actionid' => '4',
+      'presetid' => '2',
+      'weight' => '0',
+      'module' => 'imagecache',
+      'action' => 'imagecache_crop',
+      'data' => 'a:4:{s:5:"width";s:3:"555";s:6:"height";s:4:"5555";s:7:"xoffset";s:6:"center";s:7:"yoffset";s:6:"center";}',
+    ))->values(array(
+      'actionid' => '5',
+      'presetid' => '2',
+      'weight' => '0',
+      'module' => 'imagecache',
+      'action' => 'imagecache_resize',
+      'data' => 'a:2:{s:5:"width";s:3:"55%";s:6:"height";s:3:"55%";}',
+    ))->values(array(
+      'actionid' => '6',
+      'presetid' => '2',
+      'weight' => '0',
+      'module' => 'imagecache',
+      'action' => 'imagecache_rotate',
+      'data' => 'a:3:{s:7:"degrees";s:2:"55";s:6:"random";i:0;s:7:"bgcolor";s:0:"";}',
+    ))->execute();
+  }
+
+}
+#90267fd3a92bd722208f016a23ab5f97
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php
new file mode 100644
index 0000000..154662c
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Table\d6\ImagecachePreset.
+ *
+ * THIS IS A GENERATED FILE. DO NOT EDIT.
+ *
+ * @see core/scripts/migrate-db.sh
+ * @see https://www.drupal.org/sandbox/benjy/2405029
+ */
+
+namespace Drupal\migrate_drupal\Tests\Table\d6;
+
+use Drupal\migrate_drupal\Tests\Dump\DrupalDumpBase;
+
+/**
+ * Generated file to represent the imagecache_preset table.
+ */
+class ImagecachePreset extends DrupalDumpBase {
+
+  public function load() {
+    $this->createTable("imagecache_preset", array(
+      'primary key' => array(
+        'presetid',
+      ),
+      'fields' => array(
+        'presetid' => array(
+          'type' => 'serial',
+          'not null' => TRUE,
+          'length' => '10',
+          'unsigned' => TRUE,
+        ),
+        'presetname' => array(
+          'type' => 'varchar',
+          'not null' => TRUE,
+          'length' => '255',
+        ),
+      ),
+      'mysql_character_set' => 'utf8',
+    ));
+    $this->database->insert("imagecache_preset")->fields(array(
+      'presetid',
+      'presetname',
+    ))
+    ->values(array(
+      'presetid' => '1',
+      'presetname' => 'slackjaw_boys',
+    ))->values(array(
+      'presetid' => '2',
+      'presetname' => 'big_blue_cheese',
+    ))->execute();
+  }
+
+}
+#b2102d82ad5b3d8be026fe23cea75674
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
index a684403..d0d9d9b 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
@@ -848,6 +848,28 @@ public function load() {
       'weight' => '0',
       'info' => 'a:10:{s:4:"name";s:8:"Views UI";s:11:"description";s:93:"Administrative interface to views. Without this module, you cannot create or edit your views.";s:7:"package";s:5:"Views";s:4:"core";s:3:"6.x";s:12:"dependencies";a:1:{i:0;s:5:"views";}s:7:"version";s:7:"6.x-3.0";s:7:"project";s:5:"views";s:9:"datestamp";s:10:"1325638545";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
     ))->values(array(
+      'filename' => 'sites/all/modules/imageapi/imageapi.module',
+      'name' => 'imageapi',
+      'type' => 'module',
+      'owner' => '',
+      'status' => '1',
+      'throttle' => '0',
+      'bootstrap' => '0',
+      'schema_version' => '0',
+      'weight' => '0',
+      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
+    ))->values(array(
+      'filename' => 'sites/all/modules/imagecache/imagecache.module',
+      'name' => 'imagecache',
+      'type' => 'module',
+      'owner' => '',
+      'status' => '1',
+      'throttle' => '0',
+      'bootstrap' => '0',
+      'schema_version' => '6001',
+      'weight' => '0',
+      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
+    ))->values(array(
       'filename' => 'themes/bluemarine/bluemarine.info',
       'name' => 'bluemarine',
       'type' => 'theme',
@@ -917,4 +939,4 @@ public function load() {
   }
 
 }
-#f48594e66407fef659b575523a75c6e6
+#f7d26efda87933cbe199c1f232d329b2
