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);
}