diff --git a/Gruntfile.js b/Gruntfile.js
index 06511e31..8c7ff60a 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -39,6 +39,7 @@ module.exports = function(grunt) {
"src/osmtilesource.js",
"src/tmstilesource.js",
"src/legacytilesource.js",
+ "src/imagetilesource.js",
"src/tilesourcecollection.js",
"src/button.js",
"src/buttongroup.js",
diff --git a/src/imagetilesource.js b/src/imagetilesource.js
new file mode 100644
index 00000000..a7f025b3
--- /dev/null
+++ b/src/imagetilesource.js
@@ -0,0 +1,174 @@
+/*
+ * OpenSeadragon - ImageTileSource
+ *
+ * Copyright (C) 2009 CodePlex Foundation
+ * Copyright (C) 2010-2013 OpenSeadragon contributors
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of CodePlex Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function ($) {
+
+ /**
+ * @class ImageTileSource
+ * @classdesc The ImageTileSource allows simple image to be loaded
+ * into an OpenSeadragon Viewer.
+ *
+ * @memberof OpenSeadragon
+ * @extends OpenSeadragon.TileSource
+ * @param {Object} options Options object.
+ * @property {String} options.url URL of the image
+ */
+ $.ImageTileSource = function (options) {
+
+ $.TileSource.apply(this, [options]);
+
+ };
+
+ $.extend($.ImageTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.ImageTileSource.prototype */{
+ /**
+ * Determine if the data and/or url imply the image service is supported by
+ * this tile source.
+ * @function
+ * @param {Object|Array} data
+ * @param {String} optional - url
+ */
+ supports: function (data, url) {
+ return data.type && data.type === "image";
+ },
+ /**
+ *
+ * @function
+ * @param {Image} image - the actual image
+ * @param {String} dataUrl - the url the image was retreived from, if any.
+ * @return {Object} options - A dictionary of keyword arguments sufficient
+ * to configure this tile sources constructor.
+ */
+ configure: function (image, dataUrl) {
+ return image;
+ },
+ /**
+ * Responsible for retrieving, and caching the
+ * image metadata pertinent to this TileSources implementation.
+ * @function
+ * @param {String} url
+ * @throws {Error}
+ */
+ getImageInfo: function (url) {
+ var image = new Image();
+ var _this = this;
+
+ image.addEventListener('load', function () {
+ _this.width = image.naturalWidth;
+ _this.height = image.naturalHeight;
+ _this.aspectRatio = _this.width / _this.height;
+ _this.dimensions = new $.Point(_this.width, _this.height);
+ _this._tileWidth = _this.width;
+ _this._tileHeight = _this.height;
+ _this.tileOverlap = 0;
+ _this.minLevel = 0;
+ _this.maxLevel = 0;
+
+ _this.ready = true;
+ /**
+ * Raised when a TileSource is opened and initialized.
+ *
+ * @event ready
+ * @memberof OpenSeadragon.TileSource
+ * @type {object}
+ * @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
+ * @property {Object} tileSource
+ * @property {?Object} userData - Arbitrary subscriber-defined object.
+ */
+ _this.raiseEvent('ready', {tileSource: _this});
+ });
+
+ image.addEventListener('error', function () {
+ /***
+ * Raised when an error occurs loading a TileSource.
+ *
+ * @event open-failed
+ * @memberof OpenSeadragon.TileSource
+ * @type {object}
+ * @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
+ * @property {String} message
+ * @property {String} source
+ * @property {?Object} userData - Arbitrary subscriber-defined object.
+ */
+ _this.raiseEvent('open-failed', {
+ message: "Error loading image at " + url,
+ source: url
+ });
+ });
+
+ image.src = url;
+ },
+ /**
+ * @function
+ * @param {Number} level
+ */
+ getLevelScale: function (level) {
+ return level === 0 ? 1 : NaN;
+ },
+ /**
+ * @function
+ * @param {Number} level
+ */
+ getNumTiles: function (level) {
+ var scale = this.getLevelScale(level);
+ if (scale) {
+ return new $.Point(1, 1);
+ } else {
+ return new $.Point(0, 0);
+ }
+ },
+ /**
+ * @function
+ * @param {Number} level
+ * @param {OpenSeadragon.Point} point
+ */
+ getTileAtPoint: function (level, point) {
+ return new $.Point(0, 0);
+ },
+ /**
+ * This method is not implemented by this class other than to throw an Error
+ * announcing you have to implement it. Because of the variety of tile
+ * server technologies, and various specifications for building image
+ * pyramids, this method is here to allow easy integration.
+ * @function
+ * @param {Number} level
+ * @param {Number} x
+ * @param {Number} y
+ * @throws {Error}
+ */
+ getTileUrl: function (level, x, y) {
+ return this.url;
+ }
+ });
+
+}(OpenSeadragon));
diff --git a/src/viewer.js b/src/viewer.js
index d60b5320..c763cf68 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -2075,14 +2075,26 @@ function getTileSourceImplementation( viewer, tileSource, successCallback,
return;
}
var options = $TileSource.prototype.configure.apply( _this, [ tileSource ] );
- var readySource = new $TileSource( options );
- successCallback( readySource );
+ var readySource = new $TileSource(options);
+ if (readySource.ready) {
+ successCallback(readySource);
+ } else {
+ readySource.addHandler('ready', function () {
+ successCallback(readySource);
+ });
+ readySource.addHandler('open-failed', function (event) {
+ failCallback({
+ message: event.message,
+ source: tileSource
+ });
+ });
+ }
}
} else {
//can assume it's already a tile source implementation
successCallback( tileSource );
}
- }, 1 );
+ });
}
function getOverlayObject( viewer, overlay ) {
diff --git a/test/coverage.html b/test/coverage.html
index 65cc2818..dc857202 100644
--- a/test/coverage.html
+++ b/test/coverage.html
@@ -32,6 +32,7 @@
+
diff --git a/test/modules/formats.js b/test/modules/formats.js
index 2cef3576..5166f796 100644
--- a/test/modules/formats.js
+++ b/test/modules/formats.js
@@ -142,4 +142,12 @@
'}');
});
+ // ----------
+ asyncTest('ImageTileSource', function () {
+ testOpen({
+ type: "image",
+ url: "/test/data/A.png"
+ });
+ });
+
})();