在显示上传完毕的图片的时候遇到了一个问题, 图片莫名其妙被逆时针旋转了90度就很离谱

如下图

经过一番查询, 原来是 IOS 的相机拍照的时候会把方向角写入到图片里面

因为我用的是 element 的上传组件, 所以先去找了找 issue, 果不其然在 Issues #15162有人和我提出了同样的问题, 官方给的回答是 Sorry, we have no plan to support this. 所以只能尝试自己修复了

基础思路就是

  • 获取图片的方向角
  • 将图片在 canvas 画出
  • 旋转到正常位置
  • 导出为 DataURL
  • DataURL 转换为 File 上传

获取旋转角#

这里我们会用到 exif-js 这个库来获取图片的 orientation (方向角), 如果方向角不为 0 , 就需要吧方向角改回 0

先使用 EXIF.getData 解析图片, 然后 EXIF.getTag 拿到 Orientation返回, 为了调用方便都包装成 Promise

import EXIF from 'exif-js'
 
async get_img_orientation(file) {
return new Promise((resolve, j) => {
EXIF.getData(file, function() {
resolve(EXIF.getTag(this, 'Orientation'))
})
})
}

Orientation 对照表#

Orientation 值 旋转角度
1
6 顺时针90°
8 逆时针90°
3 180°

这时候我们进行判断, 如果 Orientation = 6 那么我们就进行下面的调整

调整图片#

由于我们拿到的是 File 没法直接使用, 需要先变成 Image 对象

async file_to_image(file) {
return new Promise((resolve) => {
const reader = new FileReader()
const img = new Image()
reader.onload = (e) => {
img.src = e.target.result
img.onload = function() {
resolve(img)
}
}
reader.readAsDataURL(file)
})
}

下面的代码参考 VUE uses element UI’s upload component when ios uploads image rotation 90 degrees, 有所修改

去除方向角#

原作者这里是把图片旋转了, 这里只画出来去除了方向角

直接在画布上面画出来, 然后导出

remove_orientation(image, width, height) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
ctx.drawImage(image, 0, 0)
return canvas.toDataURL('image/jpeg')
}

转换为 file#

从base64的DataURL, 去掉标记信息, 后面的数据用 atob 解码, 直接装到 Uint8Array

dataURL_to_file(dataurl, filename) {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
}

这样就拿到了转换好的图片, 如果你喜欢可以 base64 直接上传

结合 Element UI#

如果结合 Element UI 修改 Upload 的话, before-upload 这个函数是不能返回 一个修改后的file的, 所以我们使用 http-request 拦截上传函数来做

先添加一个 :http-request="upload_file"

async upload_file(req) {
let file = req.file
const orient = await this.get_img_orientation(file)
if (orient && orient === 6) {
const img = await this.file_to_image(file)
const data = this.remove_orientation(img, img.width, img.height)
file = this.dataURL_to_file(data, file.name)
}
const payload = new FormData()
payload.append(file.name, file)
const id = await upload_file(payload) // 发送上传请求
this.item.pictures.push(id[0]) // 添加到自己业务里面
}

后~#

= = IOS 上面权限系统好麻烦, Chrome 也调用不了摄像头, 用了 vue-qrcode-reader 扫描二维码 识别率太低了, 要各种摆姿势, 微信上面基本秒扫, 有点考虑用小程序重做这部分了

参考引用#

[1]: VUE uses element UI’s upload component when ios uploads image rotation 90 degrees http://www.programmersought.com/article/6665266668/

原文地址:https://haozi.moe/2020/03/12/%E4%BF%AE%E5%A4%8DIOS%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E6%96%B9%E5%90%91%E9%97%AE%E9%A2%98/

IOS上传图片方向问题的更多相关文章

  1. ios上传图片显示方向错误问题

    IOS 上传图片方向显示错误问题 问题描述 在使用苹果手机上传图片的时候,发现传完的图片显示出来方向是错误的,竖着的图片会变成横着显示(少部分安卓手机也存在这个问题) 产生原因 ios 相机加入了方向 ...

  2. IOS上传图片方法类

    IOS上传图片方法类   iPhone开发中遇到上传图片问题,找到多资料,最终封装了一个类,请大家指点,代码如下 // // RequestPostUploadHelper.h // demodes ...

  3. IOS上传图片

    //原文地址http://www.cnblogs.com/skyblue/archive/2013/05/08/3067108.html,因为以后要用到,搬来存下// // RequestPostUp ...

  4. iOS上传图片详解

    iphone中图像通常存储在4个地方[相册.应用程序包.沙盒.Internet],通过这4个源,我们就可以存取应用图片. 相册 iphone的相册包含摄像头胶卷+用户计算机同步的部分照片.用户可以通过 ...

  5. iOS 屏幕方向

    参考文章:http://www.tuicool.com/articles/e2q6zi 一般的应用,只会支持竖屏正方向一个方向,支持多个屏幕方向的应用还是比较少的. 当时也没搞明白,所以直接就设置了正 ...

  6. iOS上传图片和视频(base64和file)

    前言:iOS开发中经常会使用到图片和视频上传及保存到相册,下面我讲介绍视频图片的两种上传服务器的方法.以阿里云的OSS服务器为例. 友情提示:上传图片方法在APP中使用很广泛,最好单独写一个图片上传的 ...

  7. 微信网页IOS上传图片旋转解决方案

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. 前端手势控制图片插件书写四(图片上传及Ios图片方向问题)

    1.在图片上传中,使用的input的type为File的属性.使用filereader的Api let that = this; var file = document.getElementById( ...

  9. vue iOS上传图片file 出错

    前言 用vue 移动端上传图片在低版本的 ios 手机上 图片转换base64 在转换file 文件类型 会报错 并且报错 “Script Error ” 查阅了github 和一些文档发现 可以吧 ...

随机推荐

  1. Java学习笔记5(API)

    Java API API(Application Programming Interface)指的是应用程序编程接口. String类 String初始化有两种,一个是使用字符串常量初始化一个Stri ...

  2. c语言"##"的使用

    #include<stdio.h> #define Operations(x) operation_ ## x // ## 是黏贴字符串 int Operations(sum)(int x ...

  3. java常用的格式化

    日常工作中,总会遇到一些格式化显示的需求,下面做一些简单的整理 JDK中java.text下提供了格式化常用的工具类,具体结构见下图 时间日期格式化 DateFormat 采用DateFormat.g ...

  4. Java字符串类型详解

    Java 字符串类主要有String.StringBuffer.StringBuilder.StringTokenizer 1.字符串类型底层都是使用char数组进行实现. 2.从jdk1.7以后,S ...

  5. linux中神奇的命令alias

    在linux中大家应该都知道,有些命令和参数特别繁琐,而且还是大量输入这些命令,这个时候我们就可以使用linux中的alias命令来给这些繁琐的命令起别名,但是,alias 命令只对当前终端有效,当终 ...

  6. Docker编写镜像 发布个人网站

    推荐国内镜像中心:网易云镜像----> https://c.163.com/hub#/home  或者歪果镜像---> https://hub.docker.com/ 博客地址:http: ...

  7. 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...

  8. Salesforce LWC学习(十八) datatable展示 image

    本篇参看: https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/documentati ...

  9. WTL中GDI+支持资源文件加载

    WTL中GDI+支持资源文件加载 分类: WTL WTL gdi+ gdi+2013-04-22 17:16 78人阅读 评论(0) 收藏 举报 WTLGDI+c++ 今天遇到一个小问题困扰了.就是G ...

  10. Redis系列(六):数据结构QuickList(快速列表)源码解析

    1.介绍 Redis在3.2版本之前List的底层编码是ZipList和LinkedList实现的 在3.2版本之后,重新引入了QuickList的数据结构,列表的底层都是QuickList实现 当L ...