finish transition to sharp

This commit is contained in:
HF 2023-05-30 19:48:31 +02:00
parent 5eb5413d10
commit b4bf9cd25b
3 changed files with 54 additions and 47 deletions

View File

@ -1,4 +1,5 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import sharp from 'sharp';
import { import {
TILE_SIZE, TILE_SIZE,
@ -9,7 +10,6 @@ async function fetchBaseChunk(
palette, palette,
zoom, zoom,
cx, cy, cx, cy,
tile,
) { ) {
const url = `https://pixelplanet.fun/chunks/${canvasId}/${cx}/${cy}.bmp`; const url = `https://pixelplanet.fun/chunks/${canvasId}/${cx}/${cy}.bmp`;
console.log(`Fetching ${url}`); console.log(`Fetching ${url}`);
@ -24,10 +24,17 @@ async function fetchBaseChunk(
throw new Error(`Chunk faulty or not found`); throw new Error(`Chunk faulty or not found`);
} }
function fetchTile(canvasId, zoom, cx, cy, tile) { async function fetchTile(canvasId, zoom, cx, cy) {
const url = `https://pixelplanet.fun/tiles/${canvasId}/${zoom}/${cx}/${cy}.webp`; const url = `https://pixelplanet.fun/tiles/${canvasId}/${zoom}/${cx}/${cy}.webp`;
console.log(`Fetching ${url}`); console.log(`Fetching ${url}`);
return sharp(url).removeAlpha().raw().toBuffer(); const response = await fetch(url);
if (response.ok) {
const arrayBuffer = await response.arrayBuffer();
if (arrayBuffer.byteLength) {
return sharp(arrayBuffer).removeAlpha().raw().toBuffer();
}
}
throw new Error(`Chunk faulty or not found`);
} }
/** /**
@ -47,13 +54,12 @@ export default async function (
const canvasId = canvas.id; const canvasId = canvas.id;
try { try {
if (canvas.maxTiledZoom === zoom) { if (canvas.maxTiledZoom === zoom) {
return await fetchBaseChunk(canvasId, canvas.palette, zoom, cx, cy, tile); return await fetchBaseChunk(canvasId, canvas.palette, zoom, cx, cy);
} else { } else {
return await fetchTile(canvasId, zoom, cx, cy, tile); return await fetchTile(canvasId, zoom, cx, cy);
} }
} catch () { } catch (err) {
console.log(`Chunk ${cx} / ${cy} - ${zoom} is empty of faulty`); console.log(`Chunk ${cx} / ${cy} - ${zoom}: ${err.message}`);
return Buffer.allocUnsafe(0); return Buffer.allocUnsafe(0);
} }
return tile;
} }

View File

@ -32,17 +32,13 @@ async function fillRect(
h += y; h += y;
y = 0; y = 0;
} }
if (w > width) { if (w + x > width) {
w = width; w = width - x;
} }
if (h > height) { if (h + y > height) {
h = height; h = height - y;
} }
if (w < 0 || h < 0) { const rowMax = y + h;
// out of image bounds
return;
}
const rowMax = r + h;
for (let row = y; row < rowMax; row += 1) { for (let row = y; row < rowMax; row += 1) {
let pos = (row * width + x) * 3; let pos = (row * width + x) * 3;
const max = pos + w * 3; const max = pos + w * 3;
@ -62,27 +58,27 @@ async function drawChunk(
const chunkBuffer = await getChunk(canvas, tiledZoom, xc, yc); const chunkBuffer = await getChunk(canvas, tiledZoom, xc, yc);
const [ emptyR, emptyG, emptyB ] = canvas.palette.rgb; const [ emptyR, emptyG, emptyB ] = canvas.palette.rgb;
let row = Math.max(-yOff, 0); let row = Math.max(-yOff, 0);
const rowMax = Math.min(TILE_SIZE - yOff + height, TILE_SIZE); const rowMax = (TILE_SIZE + yOff > height) ? height - yOff : TILE_SIZE;
const colMin = Math.max(-xOff, 0); const colMin = Math.max(-xOff, 0);
const colMax = Math.min(TILE_SIZE - xOff + width, TILE_SIZE); const colMax = (TILE_SIZE + xOff > width) ? width - xOff : TILE_SIZE;
if (colMax < 0 || rowMax < 0) { if (colMax < 0 || rowMax < 0) {
// out of image bounds // out of image bounds
return; return;
} }
const cutWidth = colMax - colMin; const cutWidth = colMax - colMin;
for (; row < rowMax; row += 1) { for (; row < rowMax; row += 1) {
let pos = (row * TILE_SIZE + colMin) * 3; let ib = (row * TILE_SIZE + colMin) * 3;
let pos = ((row + yOff) * width + colMin + xOff) * 3;
const max = pos + cutWidth * 3; const max = pos + cutWidth * 3;
let ib = ((row + yOff) * width + colMin + xOff) * 3;
while (pos < max) { while (pos < max) {
if (pos < chunkBuffer.length) { if (ib < chunkBuffer.byteLength) {
buffer[ib++] = chunkBuffer[pos++]; buffer[pos++] = chunkBuffer[ib++];
buffer[ib++] = chunkBuffer[pos++]; buffer[pos++] = chunkBuffer[ib++];
buffer[ib++] = chunkBuffer[pos++]; buffer[pos++] = chunkBuffer[ib++];
} else { } else {
buffer[ib++] = emptyR; buffer[pos++] = emptyR;
buffer[ib++] = emptyG; buffer[pos++] = emptyG;
buffer[ib++] = emptyB; buffer[pos++] = emptyB;
} }
} }
} }
@ -98,6 +94,7 @@ async function drawChunk(
* @param height height of image (optional) * @param height height of image (optional)
*/ */
export default async function renderCanvas( export default async function renderCanvas(
title,
canvas, canvas,
x, x,
y, y,
@ -125,10 +122,10 @@ export default async function renderCanvas(
const relScaleW = width / unscaledWidth; const relScaleW = width / unscaledWidth;
const relScaleH = height / unscaledHeight; const relScaleH = height / unscaledHeight;
// canvas coordinates of corners // canvas coordinates of corners
const tlX = Math.floor(x - unscaledWidth / 2 / relScaleW); const tlX = Math.floor(x - width / 2 / scale);
const tlY = Math.floor(y - unscaledHeight / 2 / relScaleH); const tlY = Math.floor(y - height / 2 / scale);
const brX = Math.floor(x - 1 + unscaledWidth / 2 / relScaleW); const brX = Math.floor(x - 1 + width / 2 / scale);
const brY = Math.floor(y - 1 + unscaledHeight / 2 / relScaleH); const brY = Math.floor(y - 1 + height / 2 / scale);
// chunk coordinates of chunks in corners // chunk coordinates of chunks in corners
const tlCX = coordToChunk(tlX, canvasSize, tiledScale); const tlCX = coordToChunk(tlX, canvasSize, tiledScale);
const tlCY = coordToChunk(tlY, canvasSize, tiledScale); const tlCY = coordToChunk(tlY, canvasSize, tiledScale);
@ -142,10 +139,11 @@ export default async function renderCanvas(
const promises = []; const promises = [];
for (let xc = tlCX; xc <= brCX; xc += 1) { for (let xc = tlCX; xc <= brCX; xc += 1) {
for (let yc = tlCY; yc <= brCY; yc += 1) { for (let yc = tlCY; yc <= brCY; yc += 1) {
const xOff = chunkToCoord(xc, canvasSize, tiledScale) - tlX; const xOff = Math.round((chunkToCoord(xc, canvasSize, tiledScale) - tlX) * tiledScale);
const yOff = chunkToCoord(yc, canvasSize, tiledScale) - tlY; const yOff = Math.round((chunkToCoord(yc, canvasSize, tiledScale) - tlY) * tiledScale);
if (xc < 0 || xc >= chunkMax || yc < 0 || yc >= chunkMax) { if (xc < 0 || xc >= chunkMax || yc < 0 || yc >= chunkMax) {
// out of canvas bounds // out of canvas bounds
console.log(`Chunk ${xc}, ${yc} out of canvas bounds`);
promises.push( promises.push(
fillRect( fillRect(
pixelBuffer, unscaledWidth, unscaledHeight, pixelBuffer, unscaledWidth, unscaledHeight,
@ -153,14 +151,15 @@ export default async function renderCanvas(
...BACKGROUND_CLR_RGB, ...BACKGROUND_CLR_RGB,
), ),
); );
} else {
promises.push(
drawChunk(
pixelBuffer, unscaledWidth, unscaledHeight,
xOff, yOff,
canvas, tiledZoom, xc, yc,
),
);
} }
promises.push(
drawChunk(
pixelBuffer, unscaledWidth, unscaledHeight,
xOff, yOff,
canvas, tiledZoom, xc, yc,
),
);
} }
} }
await Promise.all(promises); await Promise.all(promises);
@ -172,13 +171,13 @@ export default async function renderCanvas(
channels: 3, channels: 3,
}, },
}) })
.resize({ width, height }) .resize({ width, height, kernel: 'nearest' })
.png() .png()
.toBuffer(); .toBuffer();
return { return {
image: imageBuffer.buffer, image: imageBuffer,
name: `ppfun-snap-${canvas.title}_${x}_${y}_${z}.png`, name: `ppfun-snap-${title}.png`,
type: 'image/png', type: 'image/png',
w: width, w: width,
h: height, h: height,

View File

@ -177,10 +177,12 @@ class PPfunMatrixBridge {
const userId = event.sender; const userId = event.sender;
// block none :pixelplanet.fun users /*
* block none :pixelplanet.fun users
if (!userId.endsWith(this.domain)) { if (!userId.endsWith(this.domain)) {
return; return;
} }
*/
const uid = (userId.startsWith(`@${this.prefix}_`) const uid = (userId.startsWith(`@${this.prefix}_`)
&& userId.endsWith(this.domain)) && userId.endsWith(this.domain))
@ -239,7 +241,7 @@ class PPfunMatrixBridge {
async run() { async run() {
console.log('STARTING MATRIX CONNECTION'); console.log('STARTING MATRIX CONNECTION');
await this.matrixBridge.run(this.port, null, 'localhost'); await this.matrixBridge.run(this.port, null, '127.0.0.1');
console.log('STARTING PPFUN CONNECTION'); console.log('STARTING PPFUN CONNECTION');
await this.ppfunSocket.run(); await this.ppfunSocket.run();
console.log('BRIDGE CONNECTED'); console.log('BRIDGE CONNECTED');