openseadragon/src/dzitilesource.js

262 lines
7.8 KiB
JavaScript
Raw Normal View History

(function( $ ){
/**
* @class
*/
$.DziTileSource = function( width, height, tileSize, tileOverlap, tilesUrl, fileFormat, displayRects ) {
var i,
rect,
level;
$.TileSource.call( this, width, height, tileSize, tileOverlap, null, null );
this._levelRects = {};
this.tilesUrl = tilesUrl;
this.fileFormat = fileFormat;
this.displayRects = displayRects;
if ( this.displayRects ) {
for ( i = this.displayRects.length - 1; i >= 0; i-- ) {
rect = this.displayRects[ i ];
for ( level = rect.minLevel; level <= rect.maxLevel; level++ ) {
if ( !this._levelRects[ level ] ) {
this._levelRects[ level ] = [];
}
this._levelRects[ level ].push( rect );
}
}
}
};
$.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
getTileUrl: function( level, x, y ) {
return [ this.tilesUrl, level, '/', x, '_', y, '.', this.fileFormat ].join( '' );
},
tileExists: function( level, x, y ) {
var rects = this._levelRects[ level ],
rect,
scale,
xMin,
yMin,
xMax,
yMax,
i;
if ( !rects || !rects.length ) {
return true;
}
for ( i = rects.length - 1; i >= 0; i-- ) {
rect = rects[ i ];
if ( level < rect.minLevel || level > rect.maxLevel ) {
continue;
}
scale = this.getLevelScale( level );
xMin = rect.x * scale;
yMin = rect.y * scale;
xMax = xMin + rect.width * scale;
yMax = yMin + rect.height * scale;
xMin = Math.floor( xMin / this.tileSize );
yMin = Math.floor( yMin / this.tileSize );
xMax = Math.ceil( xMax / this.tileSize );
yMax = Math.ceil( yMax / this.tileSize );
if ( xMin <= x && x < xMax && yMin <= y && y < yMax ) {
return true;
}
}
return false;
}
});
/**
* @static
*/
$.DziTileSourceHelper = {
createFromXml: function( xmlUrl, xmlString, callback ) {
var async = typeof (callback) == "function",
error = null,
urlParts,
filename,
lastDot,
tilesUrl,
handler;
if ( !xmlUrl ) {
this.error = $.getString( "Errors.Empty" );
if ( async ) {
window.setTimeout( function() {
callback( null, error );
}, 1 );
return null;
}
throw new Error( error );
}
urlParts = xmlUrl.split( '/' );
filename = urlParts[ urlParts.length - 1 ];
lastDot = filename.lastIndexOf( '.' );
if ( lastDot > -1 ) {
urlParts[ urlParts.length - 1 ] = filename.slice( 0, lastDot );
}
tilesUrl = urlParts.join( '/' ) + "_files/";
function finish( func, obj ) {
try {
return func( obj, tilesUrl );
} catch ( e ) {
if ( async ) {
return null;
} else {
throw e;
}
}
}
if ( async ) {
if ( xmlString ) {
handler = $.delegate( this, this.processXml );
window.setTimeout( function() {
var source = finish( handler, $.parseXml( xmlString ) );
// call after finish sets error
callback( source, error );
}, 1);
} else {
handler = $.delegate( this, this.processResponse );
$.makeAjaxRequest( xmlUrl, function( xhr ) {
var source = finish( handler, xhr );
// call after finish sets error
callback( source, error );
});
}
return null;
}
if ( xmlString ) {
return finish(
$.delegate( this, this.processXml ),
$.parseXml( xmlString )
);
} else {
return finish(
$.delegate( this, this.processResponse ),
$.makeAjaxRequest( xmlUrl )
);
}
},
processResponse: function( xhr, tilesUrl ) {
var status,
statusText,
doc = null;
if ( !xhr ) {
throw new Error( $.getString( "Errors.Security" ) );
} else if ( xhr.status !== 200 && xhr.status !== 0 ) {
status = xhr.status;
statusText = ( status == 404 ) ?
"Not Found" :
xhr.statusText;
throw new Error( $.getString( "Errors.Status", status, statusText ) );
}
if ( xhr.responseXML && xhr.responseXML.documentElement ) {
doc = xhr.responseXML;
} else if ( xhr.responseText ) {
doc = $.parseXml( xhr.responseText );
}
return this.processXml( doc, tilesUrl );
},
processXml: function( xmlDoc, tilesUrl ) {
if ( !xmlDoc || !xmlDoc.documentElement ) {
throw new Error( $.getString( "Errors.Xml" ) );
}
var root = xmlDoc.documentElement,
rootName = root.tagName;
if ( rootName == "Image" ) {
try {
return this.processDzi( root, tilesUrl );
} catch ( e ) {
throw (e instanceof Error) ?
e :
new Error( $.getString("Errors.Dzi") );
}
} else if ( rootName == "Collection" ) {
throw new Error( $.getString( "Errors.Dzc" ) );
} else if ( rootName == "Error" ) {
return this.processError( root );
}
throw new Error( $.getString( "Errors.Dzi" ) );
},
processDzi: function( imageNode, tilesUrl ) {
var fileFormat = imageNode.getAttribute( "Format" ),
sizeNode = imageNode.getElementsByTagName( "Size" )[ 0 ],
dispRectNodes = imageNode.getElementsByTagName( "DisplayRect" ),
width = parseInt( sizeNode.getAttribute( "Width" ) ),
height = parseInt( sizeNode.getAttribute( "Height" ) ),
tileSize = parseInt( imageNode.getAttribute( "TileSize" ) ),
tileOverlap = parseInt( imageNode.getAttribute( "Overlap" ) ),
dispRects = [],
dispRectNode,
rectNode,
i;
if ( !$.imageFormatSupported( fileFormat ) ) {
throw new Error(
$.getString( "Errors.ImageFormat", fileFormat.toUpperCase() )
);
}
for ( i = 0; i < dispRectNodes.length; i++ ) {
dispRectNode = dispRectNodes[ i ];
rectNode = dispRectNode.getElementsByTagName( "Rect" )[ 0 ];
dispRects.push( new $.DisplayRect(
parseInt( rectNode.getAttribute( "X" ) ),
parseInt( rectNode.getAttribute( "Y" ) ),
parseInt( rectNode.getAttribute( "Width" ) ),
parseInt( rectNode.getAttribute( "Height" ) ),
0, // ignore MinLevel attribute, bug in Deep Zoom Composer
parseInt( dispRectNode.getAttribute( "MaxLevel" ) )
));
}
return new $.DziTileSource(
width,
height,
tileSize,
tileOverlap,
tilesUrl,
fileFormat,
dispRects
);
},
processError: function( errorNode ) {
var messageNode = errorNode.getElementsByTagName( "Message" )[ 0 ],
message = messageNode.firstChild.nodeValue;
throw new Error(message);
}
};
}( OpenSeadragon ));