DiscardMissingTileImagePolicy.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*global define*/
  2. define([
  3. '../Core/defaultValue',
  4. '../Core/defined',
  5. '../Core/DeveloperError',
  6. '../Core/getImagePixels',
  7. '../Core/loadImageViaBlob',
  8. '../ThirdParty/when'
  9. ], function(
  10. defaultValue,
  11. defined,
  12. DeveloperError,
  13. getImagePixels,
  14. loadImageViaBlob,
  15. when) {
  16. "use strict";
  17. /**
  18. * A policy for discarding tile images that match a known image containing a
  19. * "missing" image.
  20. *
  21. * @alias DiscardMissingTileImagePolicy
  22. * @constructor
  23. *
  24. * @param {Object} options Object with the following properties:
  25. * @param {String} options.missingImageUrl The URL of the known missing image.
  26. * @param {Cartesian2[]} options.pixelsToCheck An array of {@link Cartesian2} pixel positions to
  27. * compare against the missing image.
  28. * @param {Boolean} [options.disableCheckIfAllPixelsAreTransparent=false] If true, the discard check will be disabled
  29. * if all of the pixelsToCheck in the missingImageUrl have an alpha value of 0. If false, the
  30. * discard check will proceed no matter the values of the pixelsToCheck.
  31. */
  32. var DiscardMissingTileImagePolicy = function(options) {
  33. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  34. if (!defined(options.missingImageUrl)) {
  35. throw new DeveloperError('options.missingImageUrl is required.');
  36. }
  37. if (!defined(options.pixelsToCheck)) {
  38. throw new DeveloperError('options.pixelsToCheck is required.');
  39. }
  40. this._pixelsToCheck = options.pixelsToCheck;
  41. this._missingImagePixels = undefined;
  42. this._missingImageByteLength = undefined;
  43. this._isReady = false;
  44. var that = this;
  45. function success(image) {
  46. if (defined(image.blob)) {
  47. that._missingImageByteLength = image.blob.size;
  48. }
  49. var pixels = getImagePixels(image);
  50. if (options.disableCheckIfAllPixelsAreTransparent) {
  51. var allAreTransparent = true;
  52. var width = image.width;
  53. var pixelsToCheck = options.pixelsToCheck;
  54. for (var i = 0, len = pixelsToCheck.length; allAreTransparent && i < len; ++i) {
  55. var pos = pixelsToCheck[i];
  56. var index = pos.x * 4 + pos.y * width;
  57. var alpha = pixels[index + 3];
  58. if (alpha > 0) {
  59. allAreTransparent = false;
  60. }
  61. }
  62. if (allAreTransparent) {
  63. pixels = undefined;
  64. }
  65. }
  66. that._missingImagePixels = pixels;
  67. that._isReady = true;
  68. }
  69. function failure() {
  70. // Failed to download "missing" image, so assume that any truly missing tiles
  71. // will also fail to download and disable the discard check.
  72. that._missingImagePixels = undefined;
  73. that._isReady = true;
  74. }
  75. when(loadImageViaBlob(options.missingImageUrl), success, failure);
  76. };
  77. /**
  78. * Determines if the discard policy is ready to process images.
  79. * @returns True if the discard policy is ready to process images; otherwise, false.
  80. */
  81. DiscardMissingTileImagePolicy.prototype.isReady = function() {
  82. return this._isReady;
  83. };
  84. /**
  85. * Given a tile image, decide whether to discard that image.
  86. *
  87. * @param {Image} image An image to test.
  88. * @returns True if the image should be discarded; otherwise, false.
  89. *
  90. * @exception {DeveloperError} <code>shouldDiscardImage</code> must not be called before the discard policy is ready.
  91. */
  92. DiscardMissingTileImagePolicy.prototype.shouldDiscardImage = function(image) {
  93. if (!this._isReady) {
  94. throw new DeveloperError('shouldDiscardImage must not be called before the discard policy is ready.');
  95. }
  96. var pixelsToCheck = this._pixelsToCheck;
  97. var missingImagePixels = this._missingImagePixels;
  98. // If missingImagePixels is undefined, it indicates that the discard check has been disabled.
  99. if (!defined(missingImagePixels)) {
  100. return false;
  101. }
  102. if (defined(image.blob) && image.blob.size !== this._missingImageByteLength) {
  103. return false;
  104. }
  105. var pixels = getImagePixels(image);
  106. var width = image.width;
  107. for (var i = 0, len = pixelsToCheck.length; i < len; ++i) {
  108. var pos = pixelsToCheck[i];
  109. var index = pos.x * 4 + pos.y * width;
  110. for (var offset = 0; offset < 4; ++offset) {
  111. var pixel = index + offset;
  112. if (pixels[pixel] !== missingImagePixels[pixel]) {
  113. return false;
  114. }
  115. }
  116. }
  117. return true;
  118. };
  119. return DiscardMissingTileImagePolicy;
  120. });