A crop rectangle passed to drawImage() belongs to the source image. Calculate it from the intrinsic image dimensions, including when CSS makes the preview smaller.
Suppose a decoded image has intrinsic dimensions of 1600 by 1200, and its preview is 400 by 300. A source crop 200 units wide covers one eighth of the image width. A 200-unit selection in the preview covers half its width.
Use naturalWidth and naturalHeight when calculating a centered square for an HTMLImageElement:
function drawSquare(ctx, img, outputSize = 256) {
const side = Math.min(img.naturalWidth, img.naturalHeight);
if (side <= 0) throw new Error("Image has no usable dimensions");
const sx = (img.naturalWidth - side) / 2;
const sy = (img.naturalHeight - side) / 2;
ctx.drawImage(img, sx, sy, side, side, 0, 0, outputSize, outputSize);
}
Decode the image before calling this function. This example assumes a correctly sized destination canvas, an identity drawing transform, and a positive output size. It does not translate a pointer selection from the preview.
For an interactive crop, first convert the selection from the displayed image coordinates into source coordinates. Account for any space around the displayed photo before applying the width and height ratios.
I work on Morphio. In image-workflow notes, I record source coordinates and output dimensions separately so someone can check each calculation.
Top comments (0)