kollagen/cli/collages.ts

110 lines
2.5 KiB
TypeScript

import { CollageModes } from "../src/common/collages.ts";
import {
init,
CanvasRenderingContext2D,
EmulatedCanvas2D,
Image,
} from "https://deno.land/x/canvas@v1.3.0/mod.ts";
import { CollageImage } from "../src/common/types.ts";
const canvasKit = await init();
export class ProxyImage implements CollageImage {
private filepath: string | null;
private _image: Image | undefined;
constructor(input: string | Image) {
if (typeof input === "string") {
this.filepath = input;
} else {
this.filepath = null;
this._image = input;
}
}
public get path(): string | null {
return this.filepath;
}
public get image(): Image {
if (!this._image) {
const image = canvasKit.MakeImageFromEncoded(
Deno.readFileSync(this.filepath!)
);
if (!image) {
throw Error(`Failed loading ${this.filepath}!`);
}
this._image = image;
}
return this._image;
}
public get width(): number {
return this.image.width();
}
public get height(): number {
return this.image.height();
}
}
declare module "https://deno.land/x/canvas@v1.3.0/mod.ts" {
interface HTMLCanvasElement {
width: number;
height: number;
getContext(x: "2d"): CanvasRenderingContext2D;
}
}
export class DenoCollageModes extends CollageModes<
CanvasRenderingContext2D,
ProxyImage,
EmulatedCanvas2D
> {
createCanvas(w: number, h: number): EmulatedCanvas2D {
const canvas = canvasKit.MakeCanvas(Math.round(w), Math.round(h));
if (!canvas) {
throw Error("Error initializing canvas.");
}
return canvas;
}
canvasToImage(canvas: EmulatedCanvas2D): PromiseLike<ProxyImage> {
const image = canvasKit.MakeImageFromEncoded(canvas.toBuffer());
if (!image) {
throw Error("Something went wrong converting canvas to image.");
}
return Promise.resolve(new ProxyImage(image));
}
drawImage(
ctx: CanvasRenderingContext2D,
image: ProxyImage,
sx: number,
sy: number,
sw: number,
sh: number,
dx: number,
dy: number,
dw: number,
dh: number
): void {
ctx.drawImage(image.image, sx, sy, sw, sh, dx, dy, dw, dh);
}
fillText(
ctx: CanvasRenderingContext2D,
text: string,
fontSize: number,
x: number,
y: number,
maxWidth: number
): void {
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = "white";
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.fillText(text, x, y, maxWidth);
}
}
export const denoCollageModes = new DenoCollageModes();