92 lines
2.8 KiB
JavaScript
92 lines
2.8 KiB
JavaScript
import { createCanvas, loadImage } from 'canvas';
|
|
import { putVrcUrl } from './vrcurl.js';
|
|
|
|
var store = {};
|
|
|
|
|
|
export const thumbnailWidth = 360;
|
|
export const thumbnailHeight = 202;
|
|
export const iconWidth = 68;
|
|
export const iconHeight = 68;
|
|
const maxSheetWidth = 2048;
|
|
const maxSheetHeight = 2048;
|
|
const maxThumbnailRowLen = Math.floor(maxSheetWidth / thumbnailWidth); // 5
|
|
//const maxThumbnailColLen = Math.floor(maxSheetHeight / thumbnailHeight); // 10
|
|
//const maxIconRowLen = Math.floor(maxSheetWidth / iconWidth); // 30
|
|
const maxIconRowLen = 3;
|
|
//const maxIconColLen = Math.floor(maxSheetHeight / iconHeight); // 30
|
|
|
|
|
|
async function createImageSheet(thumbnailUrls = [], iconUrls = []) {
|
|
|
|
|
|
var thumbnails = thumbnailUrls.map((url, index) => {
|
|
const x = index % maxThumbnailRowLen * thumbnailWidth;
|
|
const y = Math.floor(index / maxThumbnailRowLen) * thumbnailHeight;
|
|
return {x, y, url};
|
|
});
|
|
|
|
const iconStartX = thumbnailWidth * Math.min(maxThumbnailRowLen, thumbnails.length);
|
|
|
|
var icons = iconUrls.map((url, index) => {
|
|
const x = iconStartX + index % maxIconRowLen * iconWidth;
|
|
const y = Math.floor(index / maxIconRowLen) * iconHeight;
|
|
return {x, y, url};
|
|
});
|
|
|
|
const canvasWidth = Math.max(
|
|
Math.min(thumbnails.length, maxThumbnailRowLen) * thumbnailWidth,
|
|
iconStartX + Math.min(icons.length, maxIconRowLen) * iconWidth
|
|
);
|
|
const canvasHeight = Math.max(thumbnails.length ? thumbnails.at(-1).y + thumbnailHeight : 0, icons.length ? icons.at(-1)?.y + iconHeight : 0);
|
|
|
|
var canvas = createCanvas(Math.min(maxSheetWidth, canvasWidth), Math.min(maxSheetHeight, canvasHeight));
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
var promises = [];
|
|
|
|
if (thumbnails.length) {
|
|
promises = promises.concat(thumbnails.map(({x, y, url}) => (async function(){
|
|
var image = await loadImage(url);
|
|
ctx.drawImage(image, x, y, thumbnailWidth, thumbnailHeight);
|
|
})().catch(error => console.error(error.stack))));
|
|
}
|
|
|
|
if (icons.length) {
|
|
promises = promises.concat(icons.map(({x, y, url}) => (async function(){
|
|
var image = await loadImage(url);
|
|
ctx.drawImage(image, x, y, iconWidth, iconHeight);
|
|
})().catch(error => console.error(error.stack))));
|
|
}
|
|
|
|
await Promise.all(promises);
|
|
return {
|
|
imagesheet: canvas.toBuffer("image/png"),
|
|
thumbnails, icons
|
|
};
|
|
}
|
|
|
|
|
|
export async function makeImageSheetVrcUrl(pool, thumbnailUrls, iconUrls) {
|
|
var num = await putVrcUrl(pool, {type: "imagesheet"});
|
|
var key = `${pool}:${num}`;
|
|
var promise = createImageSheet(thumbnailUrls, iconUrls);
|
|
store[key] = promise;
|
|
promise.then(() => {
|
|
setTimeout(() => {
|
|
if (store[key] === promise) delete store[key];
|
|
}, 1000*60*10); // 10 mins;
|
|
});
|
|
promise.catch(error => {
|
|
console.error(error.stack);
|
|
});
|
|
var {thumbnails, icons} = await promise;
|
|
return {
|
|
vrcurl: num,
|
|
thumbnails, icons
|
|
}
|
|
}
|
|
|
|
export async function getImageSheet(pool, num) {
|
|
return (await store[`${pool}:${num}`])?.imagesheet;
|
|
} |