选择图片上传之后,图片旋转问题解决方案(前端)

前端 专栏收录该内容
12 篇文章 0 订阅

图片上传之后,显示为什么会是旋转的呢?

这就要说到图片的 exif

简单来说,Exif 信息就是由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的 JPEG/TIFF 文件的头部,也就是说 Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,它就好像是相机的日期打印功能一样,只不过 Exif信息所记录的资讯更为详尽和完备。Exif 所记录的元数据信息非常丰富,主要包含了以下几类信息:

在这里插入图片描述

而我们的图片会旋转就是这里面的Oriention在捣鬼,那么我们该如何利用它呢?

很简单,我们只要能够知道Oriention的值,知道它往哪旋转了,那么我们反方向旋转过来就好了。

具体怎么做呢?怎么获取到 Oriention的值呢?

https://github.com/exif-js/exif-js 这个可以看到官方的demo

可以使用 exif.js 这个文件来处理,具体直接看代码吧

var img = new Image();

img.src ='图片的base64';

let _this = this;

img.onload = function () {

    EXIF.getData(img, function () {  //判断照片是否旋转

        // EXIF.getAllTags(this);
        let orientation = EXIF.getTag(img, 'Orientation');
        
        //参数说明 方向、图片base64 、图片大小需要转成MB   (图片大小b) / (1024 * 1024) 
         _this.compress(orientation,this,(图片大小需要转成MB), (dataUrl) => {

               //这里的dataUrl就是我们得到的矫正的图片的base64 

         });
         
    });
};

compress(orientation, res, fileSize, callBack) { //res代表上传的图片,fileSize大小图片的大小
    var img = new Image();
    let maxW = 1080;
    img.src = res;
    let _this = this;
    img.onload = function () {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d');
        if (img.width > maxW) {
            img.height *= maxW / img.width;
            img.width = maxW;
        }
        
        if(orientation===8||orientation===6) {

            canvas.width = img.height;
            canvas.height = img.width;

        }else{

            canvas.width = img.width;
            canvas.height = img.height;
        }


        ctx.translate(canvas.width / 2, canvas.height / 2);

        switch (orientation) {

            case 8:

                ctx.rotate(90 * Math.PI / 180);
                ctx.drawImage(img, -(canvas.height / 2), -(canvas.width / 2), canvas.height, canvas.width);


                break;

            //旋转180度
            case 3:

                ctx.rotate(180 * Math.PI / 180);
                ctx.drawImage(img, -(canvas.width / 2), -(canvas.height / 2), canvas.width, canvas.height);

                break;


            //旋转-90度
            case 6:

                ctx.rotate(-90 * Math.PI / 180);
                ctx.drawImage(img, -(canvas.height / 2), -(canvas.width / 2), canvas.height, canvas.width);


                break;

            default:

                ctx.rotate(360 * Math.PI / 180);
                ctx.drawImage(img, -(canvas.width / 2), -(canvas.height / 2), canvas.width, canvas.height);

                break;

        }

        var compressRate = _this.getCompressRate(0.8, fileSize);

        let dataUrl = canvas.toDataURL('image/jpg', compressRate);

        if (callBack) {
            callBack(dataUrl);
        }

    }
}
getCompressRate(allowMaxSize, fileSize) { //计算压缩比率,size单位为MB
    var compressRate = 1;
    if (fileSize / allowMaxSize > 4) {
        compressRate = 0.5;
    } else if (fileSize / allowMaxSize > 3) {
        compressRate = 0.6;
    } else if (fileSize / allowMaxSize > 2) {
        compressRate = 0.7;
    } else if (fileSize > allowMaxSize) {
        compressRate = 0.8;
    } else {
        compressRate = 0.9;
    }
    return compressRate;
}


// 将base64转换成file对象
dataURLtoFile(dataurl, filename = "file") {
    let arr = dataurl.split(",");
    let mime = arr[0].match(/:(.*?);/)[1];
    let suffix = mime.split("/")[1];
    let bstr = atob(arr[1]);
    let n = bstr.length;
    let u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], `${filename}.${suffix}`, {type: mime});
}

其实整个处理就是这么简单了,这是在能够获取到图片的Oriention的情况下,那么还有获取不到的时候么?有的…我就遇到了

首先重要的一点 Oriention ,仅仅是在图片是jpg/jpeg的情况下才能够处理,png是不行的,这点很重要。

那么如果获取不到图片的Oriention怎么办呢?

首先我先说一下我为什么获取不到,经过实测我们的项目中iOS的可以正常获取,Android的不行,究其原因,我发现应该使我们的手机客户端的浏览器容器的问题,

因为这个容器本身修改过一些代码,做过一些自定义适配业务的修改,经过我的多番测试确定是它的问题,那么怎么办呢?

也不敢随意修改和替换容器,这个成本比较高。

最后我使用了一种这种的办法,选择图片之后,让用户手动旋转,让用户告诉我们,应该往哪旋转,然后做处理。

这也是一种不得已的办法。

其实还有一种方式,既然是图片的Oriention值导致了图片的旋转问题,那么我们是否可以修改这个值,或者某些条件下去除这个值呢?

消除图片的exif信息的影响。

https://github.com/hMatoba/piexifjs

我还找到了js来专门干这个事情的,有兴趣的童鞋可以试试。

更多内容,欢迎同步关注作者公众号二维码!
程序员内功修炼手册 主要发布计算机基础、设计模式、计算机网络基础知识,同时重点关注大前端知识
Android、iOS、web前端、Flutter、React Native等,想学习大前端知识的速度来吧,一起学习、一起成长!
qrcode_for_gh_f730c342ff6e_344.jpg

  • 0
    点赞
  • 1
    评论
  • 3
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 1 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

Bee大前端

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值