mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-25 22:56:11 +03:00
Add IE8 support in ImageTileSource.
This commit is contained in:
parent
8e06eb56cf
commit
14a83e1154
@ -43,17 +43,23 @@
|
|||||||
* @extends OpenSeadragon.TileSource
|
* @extends OpenSeadragon.TileSource
|
||||||
* @param {Object} options Options object.
|
* @param {Object} options Options object.
|
||||||
* @property {String} options.url URL of the image
|
* @property {String} options.url URL of the image
|
||||||
* @property {Boolean} options.buildPyramid If set to true, a pyramid will
|
* @property {Boolean} options.buildPyramid If set to true (default), a
|
||||||
* be built internally to provide a better downsampling.
|
* pyramid will be built internally to provide a better downsampling.
|
||||||
* @property {String|Boolean} options.crossOriginPolicy Valid values are
|
* @property {String|Boolean} options.crossOriginPolicy Valid values are
|
||||||
* 'Anonymous', 'use-credentials', and false. If false, image requests will
|
* 'Anonymous', 'use-credentials', and false. If false, image requests will
|
||||||
* not use CORS preventing internal pyramid building for images from other
|
* not use CORS preventing internal pyramid building for images from other
|
||||||
* domains.
|
* domains.
|
||||||
* @property {String|Boolean} options.ajaxWithCredentials Whether to set the
|
* @property {String|Boolean} options.ajaxWithCredentials Whether to set the
|
||||||
* withCredentials XHR flag for AJAX requests (when loading tile sources)
|
* withCredentials XHR flag for AJAX requests (when loading tile sources)
|
||||||
|
* @property {Boolean} options.useCanvas Set to false to prevent any use of
|
||||||
|
* the canvas API.
|
||||||
*/
|
*/
|
||||||
$.ImageTileSource = function (options) {
|
$.ImageTileSource = function (options) {
|
||||||
|
|
||||||
|
$.extend(options, {
|
||||||
|
buildPyramid: true,
|
||||||
|
useCanvas: true
|
||||||
|
});
|
||||||
this.options = options;
|
this.options = options;
|
||||||
$.TileSource.apply(this, [options]);
|
$.TileSource.apply(this, [options]);
|
||||||
|
|
||||||
@ -99,7 +105,7 @@
|
|||||||
image.useCredentials = this.options.ajaxWithCredentials;
|
image.useCredentials = this.options.ajaxWithCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.addEventListener('load', function () {
|
$.addEvent(image, 'load', function () {
|
||||||
_this.width = image.naturalWidth;
|
_this.width = image.naturalWidth;
|
||||||
_this.height = image.naturalHeight;
|
_this.height = image.naturalHeight;
|
||||||
_this.aspectRatio = _this.width / _this.height;
|
_this.aspectRatio = _this.width / _this.height;
|
||||||
@ -112,7 +118,8 @@
|
|||||||
var pyramidMinWidth = _this.buildPyramid ? 1 : _this.width;
|
var pyramidMinWidth = _this.buildPyramid ? 1 : _this.width;
|
||||||
var pyramidMinHeight = _this.buildPyramid ? 1 : _this.height;
|
var pyramidMinHeight = _this.buildPyramid ? 1 : _this.height;
|
||||||
|
|
||||||
_this.levels = buildLevels(image, pyramidMinWidth, pyramidMinHeight);
|
_this.levels = _this._buildLevels(
|
||||||
|
image, pyramidMinWidth, pyramidMinHeight);
|
||||||
_this.maxLevel = _this.levels.length - 1;
|
_this.maxLevel = _this.levels.length - 1;
|
||||||
|
|
||||||
_this.ready = true;
|
_this.ready = true;
|
||||||
@ -122,21 +129,23 @@
|
|||||||
* @event ready
|
* @event ready
|
||||||
* @memberof OpenSeadragon.TileSource
|
* @memberof OpenSeadragon.TileSource
|
||||||
* @type {object}
|
* @type {object}
|
||||||
* @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
|
* @property {OpenSeadragon.TileSource} eventSource - A reference
|
||||||
|
* to the TileSource which raised the event.
|
||||||
* @property {Object} tileSource
|
* @property {Object} tileSource
|
||||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
*/
|
*/
|
||||||
_this.raiseEvent('ready', {tileSource: _this});
|
_this.raiseEvent('ready', {tileSource: _this});
|
||||||
});
|
});
|
||||||
|
|
||||||
image.addEventListener('error', function () {
|
$.addEvent(image, 'error', function () {
|
||||||
/***
|
/***
|
||||||
* Raised when an error occurs loading a TileSource.
|
* Raised when an error occurs loading a TileSource.
|
||||||
*
|
*
|
||||||
* @event open-failed
|
* @event open-failed
|
||||||
* @memberof OpenSeadragon.TileSource
|
* @memberof OpenSeadragon.TileSource
|
||||||
* @type {object}
|
* @type {object}
|
||||||
* @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
|
* @property {OpenSeadragon.TileSource} eventSource - A reference
|
||||||
|
* to the TileSource which raised the event.
|
||||||
* @property {String} message
|
* @property {String} message
|
||||||
* @property {String} source
|
* @property {String} source
|
||||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
@ -183,15 +192,11 @@
|
|||||||
return new $.Point(0, 0);
|
return new $.Point(0, 0);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* This method is not implemented by this class other than to throw an Error
|
* Retrieves a tile url
|
||||||
* 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
|
* @function
|
||||||
* @param {Number} level
|
* @param {Number} level Level of the tile
|
||||||
* @param {Number} x
|
* @param {Number} x x coordinate of the tile
|
||||||
* @param {Number} y
|
* @param {Number} y y coordinate of the tile
|
||||||
* @throws {Error}
|
|
||||||
*/
|
*/
|
||||||
getTileUrl: function (level, x, y) {
|
getTileUrl: function (level, x, y) {
|
||||||
var url = null;
|
var url = null;
|
||||||
@ -199,76 +204,71 @@
|
|||||||
url = this.levels[level].url;
|
url = this.levels[level].url;
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
},
|
||||||
});
|
/**
|
||||||
|
* @private Build the differents levels of the pyramid if possible
|
||||||
|
* (canvas API enabled and no canvas tainting issue)
|
||||||
|
*/
|
||||||
|
_buildLevels: function (image, minWidth, minHeight) {
|
||||||
|
var levels = [{
|
||||||
|
url: image.src,
|
||||||
|
width: image.naturalWidth,
|
||||||
|
height: image.naturalHeight
|
||||||
|
}];
|
||||||
|
|
||||||
function buildLevels(image, minWidth, minHeight) {
|
if (!$.supportsCanvas || !this.useCanvas) {
|
||||||
var levels = [{
|
return levels;
|
||||||
url: image.src,
|
}
|
||||||
width: image.naturalWidth,
|
|
||||||
height: image.naturalHeight
|
|
||||||
}];
|
|
||||||
|
|
||||||
var currentWidth = Math.floor(image.naturalWidth / 2);
|
var currentWidth = Math.floor(image.naturalWidth / 2);
|
||||||
var currentHeight = Math.floor(image.naturalHeight / 2);
|
var currentHeight = Math.floor(image.naturalHeight / 2);
|
||||||
|
|
||||||
if (currentWidth < minWidth || currentHeight < minHeight) {
|
if (currentWidth < minWidth || currentHeight < minHeight) {
|
||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bigCanvas = document.createElement("canvas");
|
var bigCanvas = document.createElement("canvas");
|
||||||
var bigContext = bigCanvas.getContext("2d");
|
var bigContext = bigCanvas.getContext("2d");
|
||||||
|
|
||||||
bigCanvas.width = currentWidth;
|
bigCanvas.width = currentWidth;
|
||||||
bigCanvas.height = currentHeight;
|
bigCanvas.height = currentHeight;
|
||||||
bigContext.drawImage(image, 0, 0, currentWidth, currentHeight);
|
bigContext.drawImage(image, 0, 0, currentWidth, currentHeight);
|
||||||
|
|
||||||
if (isCanvasTainted(bigContext)) {
|
|
||||||
// If the canvas is tainted, we can't compute the pyramid.
|
|
||||||
return levels;
|
|
||||||
}
|
|
||||||
levels.splice(0, 0, {
|
|
||||||
url: bigCanvas.toDataURL(),
|
|
||||||
width: currentWidth,
|
|
||||||
height: currentHeight
|
|
||||||
});
|
|
||||||
|
|
||||||
var smallCanvas = document.createElement("canvas");
|
|
||||||
var smallContext = smallCanvas.getContext("2d");
|
|
||||||
while (currentWidth >= minWidth * 2 && currentHeight >= minHeight * 2) {
|
|
||||||
currentWidth = Math.floor(currentWidth / 2);
|
|
||||||
currentHeight = Math.floor(currentHeight / 2);
|
|
||||||
smallCanvas.width = currentWidth;
|
|
||||||
smallCanvas.height = currentHeight;
|
|
||||||
smallContext.drawImage(bigCanvas, 0, 0, currentWidth, currentHeight);
|
|
||||||
|
|
||||||
|
if ($.isCanvasTainted(bigContext.canvas)) {
|
||||||
|
// If the canvas is tainted, we can't compute the pyramid.
|
||||||
|
return levels;
|
||||||
|
}
|
||||||
levels.splice(0, 0, {
|
levels.splice(0, 0, {
|
||||||
url: smallCanvas.toDataURL(),
|
url: bigCanvas.toDataURL(),
|
||||||
width: currentWidth,
|
width: currentWidth,
|
||||||
height: currentHeight
|
height: currentHeight
|
||||||
});
|
});
|
||||||
|
|
||||||
var tempCanvas = bigCanvas;
|
var smallCanvas = document.createElement("canvas");
|
||||||
bigCanvas = smallCanvas;
|
var smallContext = smallCanvas.getContext("2d");
|
||||||
smallCanvas = tempCanvas;
|
while (currentWidth >= minWidth * 2 && currentHeight >= minHeight * 2) {
|
||||||
|
currentWidth = Math.floor(currentWidth / 2);
|
||||||
|
currentHeight = Math.floor(currentHeight / 2);
|
||||||
|
smallCanvas.width = currentWidth;
|
||||||
|
smallCanvas.height = currentHeight;
|
||||||
|
smallContext.drawImage(bigCanvas, 0, 0, currentWidth, currentHeight);
|
||||||
|
|
||||||
var tempContext = bigContext;
|
levels.splice(0, 0, {
|
||||||
bigContext = smallContext;
|
url: smallCanvas.toDataURL(),
|
||||||
smallContext = tempContext;
|
width: currentWidth,
|
||||||
}
|
height: currentHeight
|
||||||
return levels;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function isCanvasTainted(context) {
|
var tempCanvas = bigCanvas;
|
||||||
var isTainted = false;
|
bigCanvas = smallCanvas;
|
||||||
try {
|
smallCanvas = tempCanvas;
|
||||||
// We test if the canvas is tainted by retrieving data from it.
|
|
||||||
// An exception will be raised if the canvas is tainted.
|
var tempContext = bigContext;
|
||||||
var data = context.getImageData(0, 0, 1, 1);
|
bigContext = smallContext;
|
||||||
} catch (e) {
|
smallContext = tempContext;
|
||||||
isTainted = true;
|
}
|
||||||
|
return levels;
|
||||||
}
|
}
|
||||||
return isTainted;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
}(OpenSeadragon));
|
}(OpenSeadragon));
|
||||||
|
@ -839,6 +839,23 @@ if (typeof define === 'function' && define.amd) {
|
|||||||
canvasElement.getContext( '2d' ) );
|
canvasElement.getContext( '2d' ) );
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the submitted canvas is tainted or not.
|
||||||
|
* @argument {Canvas} canvas The canvas to test.
|
||||||
|
* @returns {Boolean} True if the canvas is tainted.
|
||||||
|
*/
|
||||||
|
$.isCanvasTainted = function(canvas) {
|
||||||
|
var isTainted = false;
|
||||||
|
try {
|
||||||
|
// We test if the canvas is tainted by retrieving data from it.
|
||||||
|
// An exception will be raised if the canvas is tainted.
|
||||||
|
var data = canvas.getContext('2d').getImageData(0, 0, 1, 1);
|
||||||
|
} catch (e) {
|
||||||
|
isTainted = true;
|
||||||
|
}
|
||||||
|
return isTainted;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density. Defaults to 1 if canvas isn't supported by the browser.
|
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density. Defaults to 1 if canvas isn't supported by the browser.
|
||||||
* @member {Number} pixelDensityRatio
|
* @member {Number} pixelDensityRatio
|
||||||
|
@ -2047,6 +2047,7 @@ function getTileSourceImplementation( viewer, tileSource, successCallback,
|
|||||||
url: tileSource,
|
url: tileSource,
|
||||||
crossOriginPolicy: viewer.crossOriginPolicy,
|
crossOriginPolicy: viewer.crossOriginPolicy,
|
||||||
ajaxWithCredentials: viewer.ajaxWithCredentials,
|
ajaxWithCredentials: viewer.ajaxWithCredentials,
|
||||||
|
useCanvas: viewer.useCanvas,
|
||||||
success: function( event ) {
|
success: function( event ) {
|
||||||
successCallback( event.tileSource );
|
successCallback( event.tileSource );
|
||||||
}
|
}
|
||||||
@ -2062,6 +2063,9 @@ function getTileSourceImplementation( viewer, tileSource, successCallback,
|
|||||||
if (tileSource.ajaxWithCredentials === undefined) {
|
if (tileSource.ajaxWithCredentials === undefined) {
|
||||||
tileSource.ajaxWithCredentials = viewer.ajaxWithCredentials;
|
tileSource.ajaxWithCredentials = viewer.ajaxWithCredentials;
|
||||||
}
|
}
|
||||||
|
if (tileSource.useCanvas === undefined) {
|
||||||
|
tileSource.useCanvas = viewer.useCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $.isFunction( tileSource.getTileUrl ) ) {
|
if ( $.isFunction( tileSource.getTileUrl ) ) {
|
||||||
//Custom tile source
|
//Custom tile source
|
||||||
|
Loading…
Reference in New Issue
Block a user