To keep a whole photo in a square thumbnail, scale both dimensions by the same amount. Choosing a destination width and height separately can stretch a face, even when the exported file has exactly the dimensions you asked for.
Calculate the width ratio and the height ratio, then use the smaller one for both dimensions. Center that rectangle on the canvas. The unused space becomes padding around the whole photo.
For example, a 1200 by 800 source inside a 300 by 300 canvas uses a scale of 0.25. The drawn image is 300 by 200, with 50 pixels above and below. This calculation does not crop the photo.
The function below expects an already decoded image with positive natural dimensions. It also expects positive integer target dimensions. It starts with a fresh canvas, so it does not inherit transforms from an earlier draw. The white background is a deliberate choice for this example; choose the background your destination needs.
Try a portrait and a landscape photo. Check that a circle stays round and that you can still see all four edges of each source. A design that fills the entire square needs an explicit crop rule; it changes which parts of the photo remain visible.
The padding becomes part of an exported thumbnail. Changing the CSS around the canvas later will not remove it from that file.
function containThumbnail(image, width, height) {
if (!image.naturalWidth || !image.naturalHeight ||
!Number.isInteger(width) || width <= 0 ||
!Number.isInteger(height) || height <= 0) {
throw new Error("Positive image and target dimensions required");
}
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
if (!ctx) throw new Error("2D canvas unavailable");
const scale = Math.min(width / image.naturalWidth,
height / image.naturalHeight);
const w = image.naturalWidth * scale;
const h = image.naturalHeight * scale;
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
ctx.drawImage(image, (width - w) / 2, (height - h) / 2, w, h);
return canvas;
}
Reference: MDN drawImage()
I work on Morphio, a HEIC conversion project. The workflow advice here concerns preparing and checking image files.
Top comments (0)