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