uni-app的H5项目利用EXIF解决部分手机图片上传旋转的问题

公司项目中总结的一点经验,给有遇到类似问题的小伙伴提供一下思路。水平浅,代码不规整的地方,望轻喷。
部分未解决问题(其他角度拍照无法翻转)
1.手机必须支持重力感应,不然Orientation值是不变的;
2.有部分手机(R11),拍照不含有Orientation值;

node安装 exif-js
npm install exif-js -S

默认浏览器不会对带 EXIF 信息的图片进行回正,之前确实不会。但是自从 iOS 更新到 13.4.1 后,浏览器支持自动回正了。
####增加判断浏览器是否支持带EXIF的图片自动回正
文件名 IsAutoRotateImg.js

// 判断浏览器是否支持对图片进行回正操作
// 一张 2x1 的 JPEG 图片, EXIF Orientation: 6
const testAutoOrientationImageURL =
	'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' +
	'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' +
	'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
	'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' +
	'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' +
	'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==';
let isImageAutomaticRotation;

export function detectImageAutomaticRotation() {
	return new Promise((resolve) => {
		if (isImageAutomaticRotation === undefined) {
			const img = new Image();

			img.onload = () => {
				// 如果图片变成 1x2,说明浏览器对图片进行了回正
				isImageAutomaticRotation = img.width === 1 && img.height === 2;
				resolve(isImageAutomaticRotation);
			};
			img.src = testAutoOrientationImageURL;
		} else {
			// console.log('isImageAutomaticRotation === undefined');
			resolve(isImageAutomaticRotation);
		}
	});
}

处理图片旋转,获取图片的Orientation,根据Orientation的值去旋转图片

import { EXIF } from "exif-js"
//引入判断浏览器是否支持带EXIF的图片自动回正
import { detectImageAutomaticRotation } from "@/common/IsAutoRotateImg.js"
//imgFile 为 文件类型
const _rotateImg = (imgFile) => {
	console.log(imgFile);
	return new Promise((resolve, reject) => {
		EXIF.getData(imgFile, function() {
			console.log('进入getdata')
			let exifTags = EXIF.getAllTags(this);
			let reader = new FileReader();
			reader.readAsDataURL(imgFile);
			reader.onload = e => {
				let imgData = e.target.result;
				// 判断浏览器是否支持对图片进行回正操作
				detectImageAutomaticRotation().then(res => {
					//res为true时。浏览器支持对带 EXIF 信息的图片进行自动回正
					if (res) {
						return resolve(imgData)
					}
					//res为false时。执行js,对带 EXIF 信息的图片进行回正
					// 8 表示 顺时针转了90
					// 3 表示 转了 180
					// 6 表示 逆时针转了90
					if (
						exifTags.Orientation == 8 ||
						exifTags.Orientation == 3 ||
						exifTags.Orientation == 6
					) {
						//翻转
						//获取原始图片大小
						const img = new Image();
						img.src = imgData;
						img.onload = function() {
							let cvs = document.createElement('canvas');
							let ctx = cvs.getContext('2d');
							//如果旋转90
							if (
								exifTags.Orientation == 8 ||
								exifTags.Orientation == 6
							) {
								cvs.width = img.height;
								cvs.height = img.width;
							} else {
								cvs.width = img.width;
								cvs.height = img.height;
							}
							if (exifTags.Orientation == 6) {
								//原图逆时针转了90, 所以要顺时针旋转90
								ctx.rotate(Math.PI / 180 * 90);
								ctx.drawImage(
									img,
									0,
									0,
									img.width,
									img.height,
									0,
									-img.height,
									img.width,
									img.height
								);
							}
							if (exifTags.Orientation == 3) {
								//原图逆时针转了180, 所以顺时针旋转180
								ctx.rotate(Math.PI / 180 * 180);
								ctx.drawImage(
									img,
									0,
									0,
									img.width,
									img.height,
									-img.width,
									-img.height,
									img.width,
									img.height
								);
							}
							if (exifTags.Orientation == 8) {
								//原图顺时针旋转了90, 所以要你时针旋转90
								ctx.rotate(Math.PI / 180 * -90);
								ctx.drawImage(
									img,
									0,
									0,
									img.width,
									img.height,
									-img.width,
									0,
									img.width,
									img.height
								);
							}
							resolve(cvs.toDataURL('image/jpeg'));
						}
					} else {
						resolve(imgData);
					}
				})
			}
		});
	});
}
export default _rotateImg

参考资料:http://www.zyiz.net/tech/detail-135910.html
https://www.cnblogs.com/jrg-Archer/p/11659910.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值