change scaling algorithm also for first tile layer caluclated out of
chunks
This commit is contained in:
parent
727676f0f8
commit
d18882e3ae
108
src/core/Tile.js
108
src/core/Tile.js
|
@ -20,6 +20,7 @@ import { TILE_SIZE, TILE_ZOOM_LEVEL } from './constants';
|
||||||
/*
|
/*
|
||||||
* Deletes a subtile from a tile (paints it in color 0),
|
* Deletes a subtile from a tile (paints it in color 0),
|
||||||
* if we wouldn't do it, it would be black
|
* if we wouldn't do it, it would be black
|
||||||
|
* @param tileSize size of the tile within the chunk
|
||||||
* @param palette Palette to use
|
* @param palette Palette to use
|
||||||
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
||||||
* @param cell subtile to delete [dx, dy]
|
* @param cell subtile to delete [dx, dy]
|
||||||
|
@ -34,16 +35,14 @@ function deleteSubtilefromTile(
|
||||||
) {
|
) {
|
||||||
const [dx, dy] = cell;
|
const [dx, dy] = cell;
|
||||||
const offset = (dx + dy * tileSize * subtilesInTile) * tileSize;
|
const offset = (dx + dy * tileSize * subtilesInTile) * tileSize;
|
||||||
|
const [blankR, blankG, blankB] = palette.rgb;
|
||||||
for (let row = 0; row < tileSize; row += 1) {
|
for (let row = 0; row < tileSize; row += 1) {
|
||||||
let channelOffset = (offset + row * tileSize * subtilesInTile) * 3;
|
let channelOffset = (offset + row * tileSize * subtilesInTile) * 3;
|
||||||
const max = channelOffset + tileSize * 3;
|
const max = channelOffset + tileSize * 3;
|
||||||
while (channelOffset < max) {
|
while (channelOffset < max) {
|
||||||
// eslint-disable-next-line prefer-destructuring
|
buffer[channelOffset++] = blankR;
|
||||||
buffer[channelOffset++] = palette.rgb[0];
|
buffer[channelOffset++] = blankG;
|
||||||
// eslint-disable-next-line prefer-destructuring
|
buffer[channelOffset++] = blankB;
|
||||||
buffer[channelOffset++] = palette.rgb[1];
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
buffer[channelOffset++] = palette.rgb[2];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +55,7 @@ function addShrunkenSubtileToTile(
|
||||||
) {
|
) {
|
||||||
const tileSize = TILE_SIZE;
|
const tileSize = TILE_SIZE;
|
||||||
const [dx, dy] = cell;
|
const [dx, dy] = cell;
|
||||||
const chunkOffset = (dx + dy * subtilesInTile * tileSize / 4) * tileSize / 4;
|
const offset = (dx + dy * subtilesInTile * tileSize / 4) * tileSize / 4;
|
||||||
const target = tileSize / 4;
|
const target = tileSize / 4;
|
||||||
let tr;
|
let tr;
|
||||||
let tg;
|
let tg;
|
||||||
|
@ -65,7 +64,7 @@ function addShrunkenSubtileToTile(
|
||||||
let tmp;
|
let tmp;
|
||||||
const linePad = (tileSize * 3 - 1) * 3;
|
const linePad = (tileSize * 3 - 1) * 3;
|
||||||
for (let row = 0; row < target; row += 1) {
|
for (let row = 0; row < target; row += 1) {
|
||||||
let channelOffset = (chunkOffset + row * target * subtilesInTile) * 3;
|
let channelOffset = (offset + row * target * subtilesInTile) * 3;
|
||||||
const max = channelOffset + target * 3;
|
const max = channelOffset + target * 3;
|
||||||
pos = row * tileSize * 12;
|
pos = row * tileSize * 12;
|
||||||
while (channelOffset < max) {
|
while (channelOffset < max) {
|
||||||
|
@ -81,6 +80,85 @@ function addShrunkenSubtileToTile(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addShrunkenIndexedSubtilesToTile(
|
||||||
|
palette,
|
||||||
|
tileSize,
|
||||||
|
subtilesInTile,
|
||||||
|
cell,
|
||||||
|
inpTile,
|
||||||
|
buffer,
|
||||||
|
) {
|
||||||
|
const [dx, dy] = cell;
|
||||||
|
const subtileSize = tileSize / subtilesInTile;
|
||||||
|
const inpTileLength = inpTile.length;
|
||||||
|
const offset = (dx + dy * tileSize) * subtileSize;
|
||||||
|
const { rgb } = palette;
|
||||||
|
let tr;
|
||||||
|
let tg;
|
||||||
|
let tb;
|
||||||
|
let channelOffset;
|
||||||
|
let posA;
|
||||||
|
let posB;
|
||||||
|
let clr;
|
||||||
|
const linePad = (tileSize + 1) * (subtilesInTile - 1);
|
||||||
|
let amountFullRows = Math.floor(inpTileLength / subtilesInTile);
|
||||||
|
/*
|
||||||
|
* use available data
|
||||||
|
*/
|
||||||
|
for (let row = 0; row < amountFullRows; row += 1) {
|
||||||
|
channelOffset = (offset + row * tileSize) * 3;
|
||||||
|
const max = channelOffset + subtileSize * 3;
|
||||||
|
posA = row * tileSize * subtilesInTile;
|
||||||
|
posB = posA + linePad;
|
||||||
|
while (channelOffset < max) {
|
||||||
|
clr = (inpTile[posA] & 0x3F) * 3;
|
||||||
|
tr = rgb[clr++];
|
||||||
|
tg = rgb[clr++];
|
||||||
|
tb = rgb[clr];
|
||||||
|
posA += subtilesInTile;
|
||||||
|
clr = (inpTile[posB] & 0x3F) * 3;
|
||||||
|
buffer[channelOffset++] = (rgb[clr++] + tr) / 2;
|
||||||
|
buffer[channelOffset++] = (rgb[clr++] + tg) / 2;
|
||||||
|
buffer[channelOffset++] = (rgb[clr] + tb) / 2;
|
||||||
|
posB += subtilesInTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* padding the rest
|
||||||
|
*/
|
||||||
|
[tr, tg, tb] = rgb;
|
||||||
|
if (inpTileLength % subtilesInTile) {
|
||||||
|
channelOffset = (offset + amountFullRows * tileSize) * 3;
|
||||||
|
const max = channelOffset + subtileSize * 3;
|
||||||
|
posA = amountFullRows * tileSize * subtilesInTile;
|
||||||
|
while (channelOffset < max) {
|
||||||
|
if (posA < inpTileLength) {
|
||||||
|
clr = (inpTile[posA] & 0x3F) * 3;
|
||||||
|
buffer[channelOffset++] = (rgb[clr++] + tr) / 2;
|
||||||
|
buffer[channelOffset++] = (rgb[clr++] + tg) / 2;
|
||||||
|
buffer[channelOffset++] = (rgb[clr] + tb) / 2;
|
||||||
|
posA += subtilesInTile;
|
||||||
|
} else {
|
||||||
|
buffer[channelOffset++] = tr;
|
||||||
|
buffer[channelOffset++] = tg;
|
||||||
|
buffer[channelOffset++] = tb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
amountFullRows += 1;
|
||||||
|
}
|
||||||
|
if (amountFullRows < subtileSize) {
|
||||||
|
for (let row = amountFullRows; row < subtileSize; row += 1) {
|
||||||
|
channelOffset = (offset + row * tileSize) * 3;
|
||||||
|
const max = channelOffset + subtileSize * 3;
|
||||||
|
while (channelOffset < max) {
|
||||||
|
buffer[channelOffset++] = tr;
|
||||||
|
buffer[channelOffset++] = tg;
|
||||||
|
buffer[channelOffset++] = tb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
||||||
* @param cell where to add the tile [dx, dy]
|
* @param cell where to add the tile [dx, dy]
|
||||||
|
@ -181,7 +259,7 @@ export async function createZoomTileFromChunk(
|
||||||
const [x, y] = cell;
|
const [x, y] = cell;
|
||||||
const maxTiledZoom = getMaxTiledZoom(canvasSize);
|
const maxTiledZoom = getMaxTiledZoom(canvasSize);
|
||||||
const tileRGBBuffer = new Uint8Array(
|
const tileRGBBuffer = new Uint8Array(
|
||||||
TILE_SIZE * TILE_SIZE * TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL * 3,
|
TILE_SIZE * TILE_SIZE * 3,
|
||||||
);
|
);
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
@ -207,8 +285,9 @@ export async function createZoomTileFromChunk(
|
||||||
na.push([dx, dy]);
|
na.push([dx, dy]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
addIndexedSubtiletoTile(
|
addShrunkenIndexedSubtilesToTile(
|
||||||
palette,
|
palette,
|
||||||
|
TILE_SIZE,
|
||||||
TILE_ZOOM_LEVEL,
|
TILE_ZOOM_LEVEL,
|
||||||
[dx, dy],
|
[dx, dy],
|
||||||
chunk,
|
chunk,
|
||||||
|
@ -219,19 +298,18 @@ export async function createZoomTileFromChunk(
|
||||||
|
|
||||||
if (na.length !== TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL) {
|
if (na.length !== TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL) {
|
||||||
na.forEach((element) => {
|
na.forEach((element) => {
|
||||||
deleteSubtilefromTile(TILE_SIZE, palette, TILE_ZOOM_LEVEL, element, tileRGBBuffer);
|
deleteSubtilefromTile(TILE_SIZE / TILE_ZOOM_LEVEL, palette, TILE_ZOOM_LEVEL, element, tileRGBBuffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const filename = tileFileName(canvasTileFolder, [maxTiledZoom - 1, x, y]);
|
const filename = tileFileName(canvasTileFolder, [maxTiledZoom - 1, x, y]);
|
||||||
try {
|
try {
|
||||||
await sharp(Buffer.from(tileRGBBuffer.buffer), {
|
await sharp(Buffer.from(tileRGBBuffer.buffer), {
|
||||||
raw: {
|
raw: {
|
||||||
width: TILE_SIZE * TILE_ZOOM_LEVEL,
|
width: TILE_SIZE,
|
||||||
height: TILE_SIZE * TILE_ZOOM_LEVEL,
|
height: TILE_SIZE,
|
||||||
channels: 3,
|
channels: 3,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.resize(TILE_SIZE)
|
|
||||||
.png({ options: { compressionLevel: 6 } })
|
.png({ options: { compressionLevel: 6 } })
|
||||||
.toFile(filename);
|
.toFile(filename);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -291,7 +369,7 @@ export async function createZoomedTile(
|
||||||
|
|
||||||
if (na.length !== TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL) {
|
if (na.length !== TILE_ZOOM_LEVEL * TILE_ZOOM_LEVEL) {
|
||||||
na.forEach((element) => {
|
na.forEach((element) => {
|
||||||
deleteSubtilefromTile(TILE_SIZE / 4, palette, TILE_ZOOM_LEVEL, element, tileRGBBuffer);
|
deleteSubtilefromTile(TILE_SIZE / TILE_ZOOM_LEVEL, palette, TILE_ZOOM_LEVEL, element, tileRGBBuffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const filename = tileFileName(canvasTileFolder, [z, x, y]);
|
const filename = tileFileName(canvasTileFolder, [z, x, y]);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user