最新更新时间:2019年07月03日11:24:00
《猛戳-查看我的博客地图-总有你意想不到的惊喜》
本文内容:exif信息、获取图片角度信息、orientation的值和拍摄方向对照表、图片的方向校正
exif
Exif 信息,由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的 JPEG/TIFF 文件的头部,也就是说 Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,它就好像是傻瓜相机的日期打印功能一样,只不过 Exif信息所记录的资讯更为详尽和完备。Exif 所记录的元数据信息非常丰富,包含:拍摄日期、摄器材、拍摄参数、图像处理参数、图像描述及版权信息、GPS定位数据、缩略图等
获取图片角度信息
/**
* base64转ArrayBuffer对象
* @param base64
* @return buffer
*/
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码转字符串
* @param
* @return
*/
function getStringFromCharCode(dataView, start, length) {
var str = '';
var i;
for (i = start, length += start; i < length; i++) {
str += String.fromCharCode(dataView.getUint8(i));
}
return str;
}
/**
* 获取jpg图片的exif的角度
* @param
* @return
*/
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 (true) {
dataView.setUint16(offset, 1, littleEndian);
}
break;
}
}
}
return orientation;
}
- 获取方法
let orientation = getOrientation(base64ToArrayBuffer(base64));
console.log(orientation);//1 0° 3 180° 6 90° 8 -90°
orientation的值和拍摄方向对照表
拍摄方向 | orientation | 手机旋转方向 | 预览修正值 |
---|---|---|---|
![]() | 1 | -90° | 0° |
![]() | 3 | 90° | 180° |
![]() | 6 | 0° | 90° |
![]() | 8 | 180° | -90° |
注意:
- 存储在手机中的照片如果被编辑旋转过,则无法获取orientation,orientation为undefined,iOS和Android实测;
- 非数码相机(手机)拍摄的图片,则无法获取orientation,orientation为undefined;
图片的方向校正
我们期望的效果是,无论是从哪个方向(n*90°)拍摄的照片,在预览的时候始终是“向上的”
预览修正值 = 手机旋转方向 + 90°
/**
* 校正图片方向
* @param base64 校正前图片base64
* @return base64 校正后“向上的”图片base64
*/
function getUpwardImage(base64){
let orientation = getOrientation(base64ToArrayBuffer(base64));
img.src = base64
img.onload = function () {
let width = img.width, height = img.height;
let compressionRatio = 0.3;//图片压缩率 0~1 0最大压缩率 1不压缩
if(orientation == 3){
canvas.width = width;
canvas.height = height;
ctx.rotate(Math.PI);//预览修正值
ctx.drawImage(img, -width, -height, width, height)
}else if(orientation == 6){
//注意:此处canvas的宽高互换
canvas.width = height;
canvas.height = width;
ctx.rotate(Math.PI / 2);//预览修正值
ctx.drawImage(img, 0, -height, width, height)
}else if(orientation == 8){
//注意:此处canvas的宽高互换
canvas.width = height;
canvas.height = width;
ctx.rotate(-Math.PI / 2);//预览修正值
ctx.drawImage(img, -width, 0, width, height)
}else{
//不旋转原图
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
}
return canvas.toDataURL('image/jpeg', compressionRatio)
};
}
借助第三方库获取exif信息
npm install exif-js --save
import { EXIF } from "exif-js";
EXIF.getData(document.getElementById('imgElement'), function() {
const allMetaData = EXIF.getAllTags(this);
let direction;
if (allMetaData.GPSImgDirection) {
const directionArry = allMetaData.GPSImgDirection; // 方位角
direction = directionArry.numerator / directionArry.denominator;
}
let Longitude;
if (allMetaData.GPSLongitude) {
const LongitudeArry = allMetaData.GPSLongitude;
const longLongitude =
LongitudeArry[0].numerator / LongitudeArry[0].denominator +
LongitudeArry[1].numerator / LongitudeArry[1].denominator / 60 +
LongitudeArry[2].numerator / LongitudeArry[2].denominator / 3600;
Longitude = longLongitude.toFixed(8);
}
let Latitude;
if (allMetaData.GPSLatitude) {
const LatitudeArry = allMetaData.GPSLatitude;
const longLatitude =
LatitudeArry[0].numerator / LatitudeArry[0].denominator +
LatitudeArry[1].numerator / LatitudeArry[1].denominator / 60 +
LatitudeArry[2].numerator / LatitudeArry[2].denominator / 3600;
Latitude = longLatitude.toFixed(8);
}
console.log(direction, Longitude, Latitude);//方向 经度 纬度
});
相关组件
react图片预览组件,传入的所有图片,都以“向上的”形式显示
react-native图片预览组件,获取图片相关信息
参考资料
感谢阅读,欢迎评论^-^