GoogleEarthEnterpriseImageryProvider.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. import Credit from "../Core/Credit.js";
  2. import decodeGoogleEarthEnterpriseData from "../Core/decodeGoogleEarthEnterpriseData.js";
  3. import defaultValue from "../Core/defaultValue.js";
  4. import defined from "../Core/defined.js";
  5. import DeveloperError from "../Core/DeveloperError.js";
  6. import Event from "../Core/Event.js";
  7. import GeographicTilingScheme from "../Core/GeographicTilingScheme.js";
  8. import GoogleEarthEnterpriseMetadata from "../Core/GoogleEarthEnterpriseMetadata.js";
  9. import loadImageFromTypedArray from "../Core/loadImageFromTypedArray.js";
  10. import CesiumMath from "../Core/Math.js";
  11. import Rectangle from "../Core/Rectangle.js";
  12. import Request from "../Core/Request.js";
  13. import Resource from "../Core/Resource.js";
  14. import RuntimeError from "../Core/RuntimeError.js";
  15. import TileProviderError from "../Core/TileProviderError.js";
  16. import protobuf from "../ThirdParty/protobuf-minimal.js";
  17. import when from "../ThirdParty/when.js";
  18. /**
  19. * @private
  20. */
  21. function GoogleEarthEnterpriseDiscardPolicy() {
  22. this._image = new Image();
  23. }
  24. /**
  25. * Determines if the discard policy is ready to process images.
  26. * @returns {Boolean} True if the discard policy is ready to process images; otherwise, false.
  27. */
  28. GoogleEarthEnterpriseDiscardPolicy.prototype.isReady = function () {
  29. return true;
  30. };
  31. /**
  32. * Given a tile image, decide whether to discard that image.
  33. *
  34. * @param {HTMLImageElement} image An image to test.
  35. * @returns {Boolean} True if the image should be discarded; otherwise, false.
  36. */
  37. GoogleEarthEnterpriseDiscardPolicy.prototype.shouldDiscardImage = function (
  38. image
  39. ) {
  40. return image === this._image;
  41. };
  42. /**
  43. * @typedef {Object} GoogleEarthEnterpriseImageryProvider.ConstructorOptions
  44. *
  45. * Initialization options for the GoogleEarthEnterpriseImageryProvider constructor
  46. *
  47. * @property {Resource|String} url The url of the Google Earth Enterprise server hosting the imagery.
  48. * @property {GoogleEarthEnterpriseMetadata} metadata A metadata object that can be used to share metadata requests with a GoogleEarthEnterpriseTerrainProvider.
  49. * @property {Ellipsoid} [ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
  50. * @property {TileDiscardPolicy} [tileDiscardPolicy] The policy that determines if a tile
  51. * is invalid and should be discarded. If this value is not specified, a default
  52. * is to discard tiles that fail to download.
  53. * @property {Credit|String} [credit] A credit for the data source, which is displayed on the canvas.
  54. */
  55. /**
  56. * Provides tiled imagery using the Google Earth Enterprise REST API.
  57. *
  58. * Notes: This provider is for use with the 3D Earth API of Google Earth Enterprise,
  59. * {@link GoogleEarthEnterpriseMapsProvider} should be used with 2D Maps API.
  60. *
  61. * @alias GoogleEarthEnterpriseImageryProvider
  62. * @constructor
  63. *
  64. * @param {GoogleEarthEnterpriseImageryProvider.ConstructorOptions} options Object describing initialization options
  65. *
  66. * @see GoogleEarthEnterpriseTerrainProvider
  67. * @see ArcGisMapServerImageryProvider
  68. * @see GoogleEarthEnterpriseMapsProvider
  69. * @see OpenStreetMapImageryProvider
  70. * @see SingleTileImageryProvider
  71. * @see TileMapServiceImageryProvider
  72. * @see WebMapServiceImageryProvider
  73. * @see WebMapTileServiceImageryProvider
  74. * @see UrlTemplateImageryProvider
  75. *
  76. *
  77. * @example
  78. * var geeMetadata = new GoogleEarthEnterpriseMetadata('http://www.earthenterprise.org/3d');
  79. * var gee = new Cesium.GoogleEarthEnterpriseImageryProvider({
  80. * metadata : geeMetadata
  81. * });
  82. *
  83. * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
  84. */
  85. function GoogleEarthEnterpriseImageryProvider(options) {
  86. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  87. //>>includeStart('debug', pragmas.debug);
  88. if (!(defined(options.url) || defined(options.metadata))) {
  89. throw new DeveloperError("options.url or options.metadata is required.");
  90. }
  91. //>>includeEnd('debug');
  92. /**
  93. * The default alpha blending value of this provider, with 0.0 representing fully transparent and
  94. * 1.0 representing fully opaque.
  95. *
  96. * @type {Number|undefined}
  97. * @default undefined
  98. */
  99. this.defaultAlpha = undefined;
  100. /**
  101. * The default alpha blending value on the night side of the globe of this provider, with 0.0 representing fully transparent and
  102. * 1.0 representing fully opaque.
  103. *
  104. * @type {Number|undefined}
  105. * @default undefined
  106. */
  107. this.defaultNightAlpha = undefined;
  108. /**
  109. * The default alpha blending value on the day side of the globe of this provider, with 0.0 representing fully transparent and
  110. * 1.0 representing fully opaque.
  111. *
  112. * @type {Number|undefined}
  113. * @default undefined
  114. */
  115. this.defaultDayAlpha = undefined;
  116. /**
  117. * The default brightness of this provider. 1.0 uses the unmodified imagery color. Less than 1.0
  118. * makes the imagery darker while greater than 1.0 makes it brighter.
  119. *
  120. * @type {Number|undefined}
  121. * @default undefined
  122. */
  123. this.defaultBrightness = undefined;
  124. /**
  125. * The default contrast of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces
  126. * the contrast while greater than 1.0 increases it.
  127. *
  128. * @type {Number|undefined}
  129. * @default undefined
  130. */
  131. this.defaultContrast = undefined;
  132. /**
  133. * The default hue of this provider in radians. 0.0 uses the unmodified imagery color.
  134. *
  135. * @type {Number|undefined}
  136. * @default undefined
  137. */
  138. this.defaultHue = undefined;
  139. /**
  140. * The default saturation of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces the
  141. * saturation while greater than 1.0 increases it.
  142. *
  143. * @type {Number|undefined}
  144. * @default undefined
  145. */
  146. this.defaultSaturation = undefined;
  147. /**
  148. * The default gamma correction to apply to this provider. 1.0 uses the unmodified imagery color.
  149. *
  150. * @type {Number|undefined}
  151. * @default undefined
  152. */
  153. this.defaultGamma = undefined;
  154. /**
  155. * The default texture minification filter to apply to this provider.
  156. *
  157. * @type {TextureMinificationFilter}
  158. * @default undefined
  159. */
  160. this.defaultMinificationFilter = undefined;
  161. /**
  162. * The default texture magnification filter to apply to this provider.
  163. *
  164. * @type {TextureMagnificationFilter}
  165. * @default undefined
  166. */
  167. this.defaultMagnificationFilter = undefined;
  168. var metadata;
  169. if (defined(options.metadata)) {
  170. metadata = options.metadata;
  171. } else {
  172. var resource = Resource.createIfNeeded(options.url);
  173. metadata = new GoogleEarthEnterpriseMetadata(resource);
  174. }
  175. this._metadata = metadata;
  176. this._tileDiscardPolicy = options.tileDiscardPolicy;
  177. this._tilingScheme = new GeographicTilingScheme({
  178. numberOfLevelZeroTilesX: 2,
  179. numberOfLevelZeroTilesY: 2,
  180. rectangle: new Rectangle(
  181. -CesiumMath.PI,
  182. -CesiumMath.PI,
  183. CesiumMath.PI,
  184. CesiumMath.PI
  185. ),
  186. ellipsoid: options.ellipsoid,
  187. });
  188. var credit = options.credit;
  189. if (typeof credit === "string") {
  190. credit = new Credit(credit);
  191. }
  192. this._credit = credit;
  193. this._tileWidth = 256;
  194. this._tileHeight = 256;
  195. this._maximumLevel = 23;
  196. // Install the default tile discard policy if none has been supplied.
  197. if (!defined(this._tileDiscardPolicy)) {
  198. this._tileDiscardPolicy = new GoogleEarthEnterpriseDiscardPolicy();
  199. }
  200. this._errorEvent = new Event();
  201. this._ready = false;
  202. var that = this;
  203. var metadataError;
  204. this._readyPromise = metadata.readyPromise
  205. .then(function (result) {
  206. if (!metadata.imageryPresent) {
  207. var e = new RuntimeError(
  208. "The server " + metadata.url + " doesn't have imagery"
  209. );
  210. metadataError = TileProviderError.handleError(
  211. metadataError,
  212. that,
  213. that._errorEvent,
  214. e.message,
  215. undefined,
  216. undefined,
  217. undefined,
  218. e
  219. );
  220. return when.reject(e);
  221. }
  222. TileProviderError.handleSuccess(metadataError);
  223. that._ready = result;
  224. return result;
  225. })
  226. .otherwise(function (e) {
  227. metadataError = TileProviderError.handleError(
  228. metadataError,
  229. that,
  230. that._errorEvent,
  231. e.message,
  232. undefined,
  233. undefined,
  234. undefined,
  235. e
  236. );
  237. return when.reject(e);
  238. });
  239. }
  240. Object.defineProperties(GoogleEarthEnterpriseImageryProvider.prototype, {
  241. /**
  242. * Gets the name of the Google Earth Enterprise server url hosting the imagery.
  243. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  244. * @type {String}
  245. * @readonly
  246. */
  247. url: {
  248. get: function () {
  249. return this._metadata.url;
  250. },
  251. },
  252. /**
  253. * Gets the proxy used by this provider.
  254. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  255. * @type {Proxy}
  256. * @readonly
  257. */
  258. proxy: {
  259. get: function () {
  260. return this._metadata.proxy;
  261. },
  262. },
  263. /**
  264. * Gets the width of each tile, in pixels. This function should
  265. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  266. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  267. * @type {Number}
  268. * @readonly
  269. */
  270. tileWidth: {
  271. get: function () {
  272. //>>includeStart('debug', pragmas.debug);
  273. if (!this._ready) {
  274. throw new DeveloperError(
  275. "tileWidth must not be called before the imagery provider is ready."
  276. );
  277. }
  278. //>>includeEnd('debug');
  279. return this._tileWidth;
  280. },
  281. },
  282. /**
  283. * Gets the height of each tile, in pixels. This function should
  284. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  285. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  286. * @type {Number}
  287. * @readonly
  288. */
  289. tileHeight: {
  290. get: function () {
  291. //>>includeStart('debug', pragmas.debug);
  292. if (!this._ready) {
  293. throw new DeveloperError(
  294. "tileHeight must not be called before the imagery provider is ready."
  295. );
  296. }
  297. //>>includeEnd('debug');
  298. return this._tileHeight;
  299. },
  300. },
  301. /**
  302. * Gets the maximum level-of-detail that can be requested. This function should
  303. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  304. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  305. * @type {Number|undefined}
  306. * @readonly
  307. */
  308. maximumLevel: {
  309. get: function () {
  310. //>>includeStart('debug', pragmas.debug);
  311. if (!this._ready) {
  312. throw new DeveloperError(
  313. "maximumLevel must not be called before the imagery provider is ready."
  314. );
  315. }
  316. //>>includeEnd('debug');
  317. return this._maximumLevel;
  318. },
  319. },
  320. /**
  321. * Gets the minimum level-of-detail that can be requested. This function should
  322. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  323. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  324. * @type {Number}
  325. * @readonly
  326. */
  327. minimumLevel: {
  328. get: function () {
  329. //>>includeStart('debug', pragmas.debug);
  330. if (!this._ready) {
  331. throw new DeveloperError(
  332. "minimumLevel must not be called before the imagery provider is ready."
  333. );
  334. }
  335. //>>includeEnd('debug');
  336. return 0;
  337. },
  338. },
  339. /**
  340. * Gets the tiling scheme used by this provider. This function should
  341. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  342. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  343. * @type {TilingScheme}
  344. * @readonly
  345. */
  346. tilingScheme: {
  347. get: function () {
  348. //>>includeStart('debug', pragmas.debug);
  349. if (!this._ready) {
  350. throw new DeveloperError(
  351. "tilingScheme must not be called before the imagery provider is ready."
  352. );
  353. }
  354. //>>includeEnd('debug');
  355. return this._tilingScheme;
  356. },
  357. },
  358. /**
  359. * Gets the rectangle, in radians, of the imagery provided by this instance. This function should
  360. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  361. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  362. * @type {Rectangle}
  363. * @readonly
  364. */
  365. rectangle: {
  366. get: function () {
  367. //>>includeStart('debug', pragmas.debug);
  368. if (!this._ready) {
  369. throw new DeveloperError(
  370. "rectangle must not be called before the imagery provider is ready."
  371. );
  372. }
  373. //>>includeEnd('debug');
  374. return this._tilingScheme.rectangle;
  375. },
  376. },
  377. /**
  378. * Gets the tile discard policy. If not undefined, the discard policy is responsible
  379. * for filtering out "missing" tiles via its shouldDiscardImage function. If this function
  380. * returns undefined, no tiles are filtered. This function should
  381. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  382. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  383. * @type {TileDiscardPolicy}
  384. * @readonly
  385. */
  386. tileDiscardPolicy: {
  387. get: function () {
  388. //>>includeStart('debug', pragmas.debug);
  389. if (!this._ready) {
  390. throw new DeveloperError(
  391. "tileDiscardPolicy must not be called before the imagery provider is ready."
  392. );
  393. }
  394. //>>includeEnd('debug');
  395. return this._tileDiscardPolicy;
  396. },
  397. },
  398. /**
  399. * Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
  400. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  401. * are passed an instance of {@link TileProviderError}.
  402. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  403. * @type {Event}
  404. * @readonly
  405. */
  406. errorEvent: {
  407. get: function () {
  408. return this._errorEvent;
  409. },
  410. },
  411. /**
  412. * Gets a value indicating whether or not the provider is ready for use.
  413. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  414. * @type {Boolean}
  415. * @readonly
  416. */
  417. ready: {
  418. get: function () {
  419. return this._ready;
  420. },
  421. },
  422. /**
  423. * Gets a promise that resolves to true when the provider is ready for use.
  424. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  425. * @type {Promise.<Boolean>}
  426. * @readonly
  427. */
  428. readyPromise: {
  429. get: function () {
  430. return this._readyPromise;
  431. },
  432. },
  433. /**
  434. * Gets the credit to display when this imagery provider is active. Typically this is used to credit
  435. * the source of the imagery. This function should not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  436. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  437. * @type {Credit}
  438. * @readonly
  439. */
  440. credit: {
  441. get: function () {
  442. return this._credit;
  443. },
  444. },
  445. /**
  446. * Gets a value indicating whether or not the images provided by this imagery provider
  447. * include an alpha channel. If this property is false, an alpha channel, if present, will
  448. * be ignored. If this property is true, any images without an alpha channel will be treated
  449. * as if their alpha is 1.0 everywhere. Setting this property to false reduces memory usage
  450. * and texture upload time.
  451. * @memberof GoogleEarthEnterpriseImageryProvider.prototype
  452. * @type {Boolean}
  453. * @readonly
  454. */
  455. hasAlphaChannel: {
  456. get: function () {
  457. return false;
  458. },
  459. },
  460. });
  461. /**
  462. * Gets the credits to be displayed when a given tile is displayed.
  463. *
  464. * @param {Number} x The tile X coordinate.
  465. * @param {Number} y The tile Y coordinate.
  466. * @param {Number} level The tile level;
  467. * @returns {Credit[]} The credits to be displayed when the tile is displayed.
  468. *
  469. * @exception {DeveloperError} <code>getTileCredits</code> must not be called before the imagery provider is ready.
  470. */
  471. GoogleEarthEnterpriseImageryProvider.prototype.getTileCredits = function (
  472. x,
  473. y,
  474. level
  475. ) {
  476. //>>includeStart('debug', pragmas.debug);
  477. if (!this._ready) {
  478. throw new DeveloperError(
  479. "getTileCredits must not be called before the imagery provider is ready."
  480. );
  481. }
  482. //>>includeEnd('debug');
  483. var metadata = this._metadata;
  484. var info = metadata.getTileInformation(x, y, level);
  485. if (defined(info)) {
  486. var credit = metadata.providers[info.imageryProvider];
  487. if (defined(credit)) {
  488. return [credit];
  489. }
  490. }
  491. return undefined;
  492. };
  493. /**
  494. * Requests the image for a given tile. This function should
  495. * not be called before {@link GoogleEarthEnterpriseImageryProvider#ready} returns true.
  496. *
  497. * @param {Number} x The tile X coordinate.
  498. * @param {Number} y The tile Y coordinate.
  499. * @param {Number} level The tile level.
  500. * @param {Request} [request] The request object. Intended for internal use only.
  501. * @returns {Promise.<HTMLImageElement|HTMLCanvasElement>|undefined} A promise for the image that will resolve when the image is available, or
  502. * undefined if there are too many active requests to the server, and the request
  503. * should be retried later. The resolved image may be either an
  504. * Image or a Canvas DOM object.
  505. *
  506. * @exception {DeveloperError} <code>requestImage</code> must not be called before the imagery provider is ready.
  507. */
  508. GoogleEarthEnterpriseImageryProvider.prototype.requestImage = function (
  509. x,
  510. y,
  511. level,
  512. request
  513. ) {
  514. //>>includeStart('debug', pragmas.debug);
  515. if (!this._ready) {
  516. throw new DeveloperError(
  517. "requestImage must not be called before the imagery provider is ready."
  518. );
  519. }
  520. //>>includeEnd('debug');
  521. var invalidImage = this._tileDiscardPolicy._image; // Empty image or undefined depending on discard policy
  522. var metadata = this._metadata;
  523. var quadKey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);
  524. var info = metadata.getTileInformation(x, y, level);
  525. if (!defined(info)) {
  526. if (metadata.isValid(quadKey)) {
  527. var metadataRequest = new Request({
  528. throttle: request.throttle,
  529. throttleByServer: request.throttleByServer,
  530. type: request.type,
  531. priorityFunction: request.priorityFunction,
  532. });
  533. metadata.populateSubtree(x, y, level, metadataRequest);
  534. return undefined; // No metadata so return undefined so we can be loaded later
  535. }
  536. return invalidImage; // Image doesn't exist
  537. }
  538. if (!info.hasImagery()) {
  539. // Already have info and there isn't any imagery here
  540. return invalidImage;
  541. }
  542. var promise = buildImageResource(
  543. this,
  544. info,
  545. x,
  546. y,
  547. level,
  548. request
  549. ).fetchArrayBuffer();
  550. if (!defined(promise)) {
  551. return undefined; // Throttled
  552. }
  553. return promise.then(function (image) {
  554. decodeGoogleEarthEnterpriseData(metadata.key, image);
  555. var a = new Uint8Array(image);
  556. var type;
  557. var protoImagery = metadata.protoImagery;
  558. if (!defined(protoImagery) || !protoImagery) {
  559. type = getImageType(a);
  560. }
  561. if (!defined(type) && (!defined(protoImagery) || protoImagery)) {
  562. var message = decodeEarthImageryPacket(a);
  563. type = message.imageType;
  564. a = message.imageData;
  565. }
  566. if (!defined(type) || !defined(a)) {
  567. return invalidImage;
  568. }
  569. return loadImageFromTypedArray({
  570. uint8Array: a,
  571. format: type,
  572. flipY: true,
  573. });
  574. });
  575. };
  576. /**
  577. * Picking features is not currently supported by this imagery provider, so this function simply returns
  578. * undefined.
  579. *
  580. * @param {Number} x The tile X coordinate.
  581. * @param {Number} y The tile Y coordinate.
  582. * @param {Number} level The tile level.
  583. * @param {Number} longitude The longitude at which to pick features.
  584. * @param {Number} latitude The latitude at which to pick features.
  585. * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
  586. * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo}
  587. * instances. The array may be empty if no features are found at the given location.
  588. * It may also be undefined if picking is not supported.
  589. */
  590. GoogleEarthEnterpriseImageryProvider.prototype.pickFeatures = function (
  591. x,
  592. y,
  593. level,
  594. longitude,
  595. latitude
  596. ) {
  597. return undefined;
  598. };
  599. //
  600. // Functions to handle imagery packets
  601. //
  602. function buildImageResource(imageryProvider, info, x, y, level, request) {
  603. var quadKey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);
  604. var version = info.imageryVersion;
  605. version = defined(version) && version > 0 ? version : 1;
  606. return imageryProvider._metadata.resource.getDerivedResource({
  607. url: "flatfile?f1-0" + quadKey + "-i." + version.toString(),
  608. request: request,
  609. });
  610. }
  611. // Detects if a Uint8Array is a JPEG or PNG
  612. function getImageType(image) {
  613. var jpeg = "JFIF";
  614. if (
  615. image[6] === jpeg.charCodeAt(0) &&
  616. image[7] === jpeg.charCodeAt(1) &&
  617. image[8] === jpeg.charCodeAt(2) &&
  618. image[9] === jpeg.charCodeAt(3)
  619. ) {
  620. return "image/jpeg";
  621. }
  622. var png = "PNG";
  623. if (
  624. image[1] === png.charCodeAt(0) &&
  625. image[2] === png.charCodeAt(1) &&
  626. image[3] === png.charCodeAt(2)
  627. ) {
  628. return "image/png";
  629. }
  630. return undefined;
  631. }
  632. // Decodes an Imagery protobuf into the message
  633. // Partially generated with the help of protobuf.js static generator
  634. function decodeEarthImageryPacket(data) {
  635. var reader = protobuf.Reader.create(data);
  636. var end = reader.len;
  637. var message = {};
  638. while (reader.pos < end) {
  639. var tag = reader.uint32();
  640. switch (tag >>> 3) {
  641. case 1:
  642. message.imageType = reader.uint32();
  643. break;
  644. case 2:
  645. message.imageData = reader.bytes();
  646. break;
  647. case 3:
  648. message.alphaType = reader.uint32();
  649. break;
  650. case 4:
  651. message.imageAlpha = reader.bytes();
  652. break;
  653. case 5:
  654. var copyrightIds = message.copyrightIds;
  655. if (!defined(copyrightIds)) {
  656. copyrightIds = message.copyrightIds = [];
  657. }
  658. if ((tag & 7) === 2) {
  659. var end2 = reader.uint32() + reader.pos;
  660. while (reader.pos < end2) {
  661. copyrightIds.push(reader.uint32());
  662. }
  663. } else {
  664. copyrightIds.push(reader.uint32());
  665. }
  666. break;
  667. default:
  668. reader.skipType(tag & 7);
  669. break;
  670. }
  671. }
  672. var imageType = message.imageType;
  673. if (defined(imageType)) {
  674. switch (imageType) {
  675. case 0:
  676. message.imageType = "image/jpeg";
  677. break;
  678. case 4:
  679. message.imageType = "image/png";
  680. break;
  681. default:
  682. throw new RuntimeError(
  683. "GoogleEarthEnterpriseImageryProvider: Unsupported image type."
  684. );
  685. }
  686. }
  687. var alphaType = message.alphaType;
  688. if (defined(alphaType) && alphaType !== 0) {
  689. console.log(
  690. "GoogleEarthEnterpriseImageryProvider: External alpha not supported."
  691. );
  692. delete message.alphaType;
  693. delete message.imageAlpha;
  694. }
  695. return message;
  696. }
  697. export default GoogleEarthEnterpriseImageryProvider;