EXIF-修正图片上传旋转的问题

问题背景:
在移动端使用html5 + canvas进行图片上传时,ios手机竖拍照片时会发生旋转,横拍无此问题,android无此类问题,所以我们希望获取到照片拍摄的方向角,进行旋转修复。

EXIF(Exchangeable Image File)是“可交换图像文件”的缩写,Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,需要注意的是EXIF信息是不支持png,webp等图片格式的。
各种相关信息以及EXIF的其他API,详见 http://code.ciaoca.com/javascript/exif-js/

安装

  1. 通过NPM包安装
npm install exif-js --save
  1. 在HTML中使用script添加js文件
<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>

该包添加了一个全局EXIF变量;因为EXIF.js是异步的,在调用getData或任何其他功能之前,您必须等待图像完全加载,在下面我传入的url是一张base64格式的图片,在新创建Image对象的onload方法中调用EXIF的方法。

// 获取图像的数据

```javascript
getOrientation (url) {
  // url base64格式
  return new Promise(resolve => {
    const img = new Image()
    img.src = url
    img.onload = function () {
      let orientation
      // 获取图像的旋转方向
      EXIF.getData(img, function () {
        EXIF.getAllTags(this)
        orientation = EXIF.getTag(this, 'Orientation')
        resolve(orientation)
      })
    }
  })
}

EXIF提供的API方法
在这里插入图片描述
下面附完整的代码 包括Canvas压缩图片大小、获取图像的旋转方向、修复旋转的图像

<template>
  <div>
    <div style="height: 50px; line-height: 50px;text-align: center;border-bottom: 1px solid #171E28;">
      上传图片:
      <input type="file" accept="image/*" id="uploadImage" @change="selectFileImage"/>
      <!--调取手机摄像头的属性-->
    </div>
    <div style="margin-top: 10px;">
      <img alt="preview" :src="myImage" style="width: 300px"/>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
import EXIF from 'exif-js'
export default {
  data () {
    return {
      myImage: ''
    }
  },
  methods: {
    selectFileImage (fileObj) {
      // 获取到上传的图片文件
      const file = fileObj.target.files[0]
      const reader = new FileReader()
      reader.onload = (evt) => {
        this.getOrientation(evt.target.result).then(res => {
          this.drawCanvas(evt.target.result, file.type, res)
        })
      }
      reader.readAsDataURL(file)
    },
    // 获取图像的数据
    getOrientation (url) {
      // url base64格式
      return new Promise(resolve => {
        const img = new Image()
        img.src = url
        img.onload = function () {
          let orientation
          // 获取图像的旋转方向
          EXIF.getData(img, function () {
            EXIF.getAllTags(this)
            orientation = EXIF.getTag(this, 'Orientation')
            resolve(orientation)
          })
        }
      })
    },
    drawCanvas (result, type, orientation) {
      const img = new Image()
      img.src = result
      img.onload = () => {
        // 绘制canvas 压缩图片
        let expectWidth = img.width
        let expectHeight = img.height
        let dataURL
        // 这里的80012000.8可自定义
        if (img.width > img.height && img.width > 800) {
          expectWidth = 800
          expectHeight = expectWidth * img.height / img.width
        } else if (img.height > img.width && img.height > 1200) {
          expectHeight = 1200
          expectWidth = expectHeight * img.width / img.height
        }
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        canvas.width = expectWidth
        canvas.height = expectHeight
        // 旋转修复
        if (orientation > 1) {
          this.modifyOrientation(canvas, ctx, orientation)
        }
        ctx.drawImage(img, 0, 0, expectWidth, expectHeight)
        if (/image\/jpeg/.test(type) || /image\/jpg/.test(type)) {
          dataURL = canvas.toDataURL('image/jpeg', 0.8)
        } else {
          dataURL = canvas.toDataURL(type)
        }
        // 把旋转后的dataURL转换为需要上传的格式传出
        this.myImage = dataURL
      }
    },
    // 修正ios拍照时旋转问题
    modifyOrientation (canvas, ctx, orientation) {
      const w = canvas.width
      const h = canvas.height
      switch (orientation) {
        case 6: // 需要顺时针(向左)90度旋转
          ctx.rotate(0.5 * Math.PI)
          ctx.translate(0, -h)
          break
        case 8: // 需要逆时针(向右)90度旋转
          ctx.rotate(-0.5 * Math.PI)
          ctx.translate(-w, 0)
          break
        case 3: // 需要180度旋转
          ctx.translate(w, h)
          ctx.rotate(Math.PI)
          break
      }
    }
  }
}
</script>

<style lang="stylus" rel="stylesheet/stylus" scoped>

</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值