如何使用画布同时调整大小和旋转图像

时间:2019-01-02 06:40:31

标签: html canvas html5-canvas

在上传之前,我必须调整图像的大小和旋转,调整大小是为了缩小图片,旋转是为了纠正iPhone捕获的图像。

这是我正在使用的代码,用于resize,我正在使用较小的画布来重绘图像,以进行旋转,我正在使用画布来执行此操作。 问题是,我的图像仅显示源图像的一部分。如何显示完整图像?

这是源图片

enter image description here

这就是我在代码中得到的:您可以看到旋转是正确的,但是调整大小是不正确的,它剪切了源图像,只保留了一部分。 enter image description here

这就是我想要的。 enter image description here

const img = new Image();
img.src = 'https://i.stack.imgur.com/rzJQD.jpg';
img.onload = e => resize_and_rotate(img, 6);

function resize_and_rotate(img, orientation) {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");

  // limit the image to at most 600px width or 900px height.
  let ratio = img.height / img.width;
  if (img.width > 600) {
    canvas.width = 600;
    canvas.height = canvas.width * ratio;
  } else if (img.height > 900) {
    canvas.height = 900;
    canvas.width = canvas.height / ratio;
  }

  let width = canvas.width;
  let height = canvas.height;
  /*
      For iPhone, landscape mode(with home key point to right) is the correct mode, it orientation is 1
      for portrait mode(home key point to bottom), the image will rotate right by 90 degree.
   */
  if (orientation === 6) { // rotate 90 degree.
    // swap canvas width and height.
    canvas.width = height;
    canvas.height = width;

    // move to the center of the canvas
    ctx.translate(canvas.width / 2, canvas.height / 2);

    // rotate the canvas to the specified degrees
    ctx.rotate(0.5 * Math.PI);

    // since the context is rotated, the image will be rotated also
    ctx.drawImage(img, -img.width / 2, -img.height / 2);

  } else if (orientation === 3) { // rotate 180 degree.
    // 180° rotate left
    ctx.translate(canvas.width, canvas.height);
    ctx.rotate(Math.PI);
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  } else if (orientation === 8) { // rotate 90 degree, counter-clockwise.
    canvas.width = height;
    canvas.height = width;

    // move to the center of the canvas
    ctx.translate(canvas.width / 2, canvas.height / 2);

    // rotate the canvas to the specified degrees
    ctx.rotate(-0.5 * Math.PI);

    // since the context is rotated, the image will be rotated also
    ctx.drawImage(img, -img.width / 2, -img.height / 2);
  } else {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  }

  // return base64 data.
//  let base64 = canvas.toDataURL("image/jpeg");
//  return base64;
  // for SO
  document.body.append(canvas);
}
canvas{max-height: 100vh; max-width: 100vw}

如果我删除以下代码,则结果是正确的,但不会调整图像大小。画布尺寸似乎有问题吗?请帮忙。

 // limit the image to at most 600px width or 900px height.
        let ratio = img.height / img.width;
        if (img.width > 600) {
            canvas.width = 600;
            canvas.height = canvas.width * ratio;
        } else if (img.height > 900) {
            canvas.height = 900;
            canvas.width = canvas.height / ratio;
        }

1 个答案:

答案 0 :(得分:1)

您的问题出在drawImage
您没有使用足够的参数,并且那里没有使用正确的值。

完成转换( translate(center); rotation())之后,您可以正确地尝试反转转换,以便从左上角按需绘制图像。但是,您将图像的原始大小用作 x,y 参数,而不是目标参数。

此外,通过使用3参数版本,您可以将 destinationWidth destinationHeight 设置为图像的原始大小,而您需要画布的宽度和高度:

ctx.drawImage(img, -width / 2, -height / 2, width, height);

const img = new Image();
img.src = 'https://i.stack.imgur.com/rzJQD.jpg';
img.onload = e => resize_and_rotate(img, 6);

function resize_and_rotate(img, orientation) {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");

  // limit the image to at most 600px width or 900px height.
  let ratio = img.height / img.width;
  if (img.width > 600) {
    canvas.width = 600;
    canvas.height = canvas.width * ratio;
  } else if (img.height > 900) {
    canvas.height = 900;
    canvas.width = canvas.height / ratio;
  }

  let width = canvas.width;
  let height = canvas.height;
  /*
      For iPhone, landscape mode(with home key point to right) is the correct mode, it orientation is 1
      for portrait mode(home key point to bottom), the image will rotate right by 90 degree.
   */
  if (orientation === 6) { // rotate 90 degree.
    // swap canvas width and height.
    canvas.width = height;
    canvas.height = width;

    // move to the center of the canvas
    ctx.translate(canvas.width / 2, canvas.height / 2);

    // rotate the canvas to the specified degrees
    ctx.rotate(0.5 * Math.PI);

    // since the context is rotated, the image will be rotated also
    ctx.drawImage(img, -width / 2, -height / 2, width, height);

  } else if (orientation === 3) { // rotate 180 degree.
    // 180° rotate left
    ctx.translate(canvas.width, canvas.height);
    ctx.rotate(Math.PI);
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  } else if (orientation === 8) { // rotate 90 degree, counter-clockwise.
    canvas.width = height;
    canvas.height = width;

    // move to the center of the canvas
    ctx.translate(height / 2, width / 2);

    // rotate the canvas to the specified degrees
    ctx.rotate(-0.5 * Math.PI);

    // since the context is rotated, the image will be rotated also
    ctx.drawImage(img, -width / 2, -height / 2, width, height);
  } else {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, 0, 0, width, height);
  }

  // return base64 data.
//  let base64 = canvas.toDataURL("image/jpeg");
//  return base64;
  // for SO
  document.body.append(canvas);
}
canvas{max-height: 100vh; max-width: 100vw}