Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Map.getImage() #2168

Merged
merged 7 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### ✨ Features and improvements
- Improve performance by sending style layers to worker thread before processing it on main thread to allow parallel processing ([#2131](https://github.com/maplibre/maplibre-gl-js/pull/2131))
- [Breaking] Resize map when container element is resized. the resize related events now has different data associated with it ([#2157](https://github.com/maplibre/maplibre-gl-js/pull/2157))
- Add Map.getImage() to retrieve previously-loaded images. ([#2168](https://github.com/maplibre/maplibre-gl-js/pull/2168))
- *...Add new stuff here...*

### 🐞 Bug fixes
Expand Down
108 changes: 108 additions & 0 deletions src/ui/map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {CameraOptions} from './camera';
import Terrain, {} from '../render/terrain';
import {mercatorZfromAltitude} from '../geo/mercator_coordinate';
import Transform from '../geo/transform';
import { StyleImage, StyleImageInterface, StyleImageMetadata } from '../style/style_image';
import { RGBAImage } from '../util/image';

function createStyleSource() {
return {
Expand Down Expand Up @@ -2204,6 +2206,112 @@ describe('Map', () => {
});
});

test('map getImage matches addImage', done => {
HarelM marked this conversation as resolved.
Show resolved Hide resolved
const map = createMap();

//Create graphics of various types, each with a different size
const idImageUint = 'add-get-uint';
const inputImageUint = {width: 2, height: 1, data: new Uint8Array(8)};

const idImageUintClamped = 'add-get-uint-clamped';
const inputImageUintClamped = {width: 1, height: 2, data: new Uint8ClampedArray(8)};

const idImageData = 'add-get-image-data';
const inputImageData = new ImageData(1, 3);

const idStyleImage = 'add-get-style-image';
const inputStyleImage: StyleImageInterface = {
width: 3,
height: 1,
data: new Uint8Array(12)
};

const idStyleImageClamped = 'add-get-style-image-clamped';
const inputStyleImageClamped: StyleImageInterface = {
width: 4,
height: 1,
data: new Uint8ClampedArray(16)
};

const idStyleImageSDF = 'add-get-style-image-sdf';
const inputStyleImageSDF: StyleImageInterface = {
width: 5,
height: 1,
data: new Uint8Array(20)
};

//Add a graphic of each type
map.addImage(idImageUint, inputImageUint);
map.addImage(idImageUintClamped, inputImageUintClamped);
map.addImage(idImageData, inputImageData);
map.addImage(idStyleImage, inputStyleImage);
map.addImage(idStyleImageClamped, inputStyleImageClamped);
map.addImage(idStyleImageSDF, inputStyleImageSDF, {sdf: true});

//Verify all graphics added are reported as present
[idImageUint, idImageUintClamped, idImageData, idStyleImage, idStyleImageClamped, idStyleImageSDF].forEach((id) =>
expect(map.hasImage(id)).toBeTruthy());

//Retrieve graphic we added
const gotImageUint = map.getImage(idImageUint);
const gotImageUintClamped = map.getImage(idImageUintClamped);
const gotImageData = map.getImage(idImageData);
const gotStyleImage = map.getImage(idStyleImage);
const gotStyleImageClamped = map.getImage(idStyleImageClamped);
const gotStyleImageSDF = map.getImage(idStyleImageSDF);

//Verify retrieved graphic is the same size
expect(gotImageUint.data.width).toEqual(inputImageUint.width);
expect(gotImageUint.data.height).toEqual(inputImageUint.height);

expect(gotImageUintClamped.data.width).toEqual(inputImageUintClamped.width);
expect(gotImageUintClamped.data.height).toEqual(inputImageUintClamped.height);

expect(gotImageData.data.width).toEqual(inputImageData.width);
expect(gotImageData.data.height).toEqual(inputImageData.height);

expect(gotStyleImage.data.width).toEqual(inputStyleImage.width);
expect(gotStyleImage.data.height).toEqual(inputStyleImage.height);

expect(gotStyleImageClamped.data.width).toEqual(inputStyleImageClamped.width);
expect(gotStyleImageClamped.data.height).toEqual(inputStyleImageClamped.height);

expect(gotStyleImageSDF.data.width).toEqual(inputStyleImageSDF.width);
expect(gotStyleImageSDF.data.height).toEqual(inputStyleImageSDF.height);

//Verify retrieved graphic has same image contents
for (let i = 0; i < gotImageUint.data.data.length; i++) {
expect(gotImageUint.data.data[i]).toEqual(inputImageUint.data[i]);
}
ZeLonewolf marked this conversation as resolved.
Show resolved Hide resolved

for (let i = 0; i < gotImageUintClamped.data.data.length; i++) {
expect(gotImageUintClamped.data.data[i]).toEqual(inputImageUintClamped.data[i]);
}

for (let i = 0; i < gotImageData.data.data.length; i++) {
expect(gotImageData.data.data[i]).toEqual(inputImageData.data[i]);
}

for (let i = 0; i < gotStyleImage.data.data.length; i++) {
expect(gotStyleImage.data.data[i]).toEqual(inputStyleImage.data[i]);
}

for (let i = 0; i < gotStyleImageClamped.data.data.length; i++) {
expect(gotStyleImageClamped.data.data[i]).toEqual(inputStyleImageClamped.data[i]);
}

for (let i = 0; i < gotStyleImageSDF.data.data.length; i++) {
expect(gotStyleImageSDF.data.data[i]).toEqual(inputStyleImageSDF.data[i]);
}

//Verify SDF attribute
expect(gotStyleImage.sdf).toBe(false);
expect(gotStyleImageClamped.sdf).toBe(false);
expect(gotStyleImageSDF.sdf).toBe(true);

done();
});

test('map does not fire `styleimagemissing` for empty icon values', done => {
const map = createMap();

Expand Down
18 changes: 17 additions & 1 deletion src/ui/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import type {LngLatBoundsLike} from '../geo/lng_lat_bounds';
import type {FeatureIdentifier, StyleOptions, StyleSetterOptions} from '../style/style';
import type {MapEvent, MapDataEvent} from './events';
import type {CustomLayerInterface} from '../style/style_layer/custom_style_layer';
import type {StyleImageInterface, StyleImageMetadata} from '../style/style_image';
import type {StyleImage, StyleImageInterface, StyleImageMetadata} from '../style/style_image';
import type {PointLike} from './camera';
import type ScrollZoomHandler from './handler/scroll_zoom';
import type BoxZoomHandler from './handler/box_zoom';
Expand Down Expand Up @@ -1909,6 +1909,22 @@ class Map extends Camera {
this.style.updateImage(id, existingImage);
}

/**
* Returns an image, specified by ID, currently available in the map.
* This includes both images from the style's original sprite
* and any images that have been added at runtime using {@link Map#addImage}.
*
* @param id The ID of the image.
* @returns {StyleImage} An image in the map with the specified ID.
*
* @example
* var coffeeShopIcon = map.getImage("coffee_cup");
*
*/
getImage(id: string): StyleImage {
return this.style.getImage(id);
}

/**
* Check whether or not an image with a specific ID exists in the style. This checks both images
* in the style's original sprite and any images
Expand Down