解决部分安卓手机上拍出的照片被自动旋转的问题

这篇博客主要讨论了在开发钉钉微应用时遇到的安卓设备上传照片旋转问题。作者介绍了如何利用exif-js库来读取相机镜头的方向信息,并通过canvas重绘图片以修正旋转角度。在图片上传过程中,先检查文件类型,然后转换base64并根据exif信息判断是否需要旋转。如果需要,根据旋转角度进行canvas操作,最后将处理后的图片上传。
摘要由CSDN通过智能技术生成

问题:在做钉钉微应用的时候上传人脸照片时图片发生的旋转,在ios机上没有任何问题,部分安卓机拍照好处有一个自动旋转的过程。

首先我们借助exif-js可以实现相机镜头的读取,不支持IE10以下,可以直接引用的js文件,也可以使用npm安装依赖

npm install exif-js --save
import EXIFfrom 'exif-js';

/index.html引入js
<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>

这个js文件暴露了一个EXIF的全局变量,我们可以把它挂在window对象上,使他变为一个全局变量

<script type="text/javascript">
    window.onload = function () {
      window.EXIF = EXIF
    }
</script>

在上传的file文件中获取相机方向,然后使用convas重绘图片并旋转角度就可以了,我再项目里面使用的是vant-ui

//html
  <van-uploader
	:after-read="afterRead"
     @oversize="onOversize"
     :max-size="2048 * 1024"
   />
 afterRead: async function(file) {
      if (!Array.isArray(file)) {
        if (file.file.type.indexOf("image") == -1) {
          this.$toast("只能上传图片");
          this.vacate.face = "";
        } else {
 		 if (file.file.size > 10485760) {
          let canvas = document.createElement("canvas");
          let context = canvas.getContext("2d");
          let img = new Image();
          img.src = file.content; // 指定图片的DataURL(base64编码数据)
          img.onload = () => {
            canvas.width = 400; // 指定canvas画布大小,该大小为最后生成图片的大小
            canvas.height = 300;
            context.drawImage(img, 0, 0, 400, 300);
            file.content = canvas.toDataURL(file.file.type, 0.92);// 0.92为默认压缩质量
            let files = this.dataURLtoFile(file.content, file.file.name);
            this.uploadImg(files);
          };
        }
      } else {
        this.$toast("不能上传两张图片");
      }
    }
    
    dataURLtoFile(dataurl, filename) {
      // 将base64转换为文件
      let arr = dataurl.split(",");
      let mime = arr[0].match(/:(.*?);/)[1];
      let bstr = atob(arr[1]);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
    uploadImg(file) {
      let _this = this;
      EXIF.getData(file, () => {
        let orientation = null; // 相机方向
        let imgWidth = null; // 图片宽度
        let imgHeight = null; // 图片高度
        EXIF.getAllTags(file);
        orientation = EXIF.getTag(file, "Orientation");
        imgWidth = EXIF.getTag(file, "ImageWidth");
        imgHeight = EXIF.getTag(file, "ImageHeight");
        if (orientation === 6) {
          // 等于6顺时针旋转90度,等于8需要逆时针旋转90度,等于3需要旋转180度
          let canvas = document.createElement("canvas");
          let context = canvas.getContext("2d");
          let img = new Image();
          let reader = new FileReader();
          reader.readAsDataURL(file);
          reader.onload = e => {
            img.src = e.target.result;
            img.onload = () => {
              canvas.width = imgWidth;
              canvas.height = imgHeight;
              context.save(); 
              context.translate(canvas.width / 2, canvas.height / 2);
              context.rotate((90 * Math.PI) / 180); // 旋转角度
              context.drawImage(
                img,
                -(canvas.height / 2),
                -(canvas.width / 2),
                canvas.height,
                canvas.width
              );
              context.restore(); // 恢复状态
              let newImg = canvas.toDataURL("image/jpeg", 1);
              let files = _this.dataURLtoFile(newImg, file.name); // 将base64转为files文件
              let urlImg = window.URL.createObjectURL(files); // 将file转为临时url给组件回显
              this.$set(this.fileList, 0, { url: urlImg, isImage: true });
              this.uploadImgAPI(files);
            };
          };
        } else {
          // 不需要旋转的直接上传
          this.uploadImgAPI(file);
        }
      });
    },
    //上传图片
    async uploadImgAPI(file) {
      const fd = new FormData();
      fd.append("file", file);
      let res = await this.$store.dispatch("loadUploadPicture", fd);
      if (res.code == 200) {
       this.$toast("上传成功");
      }
    },

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值