通过纯Javascript重新定位和调整图像大小时图像转换不正确

时间:2018-02-07 00:21:38

标签: javascript image orientation exif

通过纯JS,我试图重新定向JPEG(到1)并将其调整为某些分辨率基准。我无法使逻辑正确;制作的图像使画布处于正确的位置/尺寸,但图像的宽高比混乱并且不适合画布。

例如,以下是在方向最初设置为8的图片上运行代码的结果:

enter image description here

我的代码正确地将其定位到1,但无法使图像适合画布'尺寸

如何修复我的代码?这就是我所拥有的:

var max_img_width = 400;
var wranges = [max_img_width, Math.round(0.8*max_img_width), Math.round(0.6*max_img_width),Math.round(0.4*max_img_width),Math.round(0.2*max_img_width)];

function reorient_and_resize(source_img, img_width, img_height, mime_type, orientation){

  if (4 < orientation && orientation < 9) {
    // switch around height and width
    var temp = null;
    temp = img_width;
    img_width = img_height;
    img_height = temp;
  }

  var new_width = null;
    switch (true) {
      case img_width < wranges[4]: new_width = wranges[4];break;
      case img_width < wranges[3]: new_width = wranges[4];break;
      case img_width < wranges[2]: new_width = wranges[3];break;
      case img_width < wranges[1]: new_width = wranges[2];break;
      case img_width < wranges[0]: new_width = wranges[1];break;
      default: new_width = wranges[0];break;
    }
  var wpercent = (new_width/img_width);
  var new_height = Math.round(img_height*wpercent);

  var canvas = document.createElement('canvas');
  canvas.width = new_width;
  canvas.height = new_height;
  var ctx = canvas.getContext("2d");

  // transform context before drawing image
  switch (orientation) {
    case 2: ctx.transform(-1, 0, 0, 1, new_width, 0); break;
    case 3: ctx.transform(-1, 0, 0, -1, new_width, new_height); break;
    case 4: ctx.transform(1, 0, 0, -1, 0, new_height); break;
    case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
    case 6: ctx.transform(0, 1, -1, 0, new_height, 0); break;
    case 7: ctx.transform(0, -1, -1, 0, new_height, new_width); break;
    case 8: ctx.transform(0, -1, 1, 0, 0, new_width); break;
    default: break;
  }

  ctx.drawImage(source_img, 0, 0, new_width, new_height);
  return dataURItoBlob(canvas.toDataURL(mime_type),mime_type);
}

我怀疑我的画布转换不起作用。请指教。

注意:在没有使用任何第三方库的情况下,让我们坚持使用纯JS。

图像最初看起来如下。此时,方向为1。在测试我的算法之前,我故意将其方向设置为8(之后发现了错误的结果):

enter image description here

2 个答案:

答案 0 :(得分:0)

我无法看到代码中的错误位置,但绝对可能:

var img = new Image();

img.onload = function() {
  var w = this.width;
  var h = this.height;

  var c = document.getElementById('canvas');
  c.width = h;
  c.height = w;
  var ctx = c.getContext('2d');

  ctx.transform(0, -1, 1, 0, 0, w);
  ctx.drawImage(this, 0, 0, w, h);
}

img.src = "https://i.stack.imgur.com/6GmiO.jpg";
canvas {
  border: 2px solid red;
}
<canvas id="canvas" />

答案 1 :(得分:0)

Alnitak的回答指出了我正确的方向。我最终重做了我的调整大小和重定向功能,如下所示:

function reorient_and_resize(source_img, img_width, img_height, mime_type, orientation){

  // flip width and height (when needed)
  switch (orientation) {
    case 2:
    case 3:
    case 4:
      break;
    case 5:
    case 6:
    case 7:
    case 8:
      var temp_width = null;
      temp_width = img_width;
      img_width = img_height;
      img_height = temp_width;
      break;
    default:
      break;
  }

  var new_width = null;
  switch (true) {
    case img_width < wranges[4]: new_width = wranges[4]; break;
    case img_width < wranges[3]: new_width = wranges[4]; break;
    case img_width < wranges[2]: new_width = wranges[3]; break;
    case img_width < wranges[1]: new_width = wranges[2]; break;
    case img_width < wranges[0]: new_width = wranges[1]; break;
    default: new_width = wranges[0]; break;
  }

  var wpercent = (new_width/img_width);
  var new_height = Math.round(img_height*wpercent);

  var canvas = document.createElement('canvas');
  canvas.width = new_width;
  canvas.height = new_height;

  var ctx = canvas.getContext('2d');
  // see for guidance: https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js
   switch (orientation) {
    case 2: 
      ctx.translate(new_width, 0);
      ctx.scale(-1, 1);
      break;//supported
    case 3:
      // rotate 180 degrees left
      ctx.translate(new_width, new_height);
      ctx.rotate(-Math.PI);
      break;//supported
    case 4: 
      // vertical flip
      ctx.translate(0, new_height);
      ctx.scale(1, -1);
      break;//supported
    case 5: 
      // vertical flip + 90 rotate right
      ctx.rotate(0.5 * Math.PI);
      ctx.scale(new_height/new_width,-new_width/new_height);
      break;//supported
    case 6: 
      // rotate 90 degrees right
      ctx.rotate(0.5 * Math.PI);
      ctx.translate(0, -new_width);
      ctx.scale(new_height/new_width,new_width/new_height);
      break;//supported
    case 7:
      // horizontal flip + 90 rotate right
      ctx.rotate(0.5 * Math.PI);
      ctx.translate(new_height, -new_width);
      ctx.scale(-new_height/new_width,new_width/new_height);
      break;
    case 8: 
      // rotate 90 degrees left
      ctx.translate(0, new_height);
      ctx.scale(new_width/new_height,new_height/new_width);
      ctx.rotate(-0.5 * Math.PI);
      break;
    default: 
      break;
  }

  ctx.drawImage(source_img, 0, 0, new_width, new_height);
  return dataURItoBlob(canvas.toDataURL(mime_type),mime_type);
}


// converting image data uri to a blob object
function dataURItoBlob(dataURI,mime_type) {
  var byteString = atob(dataURI.split(',')[1]);//supported
  var ab = new ArrayBuffer(byteString.length);//supported
  var ia = new Uint8Array(ab);//supported
  for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); }//supported
  return new Blob([ab], { type: mime_type });//supported
}

最大的区别在于我如何处理重新定位图像的部分(在行var ctx = canvas.getContext('2d');之后)。转换之前是错误的 - 但不再是。