A "multiplayer" HTML5 <canvas> to which people can connect and make changes over time.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

85 lines
2.0 KiB

// lib/canvas-image.js
// Copyright (C) 2022 Rob Colbert @[email protected]
// License: Apache-2.0
'use strict';
import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
import Jimp from 'jimp';
export default class CanvasImage {
static async getImages (redis) {
const images = [ ];
for (const key of await redis.keys('mpcvs:images:*')) {
const image = await redis.hgetall(key);
image.width = parseInt(image.width, 10);
image.height = parseInt(image.height, 10);
const tokens = key.split(':');
const id = tokens[tokens.length - 1];
images.push({ id, ...image });
}
return images;
}
constructor (id, name) {
this.id = id;
this.name = name;
this.idPrefix = this.id.slice(0, 4);
this.imagePath = path.resolve(__dirname, '..', 'images', this.idPrefix);
this._dirty = false;
}
get dirty ( ) { return this._dirty; }
get key ( ) { return `mpcvs:images:${this.id}`; }
get filename ( ) { return path.join(this.imagePath, `${this.id}.png`); }
get width ( ) { return this.image.bitmap.width; }
get height ( ) { return this.image.bitmap.height; }
create (width, height) {
this.image = new Jimp(width, height, 0xffffffff);
this._dirty = false;
}
async load ( ) {
try {
this.image = await Jimp.read(this.filename);
} catch (error) {
throw error;
} finally {
this._dirty = false;
}
}
async save ( ) {
const filename = this.filename;
console.log('writing image file', filename);
await fs.promises.mkdir(this.imagePath, { recursive: true });
await this.image
.deflateLevel(9)
.writeAsync(this.filename)
;
this._dirty = false;
}
setPixel (pixel) {
let idx = ((pixel.y * this.image.bitmap.width) + pixel.x) * 4;
this.image.bitmap.data[idx++] = pixel.r;
this.image.bitmap.data[idx++] = pixel.g;
this.image.bitmap.data[idx++] = pixel.b;
this._dirty = true;
}
}