Clark Kent
Clark Kent

Reputation: 1176

Scale and crop image to specified dimensions in Javascript

I'm trying to scale an image to a specified width and height without distorting the image in Javascript.

I currently have this: https://codesandbox.io/s/practical-diffie-fkzwb

I'm creating a canvas with the desired width and height of the image I want, then I'm translating the source image over. For this example, the source image is a very wide image, and the first destination image has a greater height than width, but is scaled down.

I'm trying to trim off a percentage of the left and right sides of the image to prevent distortion, and still capture most of the image in the new canvas. The current code for drawing the new images looks as follows:

ctx.drawImage(
      image,                 // Source image
      sx + wdx,              // Start x in source
      sy,                    // Start y in source
      w - wdx * 2,           // Source width in dest
      h,                     // Source height in dest
      dx,                    // Start x in dest
      dy,                    // Start y in dest
      desiredWidth,          // Dest width
      desiredHeight          // Dest height
    );

The issue is that the image looks distorted. I tried tweaking the start and end for the source fields, but I'm having difficulties coming up with the right function to appropriately scale these images.

How can I scale and trim these images to the desired width and height?

Upvotes: 1

Views: 729

Answers (1)

Russopotomus
Russopotomus

Reputation: 705

I think the key component you are missing is taking the image aspect ratio into account. I tried this on your code sandbox, I think it does what you want:

let aspectRatio = Math.min(desiredWidth / w, desiredHeight / h);
    let actualW = (aspectRatio * w);
    let actualH = (aspectRatio * h);

    ctx.drawImage(
      image, // Src image.
      0, // Start x in source
      0, // Start y in source
      w, // Source width in dest
      h, // Source height in dest
      (desiredWidth - actualW) / 2, // Start x in dest
      (desiredHeight - actualH) / 2, // Start y in dest
      actualW, // Dest width
      actualH // Dest height
    );

Upvotes: 1

Related Questions