diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index ceb2c8a..e1604da 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -34,6 +34,7 @@ function image_field_info() {
       ),
       'default_widget' => 'image_image',
       'default_formatter' => 'image',
+      'field item class' => '\Drupal\image\Type\ImageItem',
     ),
   );
 }
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php
new file mode 100644
index 0000000..ed2f638
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * @image
+ * Contains \Drupal\image\Tests\ImageItemTest.
+ */
+
+namespace Drupal\image\Tests;
+
+use Drupal\Core\Entity\Field\FieldItemInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
+use Drupal\field\Tests\FieldItemUnitTestBase;
+
+/**
+ * Tests the new entity API for the image field type.
+ */
+class ImageItemTest extends FieldItemUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('file', 'image');
+
+  /**
+   * Created file entity.
+   *
+   * @var \Drupal\file\Plugin\Core\Entity\File
+   */
+  protected $image;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Image field item API',
+      'description' => 'Tests using entity fields of the image field type.',
+      'group' => 'Image',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->installSchema('file', 'file_managed');
+    $this->installSchema('file', 'file_usage');
+
+    $field = array(
+      'field_name' => 'image_test',
+      'type' => 'image',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    );
+    field_create_field($field);
+    $instance = array(
+      'entity_type' => 'entity_test',
+      'field_name' => 'image_test',
+      'bundle' => 'entity_test',
+      'widget' => array(
+        'type' => 'image_image',
+      ),
+    );
+    field_create_instance($instance);
+    file_unmanaged_copy(DRUPAL_ROOT . '/core/misc/druplicon.png', 'public://example.jpg');
+    $this->image = entity_create('file', array(
+      'uri' => 'public://example.jpg',
+    ));
+    $this->image->save();
+  }
+
+  /**
+   * Tests using entity fields of the image field type.
+   */
+  public function testImageItem() {
+    // Create a test entity with the
+    $entity = entity_create('entity_test', array());
+    $entity->image_test->fid = $this->image->id();
+    $entity->image_test->alt = $alt = $this->randomName();
+    $entity->image_test->title = $title = $this->randomName();
+    $entity->name->value = $this->randomName();
+    $entity->save();
+
+    $entity = entity_load('entity_test', $entity->id());
+    $this->assertTrue($entity->image_test instanceof FieldInterface, 'Field implements interface.');
+    $this->assertTrue($entity->image_test[0] instanceof FieldItemInterface, 'Field item implements interface.');
+    $this->assertEqual($entity->image_test->fid, $this->image->id());
+    $this->assertEqual($entity->image_test->alt, $alt);
+    $this->assertEqual($entity->image_test->title, $title);
+    $info = image_get_info('public://example.jpg');
+    $this->assertEqual($entity->image_test->width, $info['width']);
+    $this->assertEqual($entity->image_test->height, $info['height']);
+    $this->assertEqual($entity->image_test->entity->id(), $this->image->id());
+    $this->assertEqual($entity->image_test->entity->uuid(), $this->image->uuid());
+
+    // Make sure the computed entity reflects updates to the referenced file.
+    file_unmanaged_copy(DRUPAL_ROOT . '/core/misc/feed.png', 'public://example-2.jpg');
+    $image2 = entity_create('file', array(
+      'uri' => 'public://example-2.jpg',
+    ));
+    $image2->save();
+
+    $entity->image_test->fid = $image2->id();
+    $entity->image_test->alt = $new_alt = $this->randomName();
+    // The width and height is only updated when width is not set.
+    $entity->image_test->width = NULL;
+    $entity->save();
+    $this->assertEqual($entity->image_test->entity->id(), $image2->id());
+    $this->assertEqual($entity->image_test->entity->uri, $image2->uri);
+    $info = image_get_info('public://example-2.jpg');
+    $this->assertEqual($entity->image_test->width, $info['width']);
+    $this->assertEqual($entity->image_test->height, $info['height']);
+    $this->assertEqual($entity->image_test->alt, $new_alt);
+  }
+
+}
diff --git a/core/modules/image/lib/Drupal/image/Type/ImageItem.php b/core/modules/image/lib/Drupal/image/Type/ImageItem.php
new file mode 100644
index 0000000..cbfea71
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/Type/ImageItem.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @image
+ * Contains \Drupal\image\Type\ImageItem.
+ */
+
+namespace Drupal\image\Type;
+
+use Drupal\Core\Entity\Field\FieldItemBase;
+
+/**
+ * Defines the 'image_field' entity field item.
+ */
+class ImageItem extends FieldItemBase {
+
+  /**
+   * Property definitions of the contained properties.
+   *
+   * @see ImageItem::getPropertyDefinitions()
+   *
+   * @var array
+   */
+  static $propertyDefinitions;
+
+  /**
+   * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
+   */
+  public function getPropertyDefinitions() {
+    if (!isset(static::$propertyDefinitions)) {
+      static::$propertyDefinitions['fid'] = array(
+        'type' => 'integer',
+        'label' => t('Referenced file id.'),
+      );
+      static::$propertyDefinitions['alt'] = array(
+        'type' => 'boolean',
+        'label' => t("Alternative image text, for the image's 'alt' attribute."),
+      );
+      static::$propertyDefinitions['title'] = array(
+        'type' => 'string',
+        'label' => t("Image title text, for the image's 'title' attribute."),
+      );
+      static::$propertyDefinitions['width'] = array(
+        'type' => 'integer',
+        'label' => t('The width of the image in pixels.'),
+      );
+      static::$propertyDefinitions['height'] = array(
+        'type' => 'integer',
+        'label' => t('The height of the image in pixels.'),
+      );
+      static::$propertyDefinitions['entity'] = array(
+        'type' => 'entity',
+        'constraints' => array(
+          'EntityType' => 'file',
+        ),
+        'label' => t('Image'),
+        'description' => t('The referenced file'),
+        // The entity object is computed out of the fid.
+        'computed' => TRUE,
+        'read-only' => FALSE,
+        'settings' => array('id source' => 'fid'),
+      );
+    }
+    return static::$propertyDefinitions;
+  }
+
+  /**
+   * Overrides \Drupal\Core\Entity\Field\FieldItemBase::setValue().
+   */
+  public function setValue($values) {
+    // Treat the values as property value of the entity field, if no array
+    // is given.
+    if (!is_array($values)) {
+      $values = array('entity' => $values);
+    }
+
+    foreach (array('alt', 'title', 'width', 'height') as $property) {
+      if (isset($values[$property])) {
+        $this->properties[$property]->setValue($values[$property]);
+        unset($values[$property]);
+      }
+    }
+
+    // Entity is computed out of the ID, so we only need to update the ID. Only
+    // set the entity field if no ID is given.
+    if (isset($values['fid'])) {
+      $this->properties['fid']->setValue($values['fid']);
+    }
+    elseif (isset($values['entity'])) {
+      $this->properties['entity']->setValue($values['entity']);
+    }
+    else {
+      $this->properties['entity']->setValue(NULL);
+    }
+    unset($values['fid'], $values['entity']);
+    if ($values) {
+      throw new \InvalidArgumentException('Property ' . key($values) . ' is unknown.');
+    }
+  }
+
+}
