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

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

利用exif.js读取照片的拍摄信息,详见  http://code.ciaoca.com/javascript/exif-js/

这里主要用到Orientation属性。

Orientation属性说明如下:

旋转角度 参数
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如下:

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

以上是转载自:http://blog.csdn.net/linlzk/article/details/48652635

以下是自己在实际的项目开发中所用的方法:

$('#input_photo').on('change',function(){
    if(checkUA.isIOS){
        selectFileImage(this);
    }else{   //发现安卓用这个方法速度快得多。
        var fileval = this.value;
        if(!/\.(jpg|gif|jpeg|png|bmp)$/ig.test(fileval)){
            return false;
        }else{
            var url = window.URL.createObjectURL(file.files[0]);
            viewphoto.src = url;
        }
    }
}
function selectFileImage(fileObj) {
        var file = fileObj.files['0'];
        //图片方向角 added by lzk
        var Orientation = null;  

        if (file) {
            // console.log("正在上传,请稍后...");
            document.querySelector('#fixed').style.display = 'block';
            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 (checkUA.isIOS) {
                        // 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);
                    $("#viewphoto").attr("src", base64);
                    // console.log("上传完成,请稍后...");
                    document.querySelector('#fixed').style.display = 'none';
                };
            };
            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解决ios手机上传竖拍照片旋转90度问题的更多相关文章

  1. iOS 解决图片上传到服务器旋转90度的问题(图片倒置)

    //使用swift的朋友们可以,把这个所在的类的.h,在-Header-Swift.h中一用一下. - (UIImage *)fixOrientation:(UIImage *)aImage { if ...

  2. 移动端上传照片 预览+Draw on Canvas&#39;s Demo(解决 iOS 等设备照片旋转 90 度的 bug)

    背景: 本人的一个移动端H5项目,需求如下: 需求一:手机相册选取或拍摄照片后在页面上预览 需求二:然后绘制在canvas画布上 这里,我们先看一个demo(http://jsfiddle.net/q ...

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

    微信多图片上传必须挨个上传,也就是不能并行,得串行: 那么我们可以定义一个如下所示的上传函数: var serverIds = []; function uploadImages(localImage ...

  4. iOS拍照上传后,在web端显示旋转 Swift+OC版解决方案

    问题描述: 手机头像上传,遇到一个怪现象,就是拍照上传时,手机端显示头像正常,但在web端查看会有一个左旋90度的问题. 并且照片竖怕才会有此问题,横拍不存在. 原因分析: 手机拍照时,用相机拍摄出来 ...

  5. 利用WCF与Android实现图片上传并传参

    利用WCF与Android实现图片上传并传参 最近做一个项目后端使用WCF接收Android手机拍照并带其它参数保存到服务器里:刚好把最近学习的WCF利用上,本以为是个比较简单的功能应该很好实现,没想 ...

  6. 修正ios h5上传图时的图片方向问题

     .ios上传会在exif中带一个 Orientation的属性,这个属性在windows中不会生效,在ios浏览器中会生效,造成图片在windows资源管理器中与ios浏览器中方向不一致  为了用户 ...

  7. 利用jquery+iframe做一个ajax上传效果

    以下是自学it网--中级班上课笔记 网址:www.zixue.it html页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict ...

  8. win7下利用ftp实现华为路由器的上传和下载

    win7下利用ftp实现华为路由器的上传和下载 1.  Win7下ftp的安装和配置 (1)开始->控制面板->程序->程序和功能->打开或关闭Windows功能 (2)在Wi ...

  9. iOS如何上传代码到Github

    iOS如何上传代码到Github 很多iOS开发者想开源自己的代码或者demo,开源到Github是个不错的选择,那么如何上传我们的代码到Github,令所有人可以下载使用呢?这里我们的目的很明确,就 ...

随机推荐

  1. linux 调用java main方法

    #!/bin/shexport LANG=zh_CNtimestamp=`date +%Y%m%d%H%M`/opt/java6/bin/java -Xms128m -Xmx512m -Dfile.e ...

  2. oracle更改用户名

    例如,用户名test1改为test2,在plsql界面中不支持直接更改,只能通过sql更改 1.查询系统user$中的user#值 select user#,name from user$ where ...

  3. Base64简介

    Base64是一种用64个字符来表示任意二进制数据的方法.首先,准备一个包含64个字符的数组:['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... ...

  4. I&#39;m an artist who loves linux (转)

    My father got me a computer for graduation with 512MB RAM and a Pentium processor. It came with Wind ...

  5. mysql高可用架构

    高可用   高可用(High Availabiltity) 应用提供持续不间断(可用)的服务的能力 系统高可用性的评价通常用可用率表示   造成不可用的原因 硬件故障(各种) 预期中的系统软硬件维护 ...

  6. Div自适应高度的方法

    http://www.yutheme.cn/website/index.php/content/view/39/63.html div高度自适应是个比较麻烦的问题,在朋友artery那里看到这个文章, ...

  7. 解决淘宝sui插件后退bug

    淘宝的sui插件在微信里,第一次访问没有问题,跳转走以后,再后退回来, 插件就无法正常加载. 一下是官方给出的说法 切换到的新页面中的 js 不执行 由于浏览器安全性考虑的限制以及可能的 js 重复执 ...

  8. CSS网页布局错位:CSS宽度计算

    为什么计算宽度计算网页像素宽度是为了CSS网页布局整齐与兼容.常见的我们布局左右结构网页或使用padding.margin布局的时候将计算整页宽度,如果不计算无论是宽度过大过小就会出现错位问题. 怎么 ...

  9. 3.html5的文本元素

    如果你看了第一篇的内容,你会发现我的代码是这样的: 文本 <span>文本</span> <scolia>文本</scolia> <scolia ...

  10. Sqli-labs less 20

    Less-20 从源代码中我们可以看到cookie从username中获得值后,当再次刷新时,会从cookie中读取username,然后进行查询. 登录成功后,我们修改cookie,再次刷新时,这时 ...