Skip to content

Commit dca9ed1

Browse files
author
Shehata
committedFeb 18, 2019
Add tests for image bitmap scenarios
1 parent b772d52 commit dca9ed1

File tree

3 files changed

+283
-41
lines changed

3 files changed

+283
-41
lines changed
 

‎Specs/Core/ResourceSpec.js

+134-7
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,36 @@ defineSuite([
22
'Core/Resource',
33
'Core/defaultValue',
44
'Core/DefaultProxy',
5+
'Core/FeatureDetection',
56
'Core/queryToObject',
67
'Core/Request',
78
'Core/RequestErrorEvent',
89
'Core/RequestScheduler',
10+
'Core/TrustedServers',
11+
'Specs/createCanvas',
912
'ThirdParty/Uri',
1013
'ThirdParty/when'
1114
], function(
1215
Resource,
1316
defaultValue,
1417
DefaultProxy,
18+
FeatureDetection,
1519
queryToObject,
1620
Request,
1721
RequestErrorEvent,
1822
RequestScheduler,
23+
TrustedServers,
24+
createCanvas,
1925
Uri,
2026
when) {
2127
'use strict';
2228

29+
var dataUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Nk+M/wHwAEBgIA5agATwAAAABJRU5ErkJggg==';
30+
31+
beforeAll(function() {
32+
return FeatureDetection.supportsImageBitmapOptions();
33+
});
34+
2335
it('Constructor sets correct properties', function() {
2436
var proxy = new DefaultProxy('/proxy/');
2537
var request = new Request();
@@ -1122,26 +1134,141 @@ defineSuite([
11221134
});
11231135
});
11241136

1125-
describe('fetchImage', function() {
1137+
it('can load an image preferring blob', function() {
1138+
return Resource.fetchImage('./Data/Images/Green.png', true).then(function(loadedImage) {
1139+
expect(loadedImage.width).toEqual(1);
1140+
expect(loadedImage.height).toEqual(1);
1141+
});
1142+
});
11261143

1127-
var dataUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Nk+M/wHwAEBgIA5agATwAAAABJRU5ErkJggg==';
1144+
it('can load an image from a data URI', function() {
1145+
return Resource.fetchImage(dataUri).then(function(loadedImage) {
1146+
expect(loadedImage.width).toEqual(1);
1147+
expect(loadedImage.height).toEqual(1);
1148+
});
1149+
});
11281150

1129-
it('can load an image', function() {
1151+
describe('fetchImage with ImageBitmap', function() {
1152+
if (!FeatureDetection.supportsCreateImageBitmap()) {
1153+
return;
1154+
}
1155+
1156+
var canvas;
1157+
beforeAll(function() {
1158+
canvas = createCanvas(1, 2);
1159+
});
1160+
1161+
afterAll(function() {
1162+
document.body.removeChild(canvas);
1163+
});
1164+
1165+
function getColorAtPixel(image, x, y) {
1166+
var context = canvas.getContext('2d');
1167+
context.drawImage(image, 0, 0, image.width, image.height);
1168+
var imageData = context.getImageData(0, 0, 1, 1);
1169+
return [imageData.data[0], imageData.data[1], imageData.data[2], imageData.data[3]];
1170+
}
1171+
1172+
it('can load and decode an image', function() {
11301173
return Resource.fetchImage('./Data/Images/Green.png').then(function(loadedImage) {
11311174
expect(loadedImage.width).toEqual(1);
11321175
expect(loadedImage.height).toEqual(1);
1176+
expect(loadedImage instanceof ImageBitmap);
11331177
});
11341178
});
11351179

1136-
it('can load an image preferring blob', function() {
1137-
return Resource.fetchImage('./Data/Images/Green.png', true).then(function(loadedImage) {
1180+
it('does not call createImageBitmap when ImageBitmapOptions support is not ready', function() {
1181+
spyOn(FeatureDetection, 'supportsImageBitmapOptionsSync').and.returnValue(undefined);
1182+
spyOn(window, 'createImageBitmap').and.callThrough();
1183+
1184+
return Resource.fetchImage('./Data/Images/Green.png').then(function(loadedImage) {
11381185
expect(loadedImage.width).toEqual(1);
11391186
expect(loadedImage.height).toEqual(1);
1187+
expect(window.createImageBitmap).not.toHaveBeenCalled();
1188+
});
1189+
});
1190+
1191+
it('correctly flips image when ImageBitmapOptions are supported', function() {
1192+
return Resource.fetchImage({
1193+
url: './Data/Images/BlueOverRed.png',
1194+
flipImage: true
1195+
}).then(function(loadedImage) {
1196+
if (FeatureDetection.supportsImageBitmapOptionsSync()) {
1197+
expect(getColorAtPixel(loadedImage, 0, 0)).toEqual([255, 0, 0, 255]);
1198+
} else {
1199+
expect(getColorAtPixel(loadedImage, 0, 0)).toEqual([0, 0, 255, 255]);
1200+
}
1201+
});
1202+
});
1203+
1204+
it('correctly loads image without flip when ImageBitmapOptions are supported', function() {
1205+
return Resource.fetchImage({
1206+
url: './Data/Images/BlueOverRed.png',
1207+
flipImage: false
1208+
}).then(function(loadedImage) {
1209+
if (FeatureDetection.supportsImageBitmapOptionsSync()) {
1210+
expect(getColorAtPixel(loadedImage, 0, 0)).toEqual([0, 0, 255, 255]);
1211+
} else {
1212+
expect(getColorAtPixel(loadedImage, 0, 0)).toEqual([0, 0, 255, 255]);
1213+
}
11401214
});
11411215
});
11421216

1143-
it('can load an image from a data URI', function() {
1144-
return Resource.fetchImage(dataUri).then(function(loadedImage) {
1217+
it('does not pass options when ImageBitmapOptions are not supported', function() {
1218+
spyOn(FeatureDetection, 'supportsImageBitmapOptionsSync').and.returnValue(false);
1219+
spyOn(window, 'createImageBitmap').and.callThrough();
1220+
1221+
return Resource.fetchImage('./Data/Images/Green.png').then(function(loadedImage) {
1222+
expect(window.createImageBitmap).toHaveBeenCalledWith(new Blob());
1223+
});
1224+
});
1225+
1226+
it('rejects the promise when the image errors', function() {
1227+
return Resource.fetchImage('http://example.invalid/testuri.png')
1228+
.then(function() {
1229+
fail('expected promise to reject');
1230+
})
1231+
.otherwise(function(error) {
1232+
expect(error).toBeInstanceOf(TypeError);
1233+
});
1234+
});
1235+
1236+
it('does not set credentials for untrusted cross-origin images using fetch API', function() {
1237+
var fetchSpy = spyOn(window, 'fetch').and.callThrough();
1238+
var url = './Data/Images/Green.png';
1239+
1240+
return Resource.fetchImage(url)
1241+
.then(function() {
1242+
expect(fetchSpy).toHaveBeenCalledWith(url, {
1243+
credentials: 'same-origin'
1244+
});
1245+
});
1246+
});
1247+
1248+
it('sets credentials for trusted cross-origin images using fetch API', function() {
1249+
var fetchSpy = spyOn(window, 'fetch').and.callThrough();
1250+
spyOn(TrustedServers, 'contains').and.returnValue(true);
1251+
var url = 'http://example.invalid/testuri.png';
1252+
1253+
return Resource.fetchImage(url)
1254+
.otherwise(function() {
1255+
expect(fetchSpy).toHaveBeenCalledWith(url, {
1256+
credentials: 'include'
1257+
});
1258+
});
1259+
});
1260+
});
1261+
1262+
describe('fetchImage without ImageBitmap', function() {
1263+
beforeAll(function() {
1264+
// Force it to use the Image constructor since these specs all test
1265+
// specific functionality of this code path. For example, the crossOrigin
1266+
// restriction does not apply to images loaded with ImageBitmap.
1267+
spyOn(FeatureDetection, 'supportsCreateImageBitmap').and.returnValue(false);
1268+
});
1269+
1270+
it('can load an image', function() {
1271+
return Resource.fetchImage('./Data/Images/Green.png').then(function(loadedImage) {
11451272
expect(loadedImage.width).toEqual(1);
11461273
expect(loadedImage.height).toEqual(1);
11471274
});
+73-6
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,105 @@
11
defineSuite([
22
'Core/loadImageFromTypedArray',
3+
'Core/FeatureDetection',
34
'Core/Resource'
45
], function(
56
loadImageFromTypedArray,
7+
FeatureDetection,
68
Resource) {
79
'use strict';
810

11+
beforeAll(function() {
12+
return FeatureDetection.supportsImageBitmapOptions();
13+
});
14+
915
it('can load an image', function() {
1016
return Resource.fetchArrayBuffer('./Data/Images/Blue10x10.png').then(function(arrayBuffer) {
11-
var arr = new Uint8Array(arrayBuffer);
12-
return loadImageFromTypedArray(arr, 'image/png').then(function(image) {
17+
var options = {
18+
uint8Array: new Uint8Array(arrayBuffer),
19+
format: 'image/png'
20+
};
21+
22+
return loadImageFromTypedArray(options).then(function(image) {
23+
expect(image.width).toEqual(10);
24+
expect(image.height).toEqual(10);
25+
});
26+
});
27+
});
28+
29+
it('flips image when ImageBitmapOptions are supported', function() {
30+
var options = {
31+
uint8Array: new Uint8Array([67, 101, 115, 105, 117, 109]), // This is an invalid PNG.
32+
format: 'image/png',
33+
flipY: true
34+
};
35+
spyOn(window, 'createImageBitmap');
36+
var blob = new Blob([options.uint8Array], {
37+
type : options.format
38+
});
39+
40+
return loadImageFromTypedArray(options).then(function() {
41+
if (FeatureDetection.supportsImageBitmapOptionsSync()) {
42+
expect(window.createImageBitmap).toHaveBeenCalledWith(blob, {
43+
imageOrientation: 'flipY'
44+
});
45+
} else {
46+
expect(window.createImageBitmap).toHaveBeenCalledWith(blob);
47+
}
48+
49+
options.flipY = false;
50+
window.createImageBitmap.calls.reset();
51+
return loadImageFromTypedArray(options);
52+
})
53+
.then(function() {
54+
if (FeatureDetection.supportsImageBitmapOptionsSync()) {
55+
expect(window.createImageBitmap).toHaveBeenCalledWith(blob, {
56+
imageOrientation: 'none'
57+
});
58+
} else {
59+
expect(window.createImageBitmap).toHaveBeenCalledWith(blob);
60+
}
61+
});
62+
});
63+
64+
it('can load an image when ImageBitmap is not supported', function() {
65+
spyOn(FeatureDetection, 'supportsCreateImageBitmap').and.returnValue(false);
66+
spyOn(window, 'createImageBitmap').and.callThrough();
67+
return Resource.fetchArrayBuffer('./Data/Images/Blue10x10.png').then(function(arrayBuffer) {
68+
var options = {
69+
uint8Array: new Uint8Array(arrayBuffer),
70+
format: 'image/png'
71+
};
72+
73+
return loadImageFromTypedArray(options).then(function(image) {
1374
expect(image.width).toEqual(10);
1475
expect(image.height).toEqual(10);
76+
expect(window.createImageBitmap).not.toHaveBeenCalled();
1577
});
1678
});
1779
});
1880

1981
it('can not load an invalid image', function() {
20-
var notApng = new Uint8Array([67, 101, 115, 105, 117, 109]);
21-
return loadImageFromTypedArray(notApng, 'image/png').then(function(image) {
82+
var options = {
83+
uint8Array: new Uint8Array([67, 101, 115, 105, 117, 109]), // This is an invalid PNG.
84+
format: 'image/png'
85+
};
86+
return loadImageFromTypedArray(options).then(function(image) {
2287
fail('should not be called');
2388
}).otherwise(function() {
2489
});
2590
});
2691

2792
it('Throws without array', function() {
2893
expect(function() {
29-
loadImageFromTypedArray();
94+
loadImageFromTypedArray({});
3095
}).toThrowDeveloperError();
3196
});
3297

3398
it('Throws without format', function() {
3499
expect(function() {
35-
loadImageFromTypedArray(new Uint8Array());
100+
loadImageFromTypedArray({
101+
uint8Array: new Uint8Array()
102+
});
36103
}).toThrowDeveloperError();
37104
});
38105
});

‎Specs/Renderer/TextureSpec.js

+76-28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defineSuite([
22
'Renderer/Texture',
33
'Core/Cartesian2',
44
'Core/Color',
5+
'Core/FeatureDetection',
56
'Core/loadKTX',
67
'Core/PixelFormat',
78
'Core/Resource',
@@ -18,6 +19,7 @@ defineSuite([
1819
Texture,
1920
Cartesian2,
2021
Color,
22+
FeatureDetection,
2123
loadKTX,
2224
PixelFormat,
2325
Resource,
@@ -37,6 +39,7 @@ defineSuite([
3739
var blueImage;
3840
var blueAlphaImage;
3941
var blueOverRedImage;
42+
var blueOverRedUnflippedImage;
4043
var red16x16Image;
4144

4245
var greenDXTImage;
@@ -55,34 +58,43 @@ defineSuite([
5558

5659
beforeAll(function() {
5760
context = createContext();
58-
59-
var promises = [];
60-
promises.push(Resource.fetchImage('./Data/Images/Green.png').then(function(image) {
61-
greenImage = image;
62-
}));
63-
promises.push(Resource.fetchImage('./Data/Images/Blue.png').then(function(image) {
64-
blueImage = image;
65-
}));
66-
promises.push(Resource.fetchImage('./Data/Images/BlueAlpha.png').then(function(image) {
67-
blueAlphaImage = image;
68-
}));
69-
promises.push(Resource.fetchImage('./Data/Images/BlueOverRed.png').then(function(image) {
70-
blueOverRedImage = image;
71-
}));
72-
promises.push(Resource.fetchImage('./Data/Images/Red16x16.png').then(function(image) {
73-
red16x16Image = image;
74-
}));
75-
promises.push(loadKTX('./Data/Images/Green4x4DXT1.ktx').then(function(image) {
76-
greenDXTImage = image;
77-
}));
78-
promises.push(loadKTX('./Data/Images/Green4x4PVR.ktx').then(function(image) {
79-
greenPVRImage = image;
80-
}));
81-
promises.push(loadKTX('./Data/Images/Green4x4ETC1.ktx').then(function(image) {
82-
greenETC1Image = image;
83-
}));
84-
85-
return when.all(promises);
61+
return FeatureDetection.supportsImageBitmapOptions()
62+
.then(function() {
63+
var promises = [];
64+
promises.push(Resource.fetchImage('./Data/Images/Green.png').then(function(image) {
65+
greenImage = image;
66+
}));
67+
promises.push(Resource.fetchImage('./Data/Images/Blue.png').then(function(image) {
68+
blueImage = image;
69+
}));
70+
promises.push(Resource.fetchImage('./Data/Images/BlueAlpha.png').then(function(image) {
71+
blueAlphaImage = image;
72+
}));
73+
promises.push(Resource.fetchImage('./Data/Images/BlueOverRed.png').then(function(image) {
74+
blueOverRedImage = image;
75+
}));
76+
// Turn off the default flipping.
77+
promises.push(Resource.fetchImage({
78+
url: './Data/Images/BlueOverRed.png',
79+
flipImage: false
80+
}).then(function(image) {
81+
blueOverRedUnflippedImage = image;
82+
}));
83+
promises.push(Resource.fetchImage('./Data/Images/Red16x16.png').then(function(image) {
84+
red16x16Image = image;
85+
}));
86+
promises.push(loadKTX('./Data/Images/Green4x4DXT1.ktx').then(function(image) {
87+
greenDXTImage = image;
88+
}));
89+
promises.push(loadKTX('./Data/Images/Green4x4PVR.ktx').then(function(image) {
90+
greenPVRImage = image;
91+
}));
92+
promises.push(loadKTX('./Data/Images/Green4x4ETC1.ktx').then(function(image) {
93+
greenETC1Image = image;
94+
}));
95+
96+
return when.all(promises);
97+
});
8698
});
8799

88100
afterAll(function() {
@@ -187,6 +199,42 @@ defineSuite([
187199
}).contextToRender([0, 0, 255, 255]);
188200
});
189201

202+
it('can set flip texture only if ImageBitmapOptions is not supported', function() {
203+
var topColor = new Color(0.0, 0.0, 1.0, 1.0);
204+
var bottomColor = new Color(1.0, 0.0, 0.0, 1.0);
205+
if (FeatureDetection.supportsImageBitmapOptionsSync()) {
206+
// When imageBitmapOptions is supported, flipY on texture upload is ignored.
207+
bottomColor = topColor;
208+
}
209+
210+
texture = new Texture({
211+
context : context,
212+
source : blueOverRedUnflippedImage,
213+
pixelFormat : PixelFormat.RGBA,
214+
flipY : false
215+
});
216+
217+
expect({
218+
context : context,
219+
fragmentShader : fs,
220+
uniformMap : uniformMap
221+
}).contextToRender(topColor.toBytes());
222+
223+
// Flip the texture.
224+
texture = new Texture({
225+
context : context,
226+
source : blueOverRedUnflippedImage,
227+
pixelFormat : PixelFormat.RGBA,
228+
flipY : true
229+
});
230+
231+
expect({
232+
context : context,
233+
fragmentShader : fs,
234+
uniformMap : uniformMap
235+
}).contextToRender(bottomColor.toBytes());
236+
});
237+
190238
it('draws the expected floating-point texture color', function() {
191239
if (!context.floatingPointTexture) {
192240
return;

0 commit comments

Comments
 (0)
Please sign in to comment.