import { fileToDataURL } from "../../util"; import { AvatarOptions, squareImageAvatar } from "./avatar"; import { CanvasLayer, drawLayer } from "./Layers"; export type Ctx = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; export type TemplateRenderFunction = (options: AvatarOptions) => CanvasLayer[]; /** * Generates a canvas that contains the generated image. */ async function generateCanvas( layers: CanvasLayer[], width: number, height: number ) { const canvas = window["OffscreenCanvas"] ? new OffscreenCanvas(width, height) : document.createElement("canvas"); canvas.width = width; canvas.height = height; const ctx: Ctx = canvas.getContext("2d"); for (const layer of layers) { await drawLayer(ctx, layer, width, height); } return canvas; } export async function clientBuildImageUrl( file: File, width: number, height: number, borderWidth: number, zoomFactor: number, templateUrl: string, templateRenderFunction: TemplateRenderFunction = squareImageAvatar ) { const uploadDataUrl = await fileToDataURL(file); const layers: CanvasLayer[] = templateRenderFunction({ width, height, borderWidth, template: templateUrl, src: uploadDataUrl, srcRotation: 1, srcOffsetX: 0, srcOffsetY: 0, zoomFactor, }); const canvas = await generateCanvas(layers, width, height); let url = ""; if (canvas instanceof HTMLCanvasElement) { if (canvas.toBlob) { console.debug("Create Url via HTMLCanvasElement.toBlob"); const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/png")); url = URL.createObjectURL(blob); } else { // Fallback for Internet Explorer, might not work as the data url can become quite long console.debug("Create Url via HTMLCanvasElement.toDataURL"); url = canvas.toDataURL("image/png"); } } else { console.debug("Create Url via OffscreenCanvas.convertToBlob"); const blob = await canvas.convertToBlob(); url = URL.createObjectURL(blob); } return url; }