您的位置:首页 > 移动开发 > IOS开发

利用exif.js解决ios或Android手机上传竖拍照片旋转90度问题

2016-10-10 16:47 645 查看
html5+canvas进行移动端手机照片上传时,发现ios手机上传竖拍照片会逆时针旋转90度,横拍照片无此问题;Android手机没这个问题。

因此解决这个问题的思路是:获取到照片拍摄的方向角,对非横拍的ios照片进行角度旋转修正。

利用exif.js读取照片的拍摄信息,详见 http://code.ciaoca.com/javascript/exif-js/
这里主要
用到Orientation属性。


Orientation
属性说明如下:[/code]

旋转角度参数
1
顺时针90°6
逆时针90°8
180°3
下面就直接上代码了。

主要有html5页面和一个js,示例功能包含了图片压缩和旋转。

自己写的是uploadImage.js。

html5测试页面如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>图片上传</title>
<script type="text/javascript" src="js/jquery-1.8.3.js"></script>
<script type="text/javascript" src="js/uploadPicture/uploadImage.js" ></script>
<script type="text/javascript" src="js/exif.js" ></script>
<script>

</script>
</head>
<body>
<div style="height: 50px; line-height: 50px;text-align: center;border-bottom: 1px solid #171E28;">
上传图片:
<input type="file" accept="image/*" id="uploadImage" capture="camera" onchange="selectFileImage(this);" />
</div>
<div style="margin-top: 10px;">
<img alt="preview" src="" id="myImage"/>
</div>
</body>
</html>
uploadImage.js如下:
[javascript] view plain copy
function selectFileImage(fileObj) {
var file = fileObj.files['0'];
//图片方向角 added by lzk
var Orientation = null;

if (file) {
console.log("正在上传,请稍后...");
var rFilter = /^(image\/jpeg|image\/png)$/i; // 检查图片格式
if (!rFilter.test(file.type)) {
//showMyTips("请选择jpeg、png格式的图片", false);
return;
}
// var URL = URL || webkitURL;
//获取照片方向角属性,用户旋转控制
EXIF.getData(file, function() {
// alert(EXIF.pretty(this));
EXIF.getAllTags(this);
//alert(EXIF.getTag(this, 'Orientation'));
Orientation = EXIF.getTag(this, 'Orientation');
//return;
});

var oReader = new FileReader();
oReader.onload = function(e) {
//var blob = URL.createObjectURL(file);
//_compress(blob, file, basePath);
var image = new Image();
image.src = e.target.result;
image.onload = function() {
var expectWidth = this.naturalWidth;
var expectHeight = this.naturalHeight;

if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
expectWidth = 800;
expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
} else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
expectHeight = 1200;
expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = expectWidth;
canvas.height = expectHeight;
ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
var base64 = null;
//修复ios
if (navigator.userAgent.match(/iphone/i)) {
console.log('iphone');
//alert(expectWidth + ',' + expectHeight);
//如果方向角不为1,都需要进行旋转 added by lzk
if(Orientation != "" && Orientation != 1){
alert('旋转处理');
switch(Orientation){
case 6://需要顺时针(向左)90度旋转
alert('需要顺时针(向左)90度旋转');
rotateImg(this,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
alert('需要顺时针(向右)90度旋转');
rotateImg(this,'right',canvas);
break;
case 3://需要180度旋转
alert('需要180度旋转');
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}

/*var mpImg = new MegaPixImage(image);
mpImg.render(canvas, {
maxWidth: 800,
maxHeight: 1200,
quality: 0.8,
orientation: 8
});*/
base64 = canvas.toDataURL("image/jpeg", 0.8);
}else if (navigator.userAgent.match(/Android/i)) {// 修复android
var encoder = new JPEGEncoder();
base64 = encoder.encode(ctx.getImageData(0, 0, expectWidth, expectHeight), 80);
}else{
//alert(Orientation);
if(Orientation != "" && Orientation != 1){
//alert('旋转处理');
switch(Orientation){
case 6://需要顺时针(向左)90度旋转
alert('需要顺时针(向左)90度旋转');
rotateImg(this,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
alert('需要顺时针(向右)90度旋转');
rotateImg(this,'right',canvas);
break;
case 3://需要180度旋转
alert('需要180度旋转');
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}

base64 = canvas.toDataURL("image/jpeg", 0.8);
}
//uploadImage(base64);
$("#myImage").attr("src", base64);
};
};
oReader.readAsDataURL(file);
}
}

//对图片旋转处理 added by lzk
function rotateImg(img, direction,canvas) {
//alert(img);
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
//var img = document.getElementById(pid);
if (img == null)return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
var height = img.height;
var width = img.width;
//var step = img.getAttribute('step');
var step = 2;
if (step == null) {
step = min_step;
}
if (direction == 'right') {
step++;
//旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
//img.setAttribute('step', step);
/*var canvas = document.getElementById('pic_' + pid);
if (canvas == null) {
img.style.display = 'none';
canvas = document.createElement('canvas');
canvas.setAttribute('id', 'pic_' + pid);
img.parentNode.appendChild(canvas);
}  */
//旋转角度以弧度值为参数
var degree = step * 90 * Math.PI / 180;
var ctx = canvas.getContext('2d');
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
}


再看下Exif.js官网:
http://code.ciaoca.com/javascript/exif-js/
文档目录

使用方法

API 方法

EXIF 标识

相关信息

使用方法

载入 JavaScript 文件

<script src="exif.js"></script>

获取 EXIF 数据

EXIF.getData(document.getElementById('imgElement'), function(){
EXIF.getAllTags(this);
EXIF.getTag(this, 'Orientation');
});


API 方法

名称说明
EXIF.getData(img, callback)获取图像的数据

能兼容尚未支持提供 EXIF 数据的浏览器获取到元数据。

EXIF.getTag(img, tag)获取图像的某个数据
EXIF.getAllTags(img)获取图像的全部数据,值以对象的方式返回
EXIF.pretty(img)获取图像的全部数据,值以字符串的方式返回

EXIF 标识

名称说明
ExifVersionExif 版本
FlashPixVersionFlashPix 版本
ColorSpace色域、色彩空间
PixelXDimension图像的有效宽度
PixelYDimension图像的有效高度
ComponentsConfiguration图像构造
CompressedBitsPerPixel压缩时每像素色彩位
MakerNote制造商设置的信息
UserComment用户评论
RelatedSoundFile关联的声音文件
DateTimeOriginal创建时间
DateTimeDigitized数字化创建时间
SubsecTime日期时间(秒)
SubsecTimeOriginal原始日期时间(秒)
SubsecTimeDigitized原始日期时间数字化(秒)
ExposureTime曝光时间
FNumber光圈值
ExposureProgram曝光程序
SpectralSensitivity光谱灵敏度
ISOSpeedRatings感光度
OECF光电转换功能
ShutterSpeedValue快门速度
ApertureValue镜头光圈
BrightnessValue亮度
ExposureBiasValue曝光补偿
MaxApertureValue最大光圈
SubjectDistance物距
MeteringMode测光方式
Lightsource光源
Flash闪光灯
SubjectArea主体区域
FocalLength焦距
FlashEnergy闪光灯强度
SpatialFrequencyResponse空间频率反应
FocalPlaneXResolution焦距平面X轴解析度
FocalPlaneYResolution焦距平面Y轴解析度
FocalPlaneResolutionUnit焦距平面解析度单位
SubjectLocation主体位置
ExposureIndex曝光指数
SensingMethod图像传感器类型
FileSource源文件
SceneType场景类型(1 == 直接拍摄)
CFAPatternCFA 模式
CustomRendered自定义图像处理
ExposureMode曝光模式
WhiteBalance白平衡(1 == 自动,2 == 手动)
DigitalZoomRation数字变焦
FocalLengthIn35mmFilm35毫米胶片焦距
SceneCaptureType场景拍摄类型
GainControl场景控制
Contrast对比度
Saturation饱和度
Sharpness锐度
DeviceSettingDescription设备设定描述
SubjectDistanceRange主体距离范围
InteroperabilityIFDPointer
ImageUniqueID图像唯一ID
Tiff 相关
名称说明
ImageWidth图像宽度
ImageHeight图像高度
BitsPerSample比特采样率
Compression压缩方法
PhotometricInterpretation像素合成
Orientation拍摄方向
SamplesPerPixel像素数
PlanarConfiguration数据排列
YCbCrSubSampling色相抽样比率
YCbCrPositioning色相配置
XResolutionX方向分辨率
YResolutionY方向分辨率
ResolutionUnit分辨率单位
StripOffsets图像资料位置
RowsPerStrip每带行数
StripByteCounts每压缩带比特数
JPEGInterchangeFormatJPEG SOI 偏移量
JPEGInterchangeFormatLengthJPEG 比特数
TransferFunction转移功能
WhitePoint白点色度
PrimaryChromaticities主要色度
YCbCrCoefficients颜色空间转换矩阵系数
ReferenceBlackWhite黑白参照值
DateTime日期和时间
ImageDescription图像描述、来源
Make生产者
Model型号
Software软件
Artist作者
Copyright版权信息
GPS 相关
名称说明
GPSVersionIDGPS 版本
GPSLatitudeRef南北纬
GPSLatitude纬度
GPSLongitudeRef东西经
GPSLongitude经度
GPSAltitudeRef海拔参照值
GPSAltitude海拔
GPSTimeStampGPS 时间戳
GPSSatellites测量的卫星
GPSStatus接收器状态
GPSMeasureMode测量模式
GPSDOP测量精度
GPSSpeedRef速度单位
GPSSpeedGPS 接收器速度
GPSTrackRef移动方位参照
GPSTrack移动方位
GPSImgDirectionRef图像方位参照
GPSImgDirection图像方位
GPSMapDatum地理测量资料
GPSDestLatitudeRef目标纬度参照
GPSDestLatitude目标纬度
GPSDestLongitudeRef目标经度参照
GPSDestLongitude目标经度
GPSDestBearingRef目标方位参照
GPSDestBearing目标方位
GPSDestDistanceRef目标距离参照
GPSDestDistance目标距离
GPSProcessingMethodGPS 处理方法名
GPSAreaInformationGPS 区功能变数名
GPSDateStampGPS 日期
GPSDifferentialGPS 修正
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: