diff --git a/MultimediaViewer.php b/MultimediaViewer.php
index 131b5a16c..f3bd1efce 100644
--- a/MultimediaViewer.php
+++ b/MultimediaViewer.php
@@ -150,6 +150,7 @@ call_user_func( function() {
'mmv.provider.ImageInfo.js',
'mmv.provider.FileRepoInfo.js',
'mmv.provider.ThumbnailInfo.js',
+ 'mmv.provider.Image.js',
),
'dependencies' => array(
diff --git a/MultimediaViewerHooks.php b/MultimediaViewerHooks.php
index 5c4cd9ef9..95fe8eeff 100644
--- a/MultimediaViewerHooks.php
+++ b/MultimediaViewerHooks.php
@@ -128,6 +128,7 @@ class MultimediaViewerHooks {
'tests/qunit/provider/mmv.provider.ImageInfo.test.js',
'tests/qunit/provider/mmv.provider.FileRepoInfo.test.js',
'tests/qunit/provider/mmv.provider.ThumbnailInfo.test.js',
+ 'tests/qunit/provider/mmv.provider.Image.test.js',
'tests/qunit/mmv.lightboxinterface.test.js',
'tests/qunit/mmv.ui.description.test.js',
'tests/qunit/mmv.ui.fileUsage.test.js',
diff --git a/resources/mmv/provider/mmv.provider.Image.js b/resources/mmv/provider/mmv.provider.Image.js
new file mode 100644
index 000000000..0bc9ea088
--- /dev/null
+++ b/resources/mmv/provider/mmv.provider.Image.js
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the MediaWiki extension MultimediaViewer.
+ *
+ * MultimediaViewer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MultimediaViewer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MultimediaViewer. If not, see .
+ */
+
+( function ( mw, $ ) {
+
+ /**
+ * @class mw.mmv.provider.Image
+ * Loads an image.
+ */
+ function Image() {
+ }
+
+ /**
+ * @method
+ * Loads an image and returns it.
+ * @param {string} url
+ * @return {jQuery.Promise} a promise which resolves to the image object
+ */
+ Image.prototype.get = function( url ) {
+ var img = new window.Image(),
+ deferred = $.Deferred();
+
+ img.src = url;
+ img.onload = function() {
+ deferred.resolve( img );
+ };
+ img.onerror = function() {
+ deferred.reject( 'could not load image from ' + url );
+ };
+
+ return deferred.promise();
+ };
+
+ mw.mmv.provider.Image = Image;
+}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/provider/mmv.provider.Image.test.js b/tests/qunit/provider/mmv.provider.Image.test.js
new file mode 100644
index 000000000..3d1e8127d
--- /dev/null
+++ b/tests/qunit/provider/mmv.provider.Image.test.js
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the MediaWiki extension MultimediaViewer.
+ *
+ * MultimediaViewer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MultimediaViewer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MultimediaViewer. If not, see .
+ */
+
+( function ( mw ) {
+ QUnit.module( 'mmv.provider.Image', QUnit.newMwEnvironment() );
+
+ QUnit.test( 'Image constructor sanity check', 1, function ( assert ) {
+ var imageProvider = new mw.mmv.provider.Image();
+
+ assert.ok( imageProvider );
+ } );
+
+ QUnit.asyncTest( 'Image load success test', 1, function ( assert ) {
+ var imageProvider = new mw.mmv.provider.Image();
+
+ imageProvider.get(
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0'
+ + 'iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH'
+ + '8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC'
+ ).then( function( image ) {
+ assert.ok( image instanceof HTMLImageElement,
+ 'success handler was called with the image element');
+ QUnit.start();
+ } );
+ } );
+
+ QUnit.asyncTest( 'Image load fail test', 1, function ( assert ) {
+ var imageProvider = new mw.mmv.provider.Image();
+
+ imageProvider.get( 'doesntexist.png' ).fail( function() {
+ assert.ok( true, 'fail handler was called' );
+ QUnit.start();
+ } );
+ } );
+}( mediaWiki ) );