diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 9ed3aa9..3422fd0 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -5,6 +5,8 @@
  * Administration pages for image settings.
  */
 
+use Drupal\Core\Template\Attribute;
+
 /**
  * Menu callback; Listing of all current image styles.
  */
@@ -601,15 +603,15 @@ function theme_image_style_effects($variables) {
 }
 
 /**
- * Returns HTML for a preview of an image style.
+ * Prepare variables for image style preview templates.
  *
- * @param $variables
- *   An associative array containing:
- *   - style: The image style array being previewed.
+ * Default template: image-style-preview.html.twig.
  *
- * @ingroup themeable
+ * @param array $variables
+ *   An associative array containing:
+ *   - style: The image style being previewed.
  */
-function theme_image_style_preview($variables) {
+function template_preprocess_image_style_preview(&$variables) {
   $style = $variables['style'];
 
   $sample_image = config('image.settings')->get('preview_image');
@@ -647,46 +649,50 @@ function theme_image_style_preview($variables) {
   $preview_attributes = array_intersect_key($preview_image, array('width' => '', 'height' => ''));
   $preview_attributes['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;';
 
-  // In the previews, timestamps are added to prevent caching of images.
-  $output = '<div class="image-style-preview preview clearfix">';
-
-  // Build the preview of the original image.
-  $original_url = file_create_url($original_path);
-  $output .= '<div class="preview-image-wrapper">';
-  $output .= t('original') . ' (' . l(t('view actual size'), $original_url) . ')';
-  $output .= '<div class="preview-image original-image" style="' . $original_attributes['style'] . '">';
-  $output .= '<a href="' . $original_url . '">' . theme('image', array('uri' => $original_path, 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes)) . '</a>';
-  $output .= '<div class="height" style="height: ' . $original_height . 'px"><span>' . $original_image['height'] . 'px</span></div>';
-  $output .= '<div class="width" style="width: ' . $original_width . 'px"><span>' . $original_image['width'] . 'px</span></div>';
-  $output .= '</div>'; // End preview-image.
-  $output .= '</div>'; // End preview-image-wrapper.
-
-  // Build the preview of the image style.
-  $preview_url = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME;
-  $output .= '<div class="preview-image-wrapper">';
-  $output .= check_plain($style->label()) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')';
-  $output .= '<div class="preview-image modified-image" style="' . $preview_attributes['style'] . '">';
-  $output .= '<a href="' . file_create_url($preview_file) . '?' . time() . '">' . theme('image', array('uri' => $preview_url, 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes)) . '</a>';
-  $output .= '<div class="height" style="height: ' . $preview_height . 'px"><span>' . $preview_image['height'] . 'px</span></div>';
-  $output .= '<div class="width" style="width: ' . $preview_width . 'px"><span>' . $preview_image['width'] . 'px</span></div>';
-  $output .= '</div>'; // End preview-image.
-  $output .= '</div>'; // End preview-image-wrapper.
-
-  $output .= '</div>'; // End image-style-preview.
+  $variables['style_name'] = check_plain($style->label());
+
+  // Original image variables.
+  $variables['original_url'] = file_create_url($original_path);
+  $variables['original_attributes'] = new Attribute($original_attributes);
+  $original_attributes['src'] = file_create_url($original_path);
+  $original_attributes['alt'] = t('Sample original image');
+  $variables['original_image'] = array(
+    '#theme' => 'image',
+    '#attributes' => new Attribute($original_attributes),
+    '#uri' => $variables['original_url'],
+  );
 
-  return $output;
+  $variables['original_image_height'] = $original_image['height'];
+  $variables['original_image_width'] = $original_image['width'];
+  $variables['original_height'] = $original_height;
+  $variables['original_width'] = $original_width;
+
+  // Preview image variables.
+  $variables['preview_url'] = file_create_url($preview_file) . '?' . time();
+  $variables['preview_attributes'] = new Attribute($preview_attributes);
+  $preview_attributes['src'] = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME;
+  $preview_attributes['alt'] = t('Sample modified image');
+  $variables['preview_image'] = array(
+    '#theme' => 'image',
+    '#attributes' => new Attribute($preview_attributes),
+    '#uri' => $variables['preview_url'],
+  );
+  $variables['preview_image_height'] = $preview_image['height'];
+  $variables['preview_image_width'] = $preview_image['width'];
+  $variables['preview_height'] = $preview_height;
+  $variables['preview_width'] = $preview_width;
 }
 
 /**
- * Returns HTML for a 3x3 grid of checkboxes for image anchors.
+ * Prepares variables for image anchor templates.
  *
- * @param $variables
- *   An associative array containing:
- *   - element: A render element containing radio buttons.
+ * Default template: image-anchor.html.twig.
  *
- * @ingroup themeable
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the image.
  */
-function theme_image_anchor($variables) {
+function template_preprocess_image_anchor(&$variables) {
   $element = $variables['element'];
 
   $rows = array();
@@ -694,73 +700,93 @@ function theme_image_anchor($variables) {
   foreach (element_children($element) as $n => $key) {
     $element[$key]['#attributes']['title'] = $element[$key]['#title'];
     unset($element[$key]['#title']);
-    $row[] = drupal_render($element[$key]);
+    $row[] = array(
+      'data' => $element[$key],
+    );
     if ($n % 3 == 3 - 1) {
       $rows[] = $row;
       $row = array();
     }
   }
-
-  return theme('table', array('header' => array(), 'rows' => $rows, 'attributes' => array('class' => array('image-anchor'))));
+  $variables['table'] = array(
+    '#theme' => 'table',
+    '#header' => array(),
+    '#rows' => $rows,
+    '#attributes' => array(
+      'class' => array('image-anchor'),
+    ),
+  );
 }
 
 /**
- * Returns HTML for a summary of an image resize effect.
+ * Prepares variables for image resize summary templates.
  *
- * @param $variables
+ * Default template: image-resize-summary.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - data: The current configuration for this resize effect.
- *
- * @ingroup themeable
  */
-function theme_image_resize_summary($variables) {
+function template_preprocess_image_resize_summary(&$variables) {
+  $output = '';
   $data = $variables['data'];
 
   if ($data['width'] && $data['height']) {
-    return check_plain($data['width']) . 'x' . check_plain($data['height']);
+    $output = check_plain($data['width']) . 'x' . check_plain($data['height']);
   }
   else {
-    return ($data['width']) ? t('width @width', array('@width' => $data['width'])) : t('height @height', array('@height' => $data['height']));
+    $output = ($data['width']) ? t('width @width', array('@width' => $data['width'])) : t('height @height', array('@height' => $data['height']));
+  }
+
+  if(isset($data['upscale'])) {
+    $output .= ' (' . t('upscaling allowed') . ')';
   }
+
+  $variables['summary'] = $output;
 }
 
 /**
- * Returns HTML for a summary of an image scale effect.
+ * Prepares variables for image scale summary templates.
  *
- * @param $variables
+ * Default template: image-scale-summary.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - data: The current configuration for this scale effect.
- *
- * @ingroup themeable
  */
-function theme_image_scale_summary($variables) {
-  $data = $variables['data'];
-  return theme('image_resize_summary', array('data' => $data)) . ' ' . ($data['upscale'] ? '(' . t('upscaling allowed') . ')' : '');
+function template_preprocess_image_scale_summary(&$variables) {
+  $variables['summary'] = array(
+    '#theme' => 'image_resize_summary',
+    '#data' => $variables['data'],
+  );
 }
 
 /**
- * Returns HTML for a summary of an image crop effect.
+ * Prepares variables for image crop summary templates.
  *
- * @param $variables
+ * Default template: image-crop-summary.html.twig
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - data: The current configuration for this crop effect.
- *
- * @ingroup themeable
  */
-function theme_image_crop_summary($variables) {
-  return theme('image_resize_summary', $variables);
+function template_preprocess_image_crop_summary(&$variables) {
+  $variables['summary'] = array(
+    '#theme' => 'image_resize_summary',
+    '#data' => $variables['data'],
+  );
 }
 
 /**
- * Returns HTML for a summary of an image rotate effect.
+ * Prepares varaibles for image rotate summary templates.
  *
- * @param $variables
+ * Default template: image-rotate-summary-html-twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - data: The current configuration for this rotate effect.
- *
- * @ingroup themeable
  */
-function theme_image_rotate_summary($variables) {
+function template_preprocess_image_rotate_summary(&$variables) {
   $data = $variables['data'];
-  return ($data['random']) ? t('random between -@degrees&deg and @degrees&deg', array('@degrees' => str_replace('-', '', $data['degrees']))) : t('@degrees&deg', array('@degrees' => $data['degrees']));
+  $variables['summary'] = ($data['random']) ? t('random between -@degrees&deg and @degrees&deg', array('@degrees' => str_replace('-', '', $data['degrees']))) : t('@degrees&deg', array('@degrees' => $data['degrees']));
 }
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index a287620..5426061 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -7,6 +7,7 @@
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Template\Attribute;
 
 /**
  * Implements hook_field_info().
@@ -418,39 +419,35 @@ function _image_field_required_fields_validate($element, &$form_state) {
 }
 
 /**
- * Returns HTML for an image field widget.
+ * Prepare variables for image widget templates.
+ *
+ * Default template: image-widget.html.twig.
  *
  * @param array $variables
  *   An associative array containing:
- *   - element: A render element representing the image field widget.
- *
- * @ingroup themeable
+ *   - element: An render element representing the image field widget.
  */
-function theme_image_widget($variables) {
+function template_preprocess_image_widget(&$variables) {
   $element = $variables['element'];
-  $output = '';
-  $output .= '<div class="image-widget form-managed-file clearfix">';
+  $element['#attributes']['class'] = array('image-widget', 'form-managed-file', 'clearfix');
 
   if (isset($element['preview'])) {
-    $output .= '<div class="image-preview">';
-    $output .= drupal_render($element['preview']);
-    $output .= '</div>';
+    $variables['preview'] = $element['preview'];
   }
 
-  $output .= '<div class="image-widget-data">';
   if (!empty($element['fids']['#value'])) {
     $file = reset($element['#files']);
-    $element['file_' . $file->fid]['filename']['#markup'] .= ' <span class="file-size">(' . format_size($file->filesize) . ')</span> ';
+    $element['file_' . $file->fid]['filename']['#markup'] .= '<span class="file-size">(' . format_size($file->filesize) . ')</span>';
   }
-  $output .= drupal_render_children($element);
-  $output .= '</div>';
-  $output .= '</div>';
 
-  return $output;
+  $variables['data'] = drupal_render_children($element);
+  $variables['attributes'] = new Attribute($element['#attributes']);
 }
 
 /**
- * Returns HTML for an image field formatter.
+ * Prepares variables for image formatter templates.
+ *
+ * Default template: image-formatter.html.twig.
  *
  * @param array $variables
  *   An associative array containing:
@@ -459,8 +456,11 @@ function theme_image_widget($variables) {
  *   - path: An optional array containing the link 'path' and link 'options'.
  *
  * @ingroup themeable
+ *
+ * @todo Refactor this to remove theme() call when theme_image() is converted.
+ *   http://drupal.org/node/1939068
  */
-function theme_image_formatter($variables) {
+function template_preprocess_image_formatter(&$variables) {
   $item = $variables['item'];
 
   // Do not output an empty 'title' attribute.
@@ -468,12 +468,34 @@ function theme_image_formatter($variables) {
     unset($item['title']);
   }
 
-  if ($variables['image_style']) {
-    $item['style_name'] = $variables['image_style'];
-    $output = theme('image_style', $item);
+  if (!empty($variables['image_style'])) {
+    // Build a render array for the image from the formatter item.
+    $image = array(
+      '#theme' => 'image_style',
+      '#style_name' => $variables['image_style'],
+    );
+    if(isset($item['uri'])) {
+      $image['#uri'] = $item['uri'];
+    }
+    if(isset($item['width'])) {
+      $image['#width'] = $item['width'];
+    }
+    if(isset($item['height'])) {
+      $image['#height'] = $item['height'];
+    }
+    if(isset($item['alt'])) {
+      $image['#alt'] = $item['alt'];
+    }
+    if(isset($item['title'])) {
+      $image['#title'] = $item['title'];
+    }
+    if(isset($item['attributes'])) {
+      $image['#attributes'] = $item['attributes'];
+    }
+    $variables['image'] = $image;
   }
   else {
-    $output = theme('image', $item);
+    $variables['image'] = theme('image', $item);
   }
 
   // The link path and link options are both optional, but for the options to be
@@ -483,8 +505,6 @@ function theme_image_formatter($variables) {
     $options = isset($variables['path']['options']) ? $variables['path']['options'] : array();
     // When displaying an image inside a link, the html option must be TRUE.
     $options['html'] = TRUE;
-    $output = l($output, $path, $options);
+    $variables['url'] = url($path, $options);
   }
-
-  return $output;
 }
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index a7696a6..4bdefdb 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -12,6 +12,7 @@
 use Drupal\Component\Uuid\Uuid;
 use Drupal\file\Plugin\Core\Entity\File;
 use Drupal\image\Plugin\Core\Entity\ImageStyle;
+use Drupal\Core\Template\Attribute;
 
 /**
  * Image style constant for user presets in the database.
@@ -204,6 +205,7 @@ function image_theme() {
         'title' => NULL,
         'attributes' => array(),
       ),
+      'template' => 'image-style',
     ),
 
     // Theme functions in image.admin.inc.
@@ -215,21 +217,33 @@ function image_theme() {
     ),
     'image_style_preview' => array(
       'variables' => array('style' => NULL),
+      'file' => 'image.admin.inc',
+      'template' => 'image-style-preview',
     ),
     'image_anchor' => array(
       'render element' => 'element',
+      'file' => 'image.admin.inc',
+      'template' => 'image-anchor',
     ),
     'image_resize_summary' => array(
       'variables' => array('data' => NULL),
+      'file' => 'image.admin.inc',
+      'template' => 'image-resize-summary',
     ),
     'image_scale_summary' => array(
       'variables' => array('data' => NULL),
+      'file' => 'image.admin.inc',
+      'template' => 'image-scale-summary',
     ),
     'image_crop_summary' => array(
       'variables' => array('data' => NULL),
+      'file' => 'image.admin.inc',
+      'template' => 'image-crop-summary',
     ),
     'image_rotate_summary' => array(
       'variables' => array('data' => NULL),
+      'file' => 'image.admin.inc',
+      'template' => 'image-rotate-summary',
     ),
 
     // Theme functions in image.field.inc.
@@ -238,6 +252,7 @@ function image_theme() {
     ),
     'image_formatter' => array(
       'variables' => array('item' => NULL, 'path' => NULL, 'image_style' => NULL),
+      'template' => 'image-formatter',
     ),
   );
 }
@@ -960,26 +975,21 @@ function image_effect_apply($image, $effect) {
 }
 
 /**
- * Returns HTML for an image using a specific image style.
+ * Prepare variables for image style templates.
  *
- * @param $variables
- *   An associative array containing:
- *   - style_name: The name of the style to be used to alter the original image.
- *   - uri: The path of the image file relative to the Drupal files directory.
- *     This function does not work with images outside the files directory nor
- *     with remotely hosted images. This should be in a format such as
- *     'images/image.jpg', or using a stream wrapper such as
- *     'public://images/image.jpg'.
- *   - width: The width of the source image (if known).
- *   - height: The height of the source image (if known).
- *   - alt: The alternative text for text-based browsers.
- *   - title: The title text is displayed when the image is hovered in some
- *     popular browsers.
- *   - attributes: Associative array of attributes to be placed in the img tag.
+ * Default template: image-style.html.twig.
  *
- * @ingroup themeable
+ * @param array $variables
+ *   An associative array containing:
+ *   - width: The width of the image.
+ *   - height: The height of the image.
+ *   - style_name: The name of the image style to be applied.
+ *   - attributes: Additional attributes to apply to the image.
+ *   - uri: URI of the source image before styling.
+ *   - alt: Alternative text to be displayed instead of the image.
+ *   - title: Title of the image.
  */
-function theme_image_style($variables) {
+function template_preprocess_image_style(&$variables) {
   // Determine the dimensions of the styled image.
   $dimensions = array(
     'width' => $variables['width'],
@@ -996,7 +1006,23 @@ function theme_image_style($variables) {
 
   // Determine the URL for the styled image.
   $variables['uri'] = image_style_url($variables['style_name'], $variables['uri']);
-  return theme('image', $variables);
+
+  // Add the URL to the attributes.
+  $variables['attributes']['src'] = file_create_url($variables['uri']);
+
+  // @todo fix this
+  foreach (array('width', 'height', 'alt', 'title') as $key) {
+    if (isset($variables[$key])) {
+      $variables['attributes'][$key] = $variables[$key];
+    }
+  }
+
+  // create renderable image array
+  $variables['image'] = array(
+    '#theme' => 'image',
+    '#attributes' => $variables['attributes'],
+    '#uri' => $variables['uri'],
+  );
 }
 
 /**
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
index e7552d2..eadbf5d 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
@@ -69,7 +69,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="120" height="60" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -90,7 +90,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="60" height="120" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -112,7 +112,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -134,7 +134,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -152,7 +152,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -173,7 +173,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -193,7 +193,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="30" height="30" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -214,7 +214,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
     $this->drupalGet($url);
@@ -232,7 +232,7 @@ function testImageDimensions() {
     );
 
     image_effect_save($style, $effect);
-    $img_tag = theme_image_style($variables);
+    $img_tag = theme('image_style', $variables);
     $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
   }
 }
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index c30c686..e0222d4 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -98,9 +98,17 @@ function _testImageFieldFormatters($scheme) {
     $display_options['settings']['image_link'] = 'content';
     $display->setComponent($field_name, $display_options)
       ->save();
-    $default_output = l(theme('image', $image_info), 'node/' . $nid, array('html' => TRUE, 'attributes' => array('class' => 'active')));
     $this->drupalGet('node/' . $nid);
-    $this->assertRaw($default_output, 'Image linked to content formatter displaying correctly on full node view.');
+    $elements = $this->xpath(
+      '//a[@href=:path]/img[@src=:url and @alt="" and @width=:width and @height=:height]',
+      array(
+        ':path' => url('node/' . $nid),
+        ':url' => file_create_url($image_info['uri']),
+        ':width' => $image_info['width'],
+        ':height' => $image_info['height']
+      )
+    );
+    $this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.');
 
     // Test the image style 'thumbnail' formatter.
     $display_options['settings']['image_link'] = '';
