finish transition to sharp
This commit is contained in:
parent
5eb5413d10
commit
b4bf9cd25b
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,7 +151,7 @@ export default async function renderCanvas(
|
||||||
...BACKGROUND_CLR_RGB,
|
...BACKGROUND_CLR_RGB,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
promises.push(
|
promises.push(
|
||||||
drawChunk(
|
drawChunk(
|
||||||
pixelBuffer, unscaledWidth, unscaledHeight,
|
pixelBuffer, unscaledWidth, unscaledHeight,
|
||||||
|
@ -163,6 +161,7 @@ export default async function renderCanvas(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
// scale and convert to png
|
// scale and convert to png
|
||||||
const imageBuffer = await sharp(pixelBuffer, {
|
const imageBuffer = await sharp(pixelBuffer, {
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -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');
|
||||||
|
|
Loading…
Reference in New Issue
Block a user