export function copyImageResampled( img: HTMLImageElement | HTMLCanvasElement, ctx: CanvasRenderingContext2D, dx: number, dy: number, dWidth: number, dHeight: number ): void { const cpyCanvas = document.createElement('canvas'); const cpyCtx = cpyCanvas.getContext('2d'); // the tmpCanvas is used for storing the last image since the copy canvas should be cleared first (alpha values..) const tmpCanvas = document.createElement('canvas'); const tmpCtx = tmpCanvas.getContext('2d'); // start with original image size cpyCanvas.width = img.width; cpyCanvas.height = img.height; // the tmpCanvas should have the maximum size of the half of the original tmpCanvas.width = Math.floor(img.width * 0.5); tmpCanvas.height = Math.floor(img.height * 0.5); // draw the original image on the copy canvas, this will be the initial state cpyCtx.drawImage(img, 0, 0, cpyCanvas.width, cpyCanvas.height); // the size should be stored to make it reducible let size = { width: Math.floor(img.width), height: Math.floor(img.height), }; let lastSize = size; // Reduce the size by 50% each time in few iterations until the size is less then // 2x time the target size - the motivation for it, is to reduce the aliasing that would have been // created with direct reduction of very big image to small image while (size.width * 0.5 > dWidth) { // reduce the size by the half size = { width: Math.floor(size.width * 0.5), height: Math.floor(size.height * 0.5), }; // clear the area on the tmp canvas, and copy the image from the last state tmpCtx.clearRect(0, 0, lastSize.width + 1, lastSize.height + 1); tmpCtx.drawImage(cpyCanvas, 0, 0, lastSize.width, lastSize.height, 0, 0, size.width, size.height); // clear the area on the copy canvas, and copy the temp data on it cpyCtx.clearRect(0, 0, size.width + 1, size.height + 1); cpyCtx.drawImage(tmpCanvas, 0, 0, size.width, size.height, 0, 0, size.width, size.height); lastSize = size; } ctx.drawImage(cpyCanvas, 0, 0, size.width, size.height, dx, dy, dWidth, dHeight); }