图片旋转处理

浏览器图片旋转的兼容处理

 

需求:


          在项目中,我们经常要实现用户上传图像的功能,由于图像“太大"或者"压缩上传服务器"或者“本地处理图片”,我们经常会用canvas对图片进行2次处理。在最近的一次开发中我发现,ios低系统、ios(13.4.1之后)高系统对图片的旋转处理不同。并且我还研究了android及chrome对旋转图片的处理,下面我研究的成果,分享给大家。

 

手机拍摄旋转图片ios和android的区别:


   用户用手机拍照的时候,会不同方向的旋转拍照,所以手机拍摄的照片都具有exif信息。目前发现:

  1. android手机拍摄的照片,系统会将图片进行旋转,旋转后显示为 “正确的方向",并且oritation的属性值都是0
  2. ios拍摄的照片,系统也会将图片进行,旋转后显示为“正确的方向”,但是oritation的属性值却保留了原值。

 

H5旋转图片的显示问题 ,对比ios系统和android系统


我研究了 ios 低(低系统),ios高(ios高系统13.4.1之后),pc(chrome 84.0.4147.68),android系统。发现ios高和pc处理旋转是相同的。所以下面讲解ios高也代表pc。我用一张oritation为6的图片在不同系统进行了测试,结果如下:

  • ios低: 将图片旋转为正确的方向显示
  • ios高:将图片旋转为正确的方向显示
  • android: 图片旋转方向显示。

          如下图所示:

                            正确方向(想要的方向)                            方向 旋转

                                       

                              ios低,ios高                                                   android

 

H5旋转图片canvas 简单drawImage处理,对比ios高和ios低


        当我们看到上面的显示结果时,我们肯定想ios很智能啊,已经显示出我们想要的结果,其实ios真的很坑。对于图片我们上面说过会经常通过canvas进行处理,我们用canvas进行最简单的drawImage操作, 结果显示如下:

                                 

                                     ios高                                                   ios低,android

 结论: ios低系统在canvas绘制的时候不是以显示的正方向绘制的图片,旋转信息影响着canvas 的绘制,ios高以正确的方向绘制。 

 

通过“H5显示”和“drawImage”分析,结论如下


  1. iosandroid对旋转的图片显示机制不同

  2. ios高ios低 虽然显示相同但是canvas处理时,旋转图片的方向却不同

 

android和ios低的兼容处理


我们发现ios低android系统,在canvas处理的时候都是以 “有旋转方向的图片” 处理的。所以我们的处理方式是,获取图片的旋转信息,canvas 根据旋转信息将图片进行相应的旋转处理,最终将canvas导出正确显示的图片:

  • 这里我们使用了exif.js 获取图片exif信息和MegaPixImage.js进行图片最大尺寸和旋转处理,两个库大家可以在网上查找
function renderFileChangedImg(img, distImg) {
      return new Promise(function (resolve) {
          // MegaPixImage.js 大家可以在网上查找,用户处理图片旋转和大小
          var mpImg = new MegaPixImage(img);
          // img 为用户上传的图片 ,通过exif获取图片的信息
          EXIF.getData(img, () => {
              var allMetaData = EXIF.getAllTags(img);
              // 获取图片的旋转信息 
              var orientation = allMetaData.Orientation;
              mpImg.render(distImg, {
                  maxWidth: 1980,
                  maxHeight: 1980,
                  orientation: orientation
              }, resolve)
          })
      })
  }
  • 我们获取到结果canvas处理后正确的图片后,我们可以回显 “该图片” ,解决android显示旋转的问题,因为该图片没有旋转信息,所以在ios低处理图片的时候,可以以正确的方向处理图片。       

ios 高  的兼容处理

由于 ios高显示的是旋转后正确的方向,canvas 绘制drawImage也是正确的方向,不受旋转信息的影响。所以我们的处理方式和android、ios低不一样 “不用获取旋转信息,不进行旋转处理”

“不进行旋转处理”:是的不旋转处理,如果我们和android或ios低一样,获取旋转信息(假如oritation:6),并且处理。会将一个显示正常、drawImage正常的图片,通过canvas处理反而旋转为一张方向不正确的图片。也就是说ios高不进行旋转处理。

function renderFileChangedImg(img, distImg) {
      return new Promise(function (resolve) {
          var mpImg = new MegaPixImage(img);
          mpImg.render(distImg, {
                      maxWidth: 1980,
                      maxHeight: 1980,
                  }, resolve)
          
      })
  }

 

ios高 和 ios低的判断并实现


上面 “android和ios低的兼容处理”,“ios 高  的兼容处理” 分析过了我们兼容处理图片旋转时,只要区分 ios高和ios低就行,我这边查了好多资料,很少有解决办法,最终发现了一篇文章(https://juejin.im/post/5ec26d3c6fb9a043681f83c2)成功解决了我的问题,感谢这位博主。

// 原理是:如果是原图的是一张 1 * 2 ,oritation为6的图片(逆时针旋转90deg)的图片,ios高 获取的图片尺寸 width为2,height为1,ios低和android获取的图片尺寸 width为1,height为2,实现代码如下

// 用一张特殊的图片来检测当前浏览器是否对带 EXIF 信息的图片进行回正
// 方法来源: https://github.com/blueimp/JavaScript-Load-Image


export function detectImageAutomaticRotation() {
  return new Promise((resolve) => {
    // 一张 2x1 的 JPEG 图片, EXIF Orientation: 6
    const testAutoOrientationImageURL =
    'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' +
    'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' +
    'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
    'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' +
    'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' +
    'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==';
    let isImageAutomaticRotation;
    if (isImageAutomaticRotation === undefined) {
      const img = new Image();

      img.onload = () => {
        // 如果图片变成 1x2,说明浏览器对图片进行了回正
        isImageAutomaticRotation = img.width === 1 && img.height === 2;

        resolve(isImageAutomaticRotation);
      };

      img.src = testAutoOrientationImageURL;
    } else {
      resolve(isImageAutomaticRotation);
    }
  });
}

最终的解决办法

function renderFileChangedImg(img, distImg) {
      return new Promise(function (resolve) {
          // MegaPixImage.js 大家可以在网上查找,用户处理图片旋转和大小
          var mpImg = new MegaPixImage(img);
          // img 为用户上传的图片 ,通过exif获取图片的信息

         detectImageAutomaticRotation().then(result=>{
             // 如果为true,则为ios高,false为ios低和android
             if(result){
                 mpImg.render(distImg, {
                          maxWidth: 1980,
                          maxHeight: 1980
                      }, resolve)
​​​​​​​             }else{
                  EXIF.getData(img, () => {
                      var allMetaData = EXIF.getAllTags(img);
                      // 获取图片的旋转信息 
                      var orientation = allMetaData.Orientation;
                      mpImg.render(distImg, {
                          maxWidth: 1980,
                          maxHeight: 1980,
                          orientation: orientation
                      }, resolve)
                  })
             }
        })
          
      })
  }

留言:


希望能够帮助大家,如果大家有什么建议,可以给我留言、如果喜欢的话,记得点赞哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值