Zoomify.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the Clear BSD license.
  3. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  4. * full text of the license. */
  5. /*
  6. * Development supported by a R&D grant DC08P02OUK006 - Old Maps Online
  7. * (www.oldmapsonline.org) from Ministry of Culture of the Czech Republic.
  8. */
  9. /**
  10. * @requires OpenLayers/Layer/Grid.js
  11. */
  12. /**
  13. * Class: OpenLayers.Layer.Zoomify
  14. *
  15. * Inherits from:
  16. * - <OpenLayers.Layer.Grid>
  17. */
  18. OpenLayers.Layer.Zoomify = OpenLayers.Class(OpenLayers.Layer.Grid, {
  19. /**
  20. * Property: url
  21. * {String} URL for root directory with TileGroupX subdirectories.
  22. */
  23. url: null,
  24. /**
  25. * Property: size
  26. * {<OpenLayers.Size>} The Zoomify image size in pixels.
  27. */
  28. size: null,
  29. /**
  30. * APIProperty: isBaseLayer
  31. * {Boolean}
  32. */
  33. isBaseLayer: true,
  34. /**
  35. * Property: standardTileSize
  36. * {Integer} The size of a standard (non-border) square tile in pixels.
  37. */
  38. standardTileSize: 256,
  39. /**
  40. * Property: tileOriginCorner
  41. * {String} This layer uses top-left as tile origin
  42. **/
  43. tileOriginCorner: "tl",
  44. /**
  45. * Property: numberOfTiers
  46. * {Integer} Depth of the Zoomify pyramid, number of tiers (zoom levels)
  47. * - filled during Zoomify pyramid initialization.
  48. */
  49. numberOfTiers: 0,
  50. /**
  51. * Property: tileCountUpToTier
  52. * {Array(Integer)} Number of tiles up to the given tier of pyramid.
  53. * - filled during Zoomify pyramid initialization.
  54. */
  55. tileCountUpToTier: new Array(),
  56. /**
  57. * Property: tierSizeInTiles
  58. * {Array(<OpenLayers.Size>)} Size (in tiles) for each tier of pyramid.
  59. * - filled during Zoomify pyramid initialization.
  60. */
  61. tierSizeInTiles: new Array(),
  62. /**
  63. * Property: tierImageSize
  64. * {Array(<OpenLayers.Size>)} Image size in pixels for each pyramid tier.
  65. * - filled during Zoomify pyramid initialization.
  66. */
  67. tierImageSize: new Array(),
  68. /**
  69. * Constructor: OpenLayers.Layer.Zoomify
  70. *
  71. * Parameters:
  72. * name - {String} A name for the layer.
  73. * url - {String} - Relative or absolute path to the image or more
  74. * precisly to the TileGroup[X] directories root.
  75. * Flash plugin use the variable name "zoomifyImagePath" for this.
  76. * size - {<OpenLayers.Size>} The size (in pixels) of the image.
  77. * options - {Object} Hashtable of extra options to tag onto the layer
  78. */
  79. initialize: function(name, url, size, options) {
  80. // initilize the Zoomify pyramid for given size
  81. this.initializeZoomify( size );
  82. var newArguments = [];
  83. newArguments.push(name, url, size, {}, options);
  84. OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
  85. },
  86. /**
  87. * Method: initializeZoomify
  88. * It generates constants for all tiers of the Zoomify pyramid
  89. *
  90. * Parameters:
  91. * size - {<OpenLayers.Size>} The size of the image in pixels
  92. *
  93. */
  94. initializeZoomify: function( size ) {
  95. var imageSize = size.clone();
  96. var tiles = new OpenLayers.Size(
  97. Math.ceil( imageSize.w / this.standardTileSize ),
  98. Math.ceil( imageSize.h / this.standardTileSize )
  99. );
  100. this.tierSizeInTiles.push( tiles );
  101. this.tierImageSize.push( imageSize );
  102. while (imageSize.w > this.standardTileSize ||
  103. imageSize.h > this.standardTileSize ) {
  104. imageSize = new OpenLayers.Size(
  105. Math.floor( imageSize.w / 2 ),
  106. Math.floor( imageSize.h / 2 )
  107. );
  108. tiles = new OpenLayers.Size(
  109. Math.ceil( imageSize.w / this.standardTileSize ),
  110. Math.ceil( imageSize.h / this.standardTileSize )
  111. );
  112. this.tierSizeInTiles.push( tiles );
  113. this.tierImageSize.push( imageSize );
  114. }
  115. this.tierSizeInTiles.reverse();
  116. this.tierImageSize.reverse();
  117. this.numberOfTiers = this.tierSizeInTiles.length;
  118. this.tileCountUpToTier[0] = 0;
  119. for (var i = 1; i < this.numberOfTiers; i++) {
  120. this.tileCountUpToTier.push(
  121. this.tierSizeInTiles[i-1].w * this.tierSizeInTiles[i-1].h +
  122. this.tileCountUpToTier[i-1]
  123. );
  124. }
  125. },
  126. /**
  127. * APIMethod:destroy
  128. */
  129. destroy: function() {
  130. // for now, nothing special to do here.
  131. OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
  132. // Remove from memory the Zoomify pyramid - is that enough?
  133. this.tileCountUpToTier.length = 0;
  134. this.tierSizeInTiles.length = 0;
  135. this.tierImageSize.length = 0;
  136. },
  137. /**
  138. * APIMethod: clone
  139. *
  140. * Parameters:
  141. * obj - {Object}
  142. *
  143. * Returns:
  144. * {<OpenLayers.Layer.Zoomify>} An exact clone of this <OpenLayers.Layer.Zoomify>
  145. */
  146. clone: function (obj) {
  147. if (obj == null) {
  148. obj = new OpenLayers.Layer.Zoomify(this.name,
  149. this.url,
  150. this.size,
  151. this.options);
  152. }
  153. //get all additions from superclasses
  154. obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
  155. // copy/set any non-init, non-simple values here
  156. return obj;
  157. },
  158. /**
  159. * Method: getURL
  160. *
  161. * Parameters:
  162. * bounds - {<OpenLayers.Bounds>}
  163. *
  164. * Returns:
  165. * {String} A string with the layer's url and parameters and also the
  166. * passed-in bounds and appropriate tile size specified as
  167. * parameters
  168. */
  169. getURL: function (bounds) {
  170. bounds = this.adjustBounds(bounds);
  171. var res = this.map.getResolution();
  172. var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
  173. var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
  174. var z = this.map.getZoom();
  175. var tileIndex = x + y * this.tierSizeInTiles[z].w + this.tileCountUpToTier[z];
  176. var path = "TileGroup" + Math.floor( (tileIndex) / 256 ) +
  177. "/" + z + "-" + x + "-" + y + ".jpg";
  178. var url = this.url;
  179. if (OpenLayers.Util.isArray(url)) {
  180. url = this.selectUrl(path, url);
  181. }
  182. return url + path;
  183. },
  184. /**
  185. * Method: getImageSize
  186. * getImageSize returns size for a particular tile. If bounds are given as
  187. * first argument, size is calculated (bottom-right tiles are non square).
  188. *
  189. */
  190. getImageSize: function() {
  191. if (arguments.length > 0) {
  192. var bounds = this.adjustBounds(arguments[0]);
  193. var res = this.map.getResolution();
  194. var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
  195. var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
  196. var z = this.map.getZoom();
  197. var w = this.standardTileSize;
  198. var h = this.standardTileSize;
  199. if (x == this.tierSizeInTiles[z].w -1 ) {
  200. var w = this.tierImageSize[z].w % this.standardTileSize;
  201. };
  202. if (y == this.tierSizeInTiles[z].h -1 ) {
  203. var h = this.tierImageSize[z].h % this.standardTileSize;
  204. };
  205. return (new OpenLayers.Size(w, h));
  206. } else {
  207. return this.tileSize;
  208. }
  209. },
  210. /**
  211. * APIMethod: setMap
  212. * When the layer is added to a map, then we can fetch our origin
  213. * (if we don't have one.)
  214. *
  215. * Parameters:
  216. * map - {<OpenLayers.Map>}
  217. */
  218. setMap: function(map) {
  219. OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
  220. this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
  221. this.map.maxExtent.top);
  222. },
  223. /**
  224. * Method: calculateGridLayout
  225. * Generate parameters for the grid layout. This
  226. *
  227. * Parameters:
  228. * bounds - {<OpenLayers.Bound>}
  229. * origin - {<OpenLayers.LonLat>}
  230. * resolution - {Number}
  231. *
  232. * Returns:
  233. * Object containing properties tilelon, tilelat, tileoffsetlat,
  234. * tileoffsetlat, tileoffsetx, tileoffsety
  235. */
  236. calculateGridLayout: function(bounds, origin, resolution) {
  237. var tilelon = resolution * this.tileSize.w;
  238. var tilelat = resolution * this.tileSize.h;
  239. var offsetlon = bounds.left - origin.lon;
  240. var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
  241. var tilecolremain = offsetlon/tilelon - tilecol;
  242. var tileoffsetx = -tilecolremain * this.tileSize.w;
  243. var tileoffsetlon = origin.lon + tilecol * tilelon;
  244. var offsetlat = origin.lat - bounds.top + tilelat;
  245. var tilerow = Math.floor(offsetlat/tilelat) - this.buffer;
  246. var tilerowremain = tilerow - offsetlat/tilelat;
  247. var tileoffsety = tilerowremain * this.tileSize.h;
  248. var tileoffsetlat = origin.lat - tilelat*tilerow;
  249. return {
  250. tilelon: tilelon, tilelat: tilelat,
  251. tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
  252. tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
  253. };
  254. },
  255. CLASS_NAME: "OpenLayers.Layer.Zoomify"
  256. });