type Drawable = ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement; const newCanvas = () => document.createElement('canvas'); export function cropTo(image: Drawable, size: number, flipped = false, canvas: HTMLCanvasElement = newCanvas()) { let width: number; let height: number; // If ImageData if (image instanceof ImageData) { width = image.width; height = image.height; } // If image, bitmap, or canvas else if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement) { width = image.width; height = image.height; } // If video element else if (image instanceof HTMLVideoElement) { width = image.videoWidth; height = image.videoHeight; } else { throw new Error("Unsupported Drawable type"); } const min = Math.min(width, height); const scale = size / min; const scaledW = Math.ceil(width * scale); const scaledH = Math.ceil(height * scale); const dx = scaledW - size; const dy = scaledH - size; canvas.width = canvas.height = size; const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; // Handle ImageData separately if (image instanceof ImageData) { ctx.putImageData(image, ~~(dx / 2) * -1, ~~(dy / 2) * -1); // Adjust this if needed } else { ctx.drawImage(image, ~~(dx / 2) * -1, ~~(dy / 2) * -1, scaledW, scaledH); } if (flipped) { ctx.scale(-1, 1); ctx.drawImage(canvas, size * -1, 0); } return canvas; }