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

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

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

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

Orientation属性说明如下:

下面就直接上代码了。

主要有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;
    }
  }

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

(0)

相关推荐

  • JS解决IOS中拍照图片预览旋转90度BUG的问题

    上篇文章[Js利用Canvas实现图片压缩功能]中做了图片压缩上传,但是在IOS真机测试的时候,发现图片预览的时候自动逆时针旋转了90度.对于这个bug,我完全不知道问题出在哪里,接下来就是面向百度编程了.通过度娘找到了相关资料,解决方法记录在此.这个问题的具体因素其实我还是不清楚是为何导致的,只有IOS和部分三星手机会出现此bug. 绝大部分的安卓机并无此问题. 解决此问题需要引入一个第三方 JS 库: exif.js 下载地址:https://github.com/exif-js/exif-

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

    HTML5+canvas进行移动端手机照片上传时,发现iOS手机上传竖拍照片会逆时针旋转90度,横拍照片无此问题:Android手机没这个问题. 因此解决这个问题的思路是:获取到照片拍摄的方向角,对非横拍的ios照片进行角度旋转修正. 利用exif.js读取照片的拍摄信息,这里主要用到Orientation属性. Orientation属性说明如下: 下面就直接上代码了. 主要有html5页面和一个js,示例功能包含了图片压缩和旋转. 自己写的是uploadImage.js. html5测试页面

  • 利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层

    大容量文件上传早已不是什么新鲜问题,在.net 2.0时代,HTML5也还没有问世,要实现这样的功能,要么是改web.config,要么是用flash,要么是用一些第三方控件,然而这些解决问题的方法要么很麻烦,比如改配置,要么不稳定,比如文件上G以后,上传要么死掉,要么卡住,通过设置web.config并不能很好的解决这些问题. 这是一个Html5统治浏览器的时代,在这个新的时代,这种问题已被简化并解决,我们可以利用Html5分片上传的技术,那么Plupload则是一个对此技术进行封装的前端脚本

  • 详解JAVA中使用FTPClient工具类上传下载

    详解JAVA中使用FTPClient工具类上传下载 在Java程序中,经常需要和FTP打交道,比如向FTP服务器上传文件.下载文件.本文简单介绍如何利用jakarta commons中的FTPClient(在commons-net包中)实现上传下载文件. 1.写一个javabean文件,描述ftp上传或下载的信息 实例代码: public class FtpUseBean { private String host; private Integer port; private String us

  • 微信JSSDK多图片上传并且解决IOS系统上传一直加载的问题

    微信多图片上传必须挨个上传,也就是不能并行,得串行: 那么我们可以定义一个如下所示的上传函数: var serverIds = []; function uploadImages(localImagesIds) { if (localImagesIds.length === 0) { $.showPreloader('正在提交数据...'); $('form').submit(); } wx.uploadImage({ localId: localImagesIds[0], // 需要上传的图片

  • 详解Ajax和form+iframe 实现文件上传的方法(两种方式)

    自从有html5之后,文件上传变的非常简单.很方便的解决了项目中需要用到的文件上传功能.HTML5支持多图片上传,而且支持ajax上传,而且支持上传之前图片的预览,而且支持图片拖拽上传,而且还是纯粹利用file控件实现,JS代码寥寥,想不让人称赞都难啊! HTML5Ajax上传 html5的上传实现,是需要file控件以及XMLHttpRequest请求.下面是我封装的一个上传插件: function fileUpload(options) { var opts = options || {};

  • 详解Vue调用手机相机和相册以及上传

    组件 <template> <div> <input id="upload_file" type="file" style="display: none;" accept='image/*' name="file" @change="fileChange($event)"/> <div class="image-item space" @clic

  • 详解SpringMVC使用MultipartFile实现文件的上传

    如果需要实现跨服务器上传文件,就是将我们本地的文件上传到资源服务器上,比较好的办法就是通过ftp上传.这里是结合SpringMVC+ftp的形式上传的.我们需要先懂得如何配置springMVC,然后在配置ftp,最后再结合MultipartFile上传文件. springMVC上传需要几个关键jar包,spring以及关联包可以自己配置,这里主要说明关键的jar包 1:spring-web-3.2.9.RELEASE.jar (spring的关键jar包,版本可以自己选择) 2:commons-

  • 详解Vue+axios+Node+express实现文件上传(用户头像上传)

    Vue 页面的代码 <label for='my_file' class="theme-color"> <mu-icon left value="backup"></mu-icon> 修改头像 </label> <input type="file" ref="upload" name="avatar" id='my_file' style="d

  • 详解利用redis + lua解决抢红包高并发的问题

    抢红包的需求分析 抢红包的场景有点像秒杀,但是要比秒杀简单点. 因为秒杀通常要和库存相关.而抢红包则可以允许有些红包没有被抢到,因为发红包的人不会有损失,没抢完的钱再退回给发红包的人即可. 另外像小米这样的抢购也要比淘宝的要简单,也是因为像小米这样是一个公司的,如果有少量没有抢到,则下次再抢,人工修复下数据是很简单的事.而像淘宝这么多商品,要是每一个都存在着修复数据的风险,那如果出故障了则很麻烦. 基于redis的抢红包方案 下面介绍一种基于Redis的抢红包方案. 把原始的红包称为大红包,拆分

随机推荐