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


Posted in Javascript onNovember 04, 2016

HTML5+canvas进行移动端手机照片上传时,发现iOS手机上传竖拍照片会逆时针旋转90度,横拍照片无此问题;Android手机没这个问题。

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

利用exif.js读取照片的拍摄信息,这里主要用到Orientation属性。

Orientation属性说明如下:详解利用exif.js解决ios手机上传竖拍照片旋转90度问题

下面就直接上代码了。

主要有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如下:

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;  
    }  
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js、css、img等浏览器缓存问题的2种解决方案
Oct 23 Javascript
js document.write()使用介绍
Feb 21 Javascript
一道关于JavaScript变量作用域的面试题
Mar 08 Javascript
AngularJS基础 ng-disabled 指令详解及简单示例
Aug 01 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
Dec 06 Javascript
js 数字、字符串、布尔值的转换方法(必看)
Apr 07 Javascript
ES6扩展运算符用法实例分析
Oct 31 Javascript
用vue写一个仿简书的轮播图的示例代码
Mar 13 Javascript
vue.js响应式原理解析与实现
Jun 22 Javascript
vue登录以及权限验证相关的实现
Oct 25 Javascript
在Vue mounted方法中使用data变量详解
Nov 05 Javascript
Vue实现按钮级权限方案
Nov 21 Javascript
jQuery中 $ 符号的冲突问题及解决方案
Nov 04 #Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
Nov 04 #Javascript
详解js运算符单竖杠“|”与“||”的用法和作用介绍
Nov 04 #Javascript
使用Ajax与服务器(JSON)通信实例
Nov 04 #Javascript
AngularJS过滤器filter用法实例分析
Nov 04 #Javascript
URL的参数中有加号传值变为空格的问题(URL特殊字符)
Nov 04 #Javascript
Angular页面间切换及传值的4种方法
Nov 04 #Javascript
You might like
在数据量大(超过10万)的情况下
2007/01/15 PHP
Zend Studio 无法启动的问题解决方法
2008/12/04 PHP
php文件上传的简单实例
2013/10/19 PHP
PHP修改session_id示例代码
2014/01/08 PHP
PHP导入导出Excel代码
2015/07/07 PHP
php基于环形链表解决约瑟夫环问题示例
2017/11/07 PHP
thinkPHP通用控制器实现方法示例
2017/11/23 PHP
google 搜索框添加关键字实现代码
2010/04/24 Javascript
js+html+css实现鼠标移动div实例
2013/01/30 Javascript
浅析jQuery(function(){})与(function(){})(jQuery)之间的区别
2014/01/09 Javascript
angularjs基础教程
2014/12/25 Javascript
javascript实现避免页面按钮重复提交
2015/01/08 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
javascript简单实现跟随滚动条漂浮的返回顶部按钮效果
2016/08/19 Javascript
JS给Array添加是否包含字符串的简单方法
2016/10/29 Javascript
微信小程序三级联动地址选择器的实例代码
2017/07/12 Javascript
JS实现基于拖拽改变物体大小的方法
2018/01/23 Javascript
leaflet加载geojson叠加显示功能代码
2020/02/21 Javascript
原生js canvas实现鼠标跟随效果
2020/08/02 Javascript
[02:42]岂曰无衣,与子同袍!DOTA2致敬每一位守护人
2020/02/17 DOTA
python爬虫常用的模块分析
2014/08/29 Python
解决Python2.7读写文件中的中文乱码问题
2018/04/12 Python
Python爬取豆瓣视频信息代码实例
2019/11/16 Python
使用Python防止SQL注入攻击的实现示例
2020/05/21 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
Python2.6版本pip安装步骤解析
2020/08/17 Python
python 使用csv模块读写csv格式文件的示例
2020/12/02 Python
HTML5应用之文件上传
2016/12/30 HTML / CSS
服装设计专业自荐书范文
2013/12/30 职场文书
创业资金计划书
2014/02/06 职场文书
高中军训感言500字
2014/02/24 职场文书
信息合作协议书
2014/10/09 职场文书
协议书范文
2015/01/27 职场文书
严以用权专题学习研讨会发言材料
2015/11/09 职场文书
为什么中国式养孩子很累?
2019/08/07 职场文书
python基础学习之递归函数知识总结
2021/05/26 Python