save in webp

adjust Tile creation
This commit is contained in:
HF 2022-06-27 14:03:52 +02:00
parent c8409c6e5f
commit 61ec34d7b4
5 changed files with 90 additions and 81 deletions

View File

@ -241,7 +241,7 @@ function addIndexedSubtiletoTile(
*/
function tileFileName(canvasTileFolder, cell) {
const [z, x, y] = cell;
const filename = `${canvasTileFolder}/${z}/${x}/${y}.png`;
const filename = `${canvasTileFolder}/${z}/${x}/${y}.webp`;
return filename;
}
@ -271,24 +271,17 @@ export async function createZoomTileFromChunk(
const xabs = x * TILE_ZOOM_LEVEL;
const yabs = y * TILE_ZOOM_LEVEL;
const na = [];
for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) {
for (let dx = 0; dx < TILE_ZOOM_LEVEL; dx += 1) {
let chunk = null;
try {
chunk = await RedisCanvas.getChunk(
canvasId,
xabs + dx,
yabs + dy,
);
} catch (error) {
console.error(
// eslint-disable-next-line max-len
`Tiling: Failed to get Chunk ch:${canvasId}:${xabs + dx}${yabs + dy} with error ${error.message}`,
);
}
const prom = async (dx, dy) => {
try {
const chunk = await RedisCanvas.getChunk(
canvasId,
xabs + dx,
yabs + dy,
);
if (!chunk || !chunk.length) {
na.push([dx, dy]);
continue;
return;
}
addIndexedSubtiletoTile(
palette,
@ -297,8 +290,22 @@ export async function createZoomTileFromChunk(
chunk,
tileRGBBuffer,
);
} catch (error) {
na.push([dx, dy]);
console.error(
// eslint-disable-next-line max-len
`Tiling: Failed to get Chunk ch:${canvasId}:${xabs + dx}${yabs + dy} with error ${error.message}`,
);
}
};
const promises = [];
for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) {
for (let dx = 0; dx < TILE_ZOOM_LEVEL; dx += 1) {
promises.push(prom(dx, dy));
}
}
await Promise.all(promises);
if (na.length !== TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL) {
na.forEach((element) => {
@ -313,7 +320,7 @@ export async function createZoomTileFromChunk(
const filename = tileFileName(canvasTileFolder, [maxTiledZoom - 1, x, y]);
try {
await sharp(Buffer.from(tileRGBBuffer.buffer), {
await sharp(tileRGBBuffer, {
raw: {
width: TILE_SIZE * TILE_ZOOM_LEVEL,
height: TILE_SIZE * TILE_ZOOM_LEVEL,
@ -321,7 +328,7 @@ export async function createZoomTileFromChunk(
},
})
.resize(TILE_SIZE)
.png({ options: { compressionLevel: 6 } })
.webp({ quality: 100, smartSubsample: true })
.toFile(filename);
} catch (error) {
console.error(
@ -361,7 +368,7 @@ export async function createZoomedTile(
const prom = async (dx, dy) => {
// eslint-disable-next-line max-len
const chunkfile = `${canvasTileFolder}/${z + 1}/${x * TILE_ZOOM_LEVEL + dx}/${y * TILE_ZOOM_LEVEL + dy}.png`;
const chunkfile = `${canvasTileFolder}/${z + 1}/${x * TILE_ZOOM_LEVEL + dx}/${y * TILE_ZOOM_LEVEL + dy}.webp`;
try {
if (!fs.existsSync(chunkfile)) {
na.push([dx, dy]);
@ -404,17 +411,15 @@ export async function createZoomedTile(
const filename = tileFileName(canvasTileFolder, [z, x, y]);
try {
await sharp(
Buffer.from(
tileRGBBuffer.buffer,
), {
raw: {
width: TILE_SIZE,
height: TILE_SIZE,
channels: 3,
},
await sharp(tileRGBBuffer, {
raw: {
width: TILE_SIZE,
height: TILE_SIZE,
channels: 3,
},
).toFile(filename);
})
.webp({ quality: 100, smartSubsample: true })
.toFile(filename);
} catch (error) {
console.error(
`Tiling: Error on createZoomedTile: ${error.message}`,
@ -452,16 +457,16 @@ async function createEmptyTile(
// eslint-disable-next-line prefer-destructuring
tileRGBBuffer[i++] = palette.rgb[2];
}
const filename = `${canvasTileFolder}/emptytile.png`;
const filename = `${canvasTileFolder}/emptytile.webp`;
try {
await sharp(Buffer.from(tileRGBBuffer.buffer), {
await sharp(tileRGBBuffer, {
raw: {
width: TILE_SIZE,
height: TILE_SIZE,
channels: 3,
},
})
.png({ options: { compressionLevel: 6 } })
.webp({ quality: 100, smartSubsample: true })
.toFile(filename);
} catch (error) {
console.error(
@ -494,45 +499,36 @@ export async function createTexture(
const startTime = Date.now();
const na = [];
if (targetSize !== canvasSize) {
for (let dy = 0; dy < amount; dy += 1) {
for (let dx = 0; dx < amount; dx += 1) {
let chunk = null;
const chunkfile = `${canvasTileFolder}/${zoom}/${dx}/${dy}.png`;
const prom = (targetSize !== canvasSize)
? async (dx, dy) => {
const chunkfile = `${canvasTileFolder}/${zoom}/${dx}/${dy}.webp`;
try {
if (!fs.existsSync(chunkfile)) {
na.push([dx, dy]);
continue;
}
try {
chunk = await sharp(chunkfile).removeAlpha().raw().toBuffer();
addRGBSubtiletoTile(amount, [dx, dy], chunk, textureBuffer);
} catch (error) {
console.error(
// eslint-disable-next-line max-len
`Tiling: Error on createTexture in chunk ${chunkfile}: ${error.message}`,
);
return;
}
const chunk = await sharp(chunkfile).removeAlpha().raw().toBuffer();
addRGBSubtiletoTile(amount, [dx, dy], chunk, textureBuffer);
} catch (error) {
na.push([dx, dy]);
console.error(
// eslint-disable-next-line max-len
`Tiling: Error on createTexture in chunk ${chunkfile}: ${error.message}`,
);
}
}
} else {
for (let dy = 0; dy < amount; dy += 1) {
for (let dx = 0; dx < amount; dx += 1) {
: async (dx, dy) => {
try {
let chunk = null;
try {
chunk = await RedisCanvas.getChunk(
canvasId,
dx,
dy,
);
} catch (error) {
console.error(
// eslint-disable-next-line max-len
`Tiling: Failed to get Chunk ch:${canvasId}:${dx}${dy} with error ${error.message}`,
);
}
chunk = await RedisCanvas.getChunk(
canvasId,
dx,
dy,
);
if (!chunk || !chunk.length) {
na.push([dx, dy]);
continue;
return;
}
addIndexedSubtiletoTile(
palette,
@ -541,25 +537,36 @@ export async function createTexture(
chunk,
textureBuffer,
);
} catch (error) {
na.push([dx, dy]);
console.error(
// eslint-disable-next-line max-len
`Tiling: Failed to get Chunk ch:${canvasId}:${dx}${dy} with error ${error.message}`,
);
}
};
const promises = [];
for (let dy = 0; dy < amount; dy += 1) {
for (let dx = 0; dx < amount; dx += 1) {
promises.push(prom(dx, dy));
}
}
await Promise.all(promises);
na.forEach((element) => {
deleteSubtilefromTile(TILE_SIZE, palette, amount, element, textureBuffer);
});
const filename = `${canvasTileFolder}/texture.png`;
const filename = `${canvasTileFolder}/texture.webp`;
try {
await sharp(
Buffer.from(textureBuffer.buffer), {
raw: {
width: targetSize,
height: targetSize,
channels: 3,
},
await sharp(textureBuffer, {
raw: {
width: targetSize,
height: targetSize,
channels: 3,
},
).toFile(filename);
}).toFile(filename);
} catch (error) {
console.error(
`Tiling: Error on createTexture: ${error.message}`,
@ -605,7 +612,7 @@ export async function initializeTiles(
const tileDir = `${canvasTileFolder}/${zoom}/${cx}`;
if (!fs.existsSync(tileDir)) fs.mkdirSync(tileDir);
for (let cy = 0; cy < maxBase; cy += 1) {
const filename = `${canvasTileFolder}/${zoom}/${cx}/${cy}.png`;
const filename = `${canvasTileFolder}/${zoom}/${cx}/${cy}.webp`;
if (force || !fs.existsSync(filename)) {
const ret = await createZoomTileFromChunk(
canvasId,
@ -634,7 +641,7 @@ export async function initializeTiles(
const tileDir = `${canvasTileFolder}/${zoom}/${cx}`;
if (!fs.existsSync(tileDir)) fs.mkdirSync(tileDir);
for (let cy = 0; cy < maxZ; cy += 1) {
const filename = `${canvasTileFolder}/${zoom}/${cx}/${cy}.png`;
const filename = `${canvasTileFolder}/${zoom}/${cx}/${cy}.webp`;
if (force || !fs.existsSync(filename)) {
const ret = await createZoomedTile(
canvas,

View File

@ -161,7 +161,9 @@ class CanvasUpdater {
}
for (let c = 0; c < this.maxTiledZoom; c += 1) {
this.TileLoadingQueues.push([]);
const timeout = (7 ** (this.maxTiledZoom - c - 1)) * 5 * 1000;
const invZoom = this.maxTiledZoom - c - 1;
// eslint-disable-next-line max-len
const timeout = TILE_ZOOM_LEVEL ** (2 * invZoom + 2) * (6 / TILE_ZOOM_LEVEL ** 2) * 1000;
logger.info(
`Tiling: Set interval for zoomlevel ${c} update to ${timeout / 1000}`,
);

View File

@ -51,7 +51,7 @@ document.addEventListener('DOMContentLoaded', () => {
const [canvasIdent, canvasId, canvasSize, x, y] = parseHashCoords();
const canvasTexture = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load(`./tiles/${canvasId}/texture.png`),
map: new THREE.TextureLoader().load(`./tiles/${canvasId}/texture.webp`),
bumpMap: new THREE.TextureLoader().load(`./assets3d/normal${canvasId}.jpg`),
bumpScale: 0.02,
specularMap: new THREE.TextureLoader()

View File

@ -23,12 +23,12 @@ router.use('/', express.static(TILE_FOLDER, {
/*
* catch File Not Found: Send empty tile
*/
router.use('/:c([0-9]+)/:z([0-9]+)/:x([0-9]+)/:y([0-9]+).png',
router.use('/:c([0-9]+)/:z([0-9]+)/:x([0-9]+)/:y([0-9]+).webp',
async (req, res) => {
const { c: paramC } = req.params;
const c = parseInt(paramC, 10);
const filename = `${TILE_FOLDER}/${c}/emptytile.png`;
const filename = `${TILE_FOLDER}/${c}/emptytile.webp`;
if (!fs.existsSync(filename)) {
res.set({
'Cache-Control': `public, s-maxage=${24 * 3600}, max-age=${24 * 3600}`,
@ -39,7 +39,7 @@ router.use('/:c([0-9]+)/:z([0-9]+)/:x([0-9]+)/:y([0-9]+).png',
res.set({
'Cache-Control': `public, s-maxage=${2 * 3600}, max-age=${1 * 3600}`,
'Content-Type': 'image/png',
'Content-Type': 'image/webp',
});
res.status(200);
res.sendFile(filename);

View File

@ -304,7 +304,7 @@ class ChunkLoader {
const center = [zoom, cx, cy];
this.store.dispatch(requestBigChunk(center));
try {
const url = `tiles/${this.canvasId}/${zoom}/${cx}/${cy}.png`;
const url = `tiles/${this.canvasId}/${zoom}/${cx}/${cy}.webp`;
const img = await loadImage(url);
chunkRGB.fromImage(img);
this.store.dispatch(receiveBigChunk(center, chunkRGB));