【问题标题】:Using EXIF and BinaryFile get an error使用 EXIF 和 BinaryFile 会出错
【发布时间】:2014-06-03 08:20:32
【问题描述】:

我正在尝试在我正在使用的移动网络浏览器中使用input[type='file'] 拍摄照片后在画布中以正确的方向绘制照片:

fileReader.onloadend = function() {
    var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result));

    switch(exif.Orientation){
       case 8:
           ctx.rotate(90*Math.PI/180);
           break;
       case 3:
           ctx.rotate(180*Math.PI/180);
           break;
       case 6:
           ctx.rotate(-90*Math.PI/180);
           break;
    }
};

但我得到:TypeError: First argument to DataView constructor must be an ArrayBuffer?

我怎样才能得到这个数组缓冲区?

我正在使用 EXIF.js 和 BinaryFile.js

【问题讨论】:

  • 你能告诉我们整个FileReader代码吗?
  • 请明确链接您正在使用的库。 exif 库太多了,都叫 exif.js!

标签: javascript filereader exif


【解决方案1】:

对于 ExifJs,您需要将 base64 字符串转换为 ArrayBuffer

function base64ToArrayBuffer (base64) {
    base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
    var binaryString = atob(base64);
    var len = binaryString.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
}

你不需要BinaryFile:

var exif = EXIF.readFromBinaryFile(base64ToArrayBuffer(this.result));

这假设您使用FileReaderreadAsDataURL 来获取this.result

更好的方法 是先将文件作为数组缓冲区读取,而不是将其转换为 base64,然后使用 FileReader.readAsArrayBuffer() 再次返回。类似这样的东西(伪代码):

// `file` = files[0] from input change event
function getFileArrayBuffer(file) {
  return new Promise(function (resolve, reject) {
    var reader = new FileReader();
    reader.onload = function() {
      resolve(new Uint8Array(reader.result));
    }
    reader.readAsArrayBuffer(file);
  });
}

【讨论】:

  • 嗨,我收到这样的错误“未捕获的 DOMException:无法在 'Window' 上执行 'atob':要解码的字符串未正确编码。”因为我正在使用 reader.readAsBinaryString(file);
  • @Dominic - 你能将 FileReader 与 readAsArrayBuffer 一起用于 this.result 并直接在 EXIF.readFromBinaryFile 中使用吗?
  • @NealDavis 不确定,但听起来很可能,如果可以的话,这听起来像是最好的答案:)
  • @AndrewSchultz Np,我还刚刚添加了一些伪代码,我认为这种方法会更有效。可能需要一些调整,但基本上我认为应该可以不必先转换为 base64
【解决方案2】:

@chings228 您必须将 base64 数据传递给 base64ToArrayBuffer,而不是 blob 数据。

function base64ToArrayBuffer (base64) {
    base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
    var binaryString = atob(base64);
    var len = binaryString.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
}

var b64 = "data:image/jpeg;base64,"+$parameters.image;
var exif = EXIF.readFromBinaryFile(base64ToArrayBuffer(b64));
alert(exif.Orientation); 

【讨论】:

  • 在回答评论者的问题时考虑其他格式,因为现在除了与 @Dominic Tobias 重复之外,需要相当长的时间才能意识到您的回答者带来了什么
猜你喜欢
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
相关资源
最近更新 更多