Skip to content

Commit

Permalink
feat(ui): Render mapLayers to cropped imageData for better performanc…
Browse files Browse the repository at this point in the history
…e and less memory usage
  • Loading branch information
Hypfer committed Oct 26, 2022
1 parent c4d5df8 commit 5bb3fae
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 17 deletions.
51 changes: 48 additions & 3 deletions frontend/src/map/MapLayerRenderUtils.ts
Expand Up @@ -13,7 +13,11 @@ export type LayerColors = {
segments: RGBColor[];
};

export function RENDER_LAYERS_TO_IMAGEDATA(layers: Array<RawMapLayer>, pixelSize: number, width: number, height: number, colorsToUse: LayerColors) {
export function RENDER_LAYERS_TO_IMAGEDATA(layers: Array<RawMapLayer>, pixelSize: number, colorsToUse: LayerColors) {
const dimensions = CALCULATE_REQUIRED_DIMENSIONS(layers);
const width = dimensions.x.sum;
const height = dimensions.y.sum;

const imageData = new ImageData(
new Uint8ClampedArray( width * height * 4 ),
width,
Expand Down Expand Up @@ -46,7 +50,12 @@ export function RENDER_LAYERS_TO_IMAGEDATA(layers: Array<RawMapLayer>, pixelSize
}

for (let i = 0; i < layer.pixels.length; i = i + 2) {
const imgDataOffset = (layer.pixels[i] + layer.pixels[i+1] * width) * 4;
const imgDataOffset = (
(
(layer.pixels[i] - dimensions.x.min) +
((layer.pixels[i+1] - dimensions.y.min) * width)
) * 4
);

imageData.data[imgDataOffset] = color.r;
imageData.data[imgDataOffset + 1] = color.g;
Expand All @@ -55,7 +64,43 @@ export function RENDER_LAYERS_TO_IMAGEDATA(layers: Array<RawMapLayer>, pixelSize
}
});

return imageData;
return {
imageData: imageData,
width: dimensions.x.sum,
height: dimensions.y.sum,
left: dimensions.x.min,
top: dimensions.y.min,
};
}

function CALCULATE_REQUIRED_DIMENSIONS(layers: Array<RawMapLayer>) {
const dimensions = {
x: {
min: Infinity,
max: -Infinity,
sum: 0,
},
y: {
min: Infinity,
max: -Infinity,
sum: 0,
},
};

layers.forEach(layer => {
dimensions.x.min = layer.dimensions.x.min < dimensions.x.min ? layer.dimensions.x.min : dimensions.x.min;
dimensions.x.max = layer.dimensions.x.max > dimensions.x.max ? layer.dimensions.x.max : dimensions.x.max;

dimensions.y.min = layer.dimensions.y.min < dimensions.y.min ? layer.dimensions.y.min : dimensions.y.min;
dimensions.y.max = layer.dimensions.y.max > dimensions.y.max ? layer.dimensions.y.max : dimensions.y.max;
});

dimensions.x.sum = (dimensions.x.max - dimensions.x.min) + 1;
dimensions.y.sum = (dimensions.y.max - dimensions.y.min) + 1;
dimensions.x.sum = isFinite(dimensions.x.sum) ? dimensions.x.sum : 0;
dimensions.y.sum = isFinite(dimensions.y.sum) ? dimensions.y.sum : 0;

return dimensions;
}

// This is important because it determines the draw order
Expand Down
10 changes: 3 additions & 7 deletions frontend/src/map/MapLayerRenderer.ts
Expand Up @@ -87,7 +87,7 @@ export class MapLayerRenderer {
evt.data.height
);

this.ctx.putImageData(imageData, 0, 0);
this.ctx.putImageData(imageData, evt.data.left, evt.data.top);

if (typeof this.pendingCallback === "function") {
this.pendingCallback();
Expand Down Expand Up @@ -139,8 +139,6 @@ export class MapLayerRenderer {
this.mapLayerRenderWebWorker.postMessage( {
mapLayers: data.layers,
pixelSize: data.pixelSize,
width: this.width,
height: this.height,
colorsToUse: colorsToUse
});

Expand All @@ -154,15 +152,13 @@ export class MapLayerRenderer {
resolve();
};
} else { //Fallback if there's no worker for some reason
const imageData = RENDER_LAYERS_TO_IMAGEDATA(
const rendered = RENDER_LAYERS_TO_IMAGEDATA(
data.layers,
data.pixelSize,
this.width,
this.height,
colorsToUse
);

this.ctx.putImageData(imageData, 0, 0);
this.ctx.putImageData(rendered.imageData, rendered.left, rendered.top);
resolve();
}
} else {
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/map/MapLayerRenderer.worker.ts
Expand Up @@ -14,19 +14,19 @@ self.addEventListener( "message", ( evt ) => {
return;
}

const imageData = RENDER_LAYERS_TO_IMAGEDATA(
const rendered = RENDER_LAYERS_TO_IMAGEDATA(
evt.data.mapLayers,
evt.data.pixelSize,
evt.data.width,
evt.data.height,
evt.data.colorsToUse
);

self.postMessage( {
pixels: imageData.data.buffer,
width: evt.data.width,
height: evt.data.height,
pixels: rendered.imageData.data.buffer,
width: rendered.width,
height: rendered.height,
left: rendered.left,
top: rendered.top,
}, {
transfer: [imageData.data.buffer]
transfer: [rendered.imageData.data.buffer]
});
} );

0 comments on commit 5bb3fae

Please sign in to comment.