ios低版本出现上传手机照片旋转问题

问题

通信体验活动这个项目中需要用到手机上传照片,在ios低版本手机上会出现上传图片旋转的问题,因此需要对低版本上传的照片根据旋转的角度再次旋转回来。

方法

在判断角度中使用到exif信息查看器

  • 首先在项目中引入exif-js-min
import exifmin from '../assets/exif-js-min'
  • 获取版本信息,对ios大于13.4的系统不做图片旋转
    逆时针四个方向的数字,是6、1、3、8,在ios低与13.4个高于13.4的系统中出现的是相同的,只是低于13.4的会旋转。
// 获取版本信息
getVersion (name) {
    var arr = navigator.userAgent.split(' '); 
    var chromeVersion = '';
    let result = 0;
    const reg = new RegExp(name, 'i')
    for(var i=0;i < arr.length;i++){
        if(reg.test(arr[i]))
        chromeVersion = arr[i]
    }
    if(chromeVersion){
        result = chromeVersion.split('/')[1].split('.');
    } else {
        result = ['0', '0', '0'];
    }
    return result
},
  • 对旋转的图片进行角度旋转
  1. 在低版本上 6:逆时针旋转的90度,需要顺时针旋转90度
  2. 1没有旋转
  3. 8顺时针旋转了90度,需要逆时针旋转90度
  4. 3方向倒了,旋转了180度,需要顺时针或者逆时针旋转180度
//旋转图片函数
rotateImgFun(objectURL,fileName){
let img = new Image();
img.onload = () => {
    let width = img.width;
    let height = img.height;
    let orientation;
    exifmin.getData(img).then(data => {
        orientation = data.orientation || 1;
        if (this.getVersion('safari')[0] >= 605 ) {
            const safariVersion = this.getVersion('version')
            if (safariVersion[0] > 13 && safariVersion[1] > 1) {
                orientation = -1
            }
        } else {
            //  判断 ios 版本进行处理
            // 针对 ios 版本大于 13.4的系统不做图片旋转
            const isIos  = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?) like mac os/)
            if (isIos) {
                let version = isIos[1]
                version = version.split('_')
                if (version[0] > 13 ||  (version[0] >= 13 && version[1] >= 4)) {
                    orientation = -1
                }
            }
        }
        

        let canvas = document.createElement("canvas");
        let ctx = canvas.getContext("2d");
        ctx.save();
        switch (orientation) {
            case 6:
                canvas.width = height;
                canvas.height = width;
                //90 graus
                ctx.translate(height / 2, width / 2);
                ctx.rotate((90 * Math.PI) / 180);
                ctx.translate(-width / 2, -height / 2);
                break;
            case 8:
                canvas.height = width;
                canvas.width = height;
                //-90 graus
                ctx.translate(height / 2, width / 2);
                ctx.rotate((-90 * Math.PI) / 180);
                ctx.translate(-width / 2, -height / 2);
                break;
            case 3:
                canvas.width = width;
                canvas.height = height;
                //180 graus
                ctx.translate(width / 2, height / 2);
                ctx.rotate((180 * Math.PI) / 180);
                ctx.translate(-width / 2, -height / 2);
                break;
            //备份(可能出现的其他情况)
            case 2:
                canvas.width = width;
                canvas.height = height;
                // horizontal flip
                ctx.translate(width, 0);
                ctx.scale(-1, 1);
                break;

            case 4:
                canvas.width = width;
                canvas.height = height;
                // vertical flip
                ctx.translate(0, height);
                ctx.scale(1, -1);
                break;
            case 5:
                // vertical flip + 90 rotate right
                canvas.height = width;
                canvas.width = height;
                ctx.rotate(0.5 * Math.PI);
                ctx.scale(1, -1);
                break;
            case 7:
                // horizontal flip + 90 rotate right
                canvas.height = width;
                canvas.width = height;
                ctx.rotate(0.5 * Math.PI);
                ctx.translate(width, -height);
                ctx.scale(-1, 1);
                break;
            default:
                canvas.width = width;
                canvas.height = height;
        }

        ctx.drawImage(img, 0, 0, width, height);
        ctx.restore();
        let base64 = canvas.toDataURL();
        console.log('base',base64);
        document.getElementById('img').setAttribute('src',base64)
    });
}
img.src = objectURL

},
  • exif-js-min.js
/* eslint-disable */
const Exif = {};

Exif.getData = (img) => new Promise((reslove, reject) => {
  let obj = {};
  getImageData(img).then(data => {
    obj.arrayBuffer = data;
    obj.orientation = getOrientation(data);
    reslove(obj)
  }).catch(error => {
    reject(error)
  })
})

// 这里的获取exif要将图片转ArrayBuffer对象,这里假设获取了图片的baes64
// 步骤一
// base64转ArrayBuffer对象
function getImageData(img) {
  let data = null;
  return new Promise((reslove, reject) => {
    if (img.src) {
      if (/^data\:/i.test(img.src)) { // Data URI
        data = base64ToArrayBuffer(img.src);
        reslove(data)
      } else if (/^blob\:/i.test(img.src)) { // Object URL
        var fileReader = new FileReader();
        fileReader.onload = function (e) {
          data = e.target.result;
          reslove(data)
        };
        objectURLToBlob(img.src, function (blob) {
          fileReader.readAsArrayBuffer(blob);
        });
      } else {
        var http = new XMLHttpRequest();
        http.onload = function () {
          if (this.status == 200 || this.status === 0) {
            data = http.response
            reslove(data)
          } else {
            throw "Could not load image";
          }
          http = null;
        };
        http.open("GET", img.src, true);
        http.responseType = "arraybuffer";
        http.send(null);
      }
    } else {
      reject('img error')
    }
  })
}

function objectURLToBlob(url, callback) {
  var http = new XMLHttpRequest();
  http.open("GET", url, true);
  http.responseType = "blob";
  http.onload = function (e) {
    if (this.status == 200 || this.status === 0) {
      callback(this.response);
    }
  };
  http.send();
}



function base64ToArrayBuffer(base64) {
  base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
  var binary = atob(base64);
  var len = binary.length;
  var buffer = new ArrayBuffer(len);
  var view = new Uint8Array(buffer);
  for (var i = 0; i < len; i++) {
    view[i] = binary.charCodeAt(i);
  }
  return buffer;
}
// 步骤二,Unicode码转字符串
// ArrayBuffer对象 Unicode码转字符串
function getStringFromCharCode(dataView, start, length) {
  var str = '';
  var i;
  for (i = start, length += start; i < length; i++) {
    str += String.fromCharCode(dataView.getUint8(i));
  }
  return str;
}

// 步骤三,获取jpg图片的exif的角度(在ios体现最明显)
function getOrientation(arrayBuffer) {
  var dataView = new DataView(arrayBuffer);
  var length = dataView.byteLength;
  var orientation;
  var exifIDCode;
  var tiffOffset;
  var firstIFDOffset;
  var littleEndian;
  var endianness;
  var app1Start;
  var ifdStart;
  var offset;
  var i;
  // Only handle JPEG image (start by 0xFFD8)
  if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
    offset = 2;
    while (offset < length) {
      if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
        app1Start = offset;
        break;
      }
      offset++;
    }
  }
  if (app1Start) {
    exifIDCode = app1Start + 4;
    tiffOffset = app1Start + 10;
    if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
      endianness = dataView.getUint16(tiffOffset);
      littleEndian = endianness === 0x4949;

      if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
        if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
          firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);

          if (firstIFDOffset >= 0x00000008) {
            ifdStart = tiffOffset + firstIFDOffset;
          }
        }
      }
    }
  }
  if (ifdStart) {
    length = dataView.getUint16(ifdStart, littleEndian);

    for (i = 0; i < length; i++) {
      offset = ifdStart + i * 12 + 2;
      if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {

        // 8 is the offset of the current tag's value
        offset += 8;

        // Get the original orientation value
        orientation = dataView.getUint16(offset, littleEndian);

        // Override the orientation with its default value for Safari (#120)
        // if (IS_SAFARI_OR_UIWEBVIEW) {
        //   dataView.setUint16(offset, 1, littleEndian);
        // }
        break;
      }
    }
  }
  return orientation;
}

export default Exif

你可能感兴趣的:(ios低版本出现上传手机照片旋转问题)