function apply_image_transformation(meta, fn) {
	const original_canvas = selection ? selection.source_canvas : main_canvas;

	const new_canvas = make_canvas(original_canvas.width, original_canvas.height);

	const original_ctx = original_canvas.ctx;
	const new_ctx = new_canvas.ctx;

	fn(original_canvas, original_ctx, new_canvas, new_ctx);

	if (selection) {
		undoable({
			name: `${meta.name} (${localize("Selection")})`,
			icon: meta.icon,
			soft: true,
		}, () => {
			selection.replace_source_canvas(new_canvas);
		});
	} else {
		deselect();
		cancel();
		undoable({
			name: meta.name,
			icon: meta.icon,
		}, () => {
			saved = false;
			update_title();

			main_ctx.copy(new_canvas);

			// $canvas.trigger("update"); // update handles
			$canvas_area.trigger("resize"); // update handles and magnified canvas size (CSS width/height)
		});
	}
}
Applies an image transformation to the selection, if it exists, or otherwise the whole document.

The transformation function can change the size of the new canvas, and it will update the selection or document accordingly.

@param {{name: string, icon: HTMLImageElement | HTMLCanvasElement}} meta - object containing the name and icon for undo history.
@param {(original_canvas: PixelCanvas, original_ctx: PixelContext, new_canvas: PixelCanvas, new_ctx: PixelContext) => void} fn - The image transformation function to apply.