先看個案例:
很多人會遇到這樣的問題勾哩,一張背景圖片或者img標簽圖片沒有任何角度相關的樣式,圖片卻被旋轉了90度或者180度糠涛,然后瘋狂查看代碼依然找不到原因,其實這是部分圖片由于拍攝時候保存了exif信息。
什么是EXIF
簡單來說欧聘,Exif 信息就是由數(shù)碼相機在拍攝過程中采集一系列的信息,然后把信息放置在我們熟知的 JPEG/TIFF 文件的頭部端盆,也就是說 Exif信息是鑲嵌在 JPEG/TIFF 圖像文件格式內(nèi)的一組拍攝參數(shù)怀骤,它就好像是傻瓜相機的日期打印功能一樣,只不過 Exif信息所記錄的資訊更為詳盡和完備焕妙。Exif 所記錄的元數(shù)據(jù)信息非常豐富蒋伦,主要包含了以下幾類信息:
- 拍攝日期
- 攝器材(機身、鏡頭访敌、閃光燈等
- 拍攝參數(shù)(快門速度凉敲、光圈F值、ISO速度寺旺、焦距爷抓、測光模式等
- 圖像處理參數(shù)(銳化、對比度阻塑、飽和度蓝撇、白平衡等)
- 圖像描述及版權信息
- GPS定位數(shù)據(jù)
- 縮略圖
這里面就包含了圖片的角度信息,就是說你用手機拍照時是不是倒著拍還是側著拍陈莽,這些都是有記錄的渤昌。
有幾種方式去解決這個問題
一虽抄、后端可以利用php的exif擴展中的函數(shù)exif_read_data()去做,具體操作可以只行百度独柑,不做詳細描寫迈窟。
二、js
// 這里的獲取exif要將圖片轉ArrayBuffer對象忌栅,這里假設獲取了圖片的baes64
// 步驟一
// base64轉ArrayBuffer對象
function base64ToArrayBuffer(base64) {
base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
var binary = atob(base64);
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
return buffer;
}
// 步驟二车酣,Unicode碼轉字符串
// ArrayBuffer對象 Unicode碼轉字符串
function getStringFromCharCode(dataView, start, length) {
var str = '';
var i;
for (i = start, length += start; i < length; i++) {
str += fromCharCode(dataView.getUint8(i));
}
return str;
}
// 步驟三,獲取jpg圖片的exif的角度(在ios體現(xiàn)最明顯)
function getOrientation(arrayBuffer) {
var dataView = new DataView(arrayBuffer);
var length = dataView.byteLength;
var orientation;
var exifIDCode;
var tiffOffset;
var firstIFDOffset;
var littleEndian;
var endianness;
var app1Start;
var ifdStart;
var offset;
var i;
// Only handle JPEG image (start by 0xFFD8)
if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
offset = 2;
while (offset < length) {
if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
app1Start = offset;
break;
}
offset++;
}
}
if (app1Start) {
exifIDCode = app1Start + 4;
tiffOffset = app1Start + 10;
if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
endianness = dataView.getUint16(tiffOffset);
littleEndian = endianness === 0x4949;
if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
if (firstIFDOffset >= 0x00000008) {
ifdStart = tiffOffset + firstIFDOffset;
}
}
}
}
}
if (ifdStart) {
length = dataView.getUint16(ifdStart, littleEndian);
for (i = 0; i < length; i++) {
offset = ifdStart + i * 12 + 2;
if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {
// 8 is the offset of the current tag's value
offset += 8;
// Get the original orientation value
orientation = dataView.getUint16(offset, littleEndian);
// Override the orientation with its default value for Safari (#120)
if (IS_SAFARI_OR_UIWEBVIEW) {
dataView.setUint16(offset, 1, littleEndian);
}
break;
}
}
}
return orientation;
}
方法getStringFromCharCode(arrayBuffer)返回的orientation就是圖片的方向也就是旋轉的值索绪,再對應下面的表湖员,對圖片進行處理
大家可以先判斷圖片Exif的orientation值再根據(jù)上表對應的旋轉值,在canvas上對圖片進行反方向旋轉消除影響
三瑞驱、Photoshop另存圖片
如果圖片是單獨的一張或者是固定的又或者不是后臺返回的娘摔,可以通過photoshop重新保存,保存的時候去掉exif信息
四唤反、vue中安裝exif插件就可以獲取Orientation參數(shù)然后做調(diào)整就可以了
這里有我自己項目上傳照片時的處理代碼:
import EXIF from 'exif-js'
selectPhoto(e) {
this.uploadImgClass = '';
if (e.target.files[0].type.indexOf('image/') != 0) {
this.showTopTip('error', this.language.unify_errorFormatImgTip);
return false;
}
this.dialogData = {};
let tthis = this,
reader = new FileReader();
EXIF.getData(e.target.files[0], function() {
let Orientation = EXIF.getTag(this, 'Orientation');
if (Unit.inArray(Orientation, [3, 6, 8]) != -1) {
tthis.uploadImgClass = 'img rotate' + Orientation;
} else {
tthis.uploadImgClass = 'img';
}
});
if (e.target.files[0]) {
this.file = e.target.files[0];
e.target.value = ''; //clear file
reader.readAsDataURL(this.file);
reader.onload = function(e) {
tthis.uploadImg = this.result;
// tthis.text = tthis.language.unify_upload;
tthis.btn = true;
//get width&height
let img = new Image();
img.src = tthis.uploadImg;
img.onload = function() {
tthis.width = img.naturalWidth;
tthis.height = img.naturalHeight;
};
}
}
},
我是定義了類名根據(jù)Orientation的值做了相應旋轉
這里的exif插件不只是可以用來獲取信息還可以用來做攝像頭實時拍照等功能凳寺,總的說來是很方便的
文章部分內(nèi)容引用https://www.mk2048.com/blog/blog.php?id=hbabci10jhaa