iOS手机竖着拍的照片被旋转了90°的原因以及解决方案

最近项目发现ios竖屏拍照上传图片文件时候,照片自动选中为横屏。
经过测试发现,只有iOS手机竖着拍的照片才会出现这样的问题,而iOS手机横着拍的照片、Android手机拍的照片以及通过屏幕截图、网络下载等途径获得的图片都不会产生这个问题。

经过查找资料发现需要引入了一个叫做 exif.js 的库来实现旋转角度的纠正,它提供了js读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。而拍照方向就是关键所在!

exif.js 获取图像的拍照方向的代码如下:

EXIF.getData(IMG_FILE, function () { // IMG_FILE为图像数据
  var orientation = EXIF.getTag(this, "Orientation");
  console.log("Orientation:" + orientation); // 拍照方向
});

获取拍照方向的结果为1-8的数字:
iOS手机竖着拍的照片被旋转了90°的原因以及解决方案_第1张图片
注意:对于上面的八种方向中,加了*的并不常见,因为它们代表的是镜像方向,如果不做任何的处理,不管相机以任何角度拍摄,都无法出现镜像的情况。

这个表格代表什么意义?我们来看第一行,值为1时,右边两列的值分别为:Row #0 is Top,Column #0 is Left side,其实很好理解,它表示照片的第一行位于顶端,而第一列位于左侧,那么这张照片自然就是以正常角度拍摄的。

而这8种结果,就是第一行与第一列所在的位置的8种组合。

测试发现
(1)iOS手机横着拍的照片,照片方向显示正常。

(2) iOS手机竖着拍的照片,照片旋转了90度

测试发现照片Orientaion信息为:1、3、6、8四种状态。

我们在前端对图片进行像素处理或者drawInRect等操作之后,照片的Orientaion信息,即为拍照方向信息被删除了,所以iOS手机竖着拍的照片又回到了横着的状态,看起来也就是逆时针旋转了90°!

那么如何纠正这个旋转角度呢?
其实思路也很简单:在处理图片之前,先读取并保存图片的拍照方向信息,然后在处理图片之后,再根据拍照方向,对图片进行相应的调整,lrz.js 中的代码如下:

其中,translate是平移变换,scale(-1,1)是向左翻转,rotate是顺时针旋转。

switch (orientation) {
            case 3:
                context.rotate(180 * Math.PI / 180);
                context.drawImage(that, -targetWidth, -targetHeight, targetWidth, targetHeight);
                break;
            case 6:
                context.rotate(90 * Math.PI / 180);
                context.drawImage(that, 0, -targetWidth, targetHeight, targetWidth);
                break;
            case 8:
                context.rotate(270 * Math.PI / 180);
                context.drawImage(that, -targetHeight, 0, targetHeight, targetWidth);
                break;
            case 2:
                context.translate(targetWidth, 0);
                context.scale(-1, 1);
                context.drawImage(that, 0, 0, targetWidth, targetHeight);
                break;
            case 4:
                context.translate(targetWidth, 0);
                context.scale(-1, 1);
                context.rotate(180 * Math.PI / 180);
                context.drawImage(that, -targetWidth, -targetHeight, targetWidth, targetHeight);
                break;
            case 5:
                context.translate(targetWidth, 0);
                context.scale(-1, 1);
                context.rotate(90 * Math.PI / 180);
                context.drawImage(that, 0, -targetWidth, targetHeight, targetWidth);
                break;
            case 7:
                context.translate(targetWidth, 0);
                context.scale(-1, 1);
                context.rotate(270 * Math.PI / 180);
                context.drawImage(that, -targetHeight, 0, targetHeight, targetWidth);
                break;
            default:
                context.drawImage(that, 0, 0, targetWidth,targetHeight);
        }

举例说明 case 2,当图片的拍照方向为2时,即第一行位于顶端,而第一列位于右侧,其实相当于把照片进行了左右的翻转。所以,这里对图片的操作是,先向右平移等于图片宽度的距离,再向左翻转,这相当于以图片水平方向的对称轴为轴进行了左右翻转,然后再以(0,0)为起始点绘制原宽高的图片,即完成了对拍照方向的纠正。

最后
经过一系列的测试,发现确实只有iOS手机的竖拍照片与横拍照片是通过拍照方向来区别的,Android手机无论竖拍还是横拍的照片,拍照方向都为1。

参考文章:https://www.jianshu.com/p/ad4501db178e

你可能感兴趣的:(前端,uni-app,前端)