Add stitch renderer
This commit is contained in:
parent
bd467ceb3b
commit
4b0d51dd80
67
app/src/tiles/renderers/stitchRenderer.ts
Normal file
67
app/src/tiles/renderers/stitchRenderer.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import sharp from 'sharp';
|
||||
import { Image } from 'mapnik';
|
||||
|
||||
import { TileParams, TileRenderer } from "../types";
|
||||
import { getBbox, getXYZ, TILE_SIZE, formatParams } from "../util";
|
||||
|
||||
class StitchRenderer implements TileRenderer {
|
||||
constructor(
|
||||
/** Renderer to use when retrieving tiles to be stitched together */
|
||||
public tileRenderer: TileRenderer
|
||||
) {}
|
||||
|
||||
getTile(tileParams: TileParams, dataParams: any): Promise<Image> {
|
||||
console.log(`Stitching tile ${formatParams(tileParams)}`);
|
||||
return this.stitchTile(tileParams, dataParams, this.tileRenderer);
|
||||
}
|
||||
|
||||
private async stitchTile({ tileset, z, x, y, scale }: TileParams, dataParams: any, tileRenderer: TileRenderer) {
|
||||
const bbox = getBbox(z, x, y);
|
||||
const nextZ = z + 1;
|
||||
const nextXY = getXYZ(bbox, nextZ);
|
||||
const tileSize = TILE_SIZE * scale;
|
||||
|
||||
|
||||
const [topLeft, topRight, bottomLeft, bottomRight] = await Promise.all([
|
||||
[nextXY.minX, nextXY.minY],
|
||||
[nextXY.maxX, nextXY.minY],
|
||||
[nextXY.minX, nextXY.maxY],
|
||||
[nextXY.maxX, nextXY.maxY]
|
||||
].map(([x, y]) => tileRenderer.getTile({ tileset, z: nextZ, x, y, scale }, dataParams)));
|
||||
|
||||
// not possible to chain overlays in a single pipeline, but there may still be a better
|
||||
// way to create image buffer here (four tiles resize to one at the next zoom level)
|
||||
// instead of repeatedly creating `sharp` objects, to png, to buffer...
|
||||
return sharp({
|
||||
create: {
|
||||
width: tileSize * 2,
|
||||
height: tileSize * 2,
|
||||
channels: 4,
|
||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||
}
|
||||
}).overlayWith(
|
||||
topLeft, { gravity: sharp.gravity.northwest }
|
||||
).png().toBuffer().then((buf) => {
|
||||
return sharp(buf).overlayWith(
|
||||
topRight, { gravity: sharp.gravity.northeast }
|
||||
).png().toBuffer()
|
||||
}).then((buf) => {
|
||||
return sharp(buf).overlayWith(
|
||||
bottomLeft, { gravity: sharp.gravity.southwest }
|
||||
).png().toBuffer()
|
||||
}).then((buf) => {
|
||||
return sharp(buf).overlayWith(
|
||||
bottomRight, { gravity: sharp.gravity.southeast }
|
||||
).png().toBuffer()
|
||||
}).then((buf) => {
|
||||
return sharp(buf
|
||||
).resize(tileSize, tileSize, { fit: 'inside' }
|
||||
).png().toBuffer()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export {
|
||||
StitchRenderer
|
||||
};
|
Loading…
Reference in New Issue
Block a user