图片上传压缩校正

2018/12/10 09:28
阅读数 7
import Exif from 'exif-js';
/* eslint-disable func-names */
function ImageProcess(file, callback) {
  let Orientation;
  // 去获取拍照时的信息,解决拍出来的照片旋转问题
  Exif.getData(file, function () {
    Orientation = Exif.getTag(this, 'Orientation');
  });
  // console.log("Orientation", Orientation);
  // 看支持不支持FileReader
  if (!file || !window.FileReader) return;
  if (/^image/.test(file.type)) {
    // 创建一个reader
    const reader = new window.FileReader();
    // 将图片2将转成 base64 格式
    reader.readAsDataURL(file);
    // 读取成功后的回调
    reader.onloadend = function () {
      const img = new window.Image();
      img.src = this.result;
      img.onload = function () {
        // 压缩图片
        const data = ImageCompress(img, Orientation);
        // console.log(dataURItoBlob(data));
        callback(data);
      };
    };
  }
}
function ImageCompress(img, Orientation) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  // 瓦片canvas
  const tCanvas = document.createElement('canvas');
  const tctx = tCanvas.getContext('2d');
  let { width, height } = img;

  // 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
  let ratio = (width * height) / 4000000;
  if (ratio > 1) {
    ratio = Math.sqrt(ratio);
    width /= ratio;
    height /= ratio;
  } else {
    ratio = 1;
  }
  canvas.width = width;
  canvas.height = height;
  // 铺底色
  ctx.fillStyle = '#fff';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // 如果图片像素大于100万则使用瓦片绘制
  let count = (width * height) / 1000000;
  if (count > 1) {
    // 计算要分成多少块瓦片
    count = ~~(Math.sqrt(count) + 1);
    // 计算每块瓦片的宽和高
    const nw = ~~(width / count);
    const nh = ~~(height / count);
    tCanvas.width = nw;
    tCanvas.height = nh;
    for (let i = 0; i < count; i += 1) {
      for (let j = 0; j < count; j += 1) {
        tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
        ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
      }
    }
  } else {
    ctx.drawImage(img, 0, 0, width, height);
  }
  // 修复ios上传图片的时候 被旋转的问题
  if (Orientation && Orientation !== 1) {
    switch (Orientation) {
      case 6: // 需要顺时针(向左)90度旋转
        rotateImg(img, 'left', canvas);
        break;
      case 8: // 需要逆时针(向右)90度旋转
        rotateImg(img, 'right', canvas);
        break;
      case 3: // 需要180度旋转 转两次
        rotateImg(img, 'right', canvas);
        rotateImg(img, 'right', canvas);
        break;
      default: break;
    }
  }
  // 进行最小压缩
  const ndata = canvas.toDataURL('image/jpeg', 0.5);
  // 清除canvas画布的宽高
  tCanvas.width = 0;
  tCanvas.height = 0;
  canvas.width = 0;
  canvas.height = 0;
  // 打印压缩前后的大小,以及压缩比率
  // const initSize = img.src.length;
  // console.log('压缩前:' + initSize);
  // console.log('压缩后:' + ndata.length);
  // console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
  // console.log(ndata);
  return ndata;
}

function rotateImg(img, direction, cvs) {
  const canvas = cvs;
  // 最小与最大旋转方向,图片旋转4次后回到原方向
  const minStep = 0;
  const maxStep = 3;
  if (img == null) return;
  // img的高度和宽度不能在img元素隐藏后获取,否则会出错
  const { width, height } = img;
  let step = 2;
  if (step == null) {
    step = minStep;
  }
  if (direction === 'right') {
    step += 1;
    // 旋转到原位置,即超过最大值
    if (step > maxStep) step = minStep;
  } else {
    step -= 1;
    if (step < minStep) step = maxStep;
  }
  // 旋转角度以弧度值为参数
  const degree = (step * 90 * Math.PI) / 180;
  const 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;
    default: break;
  }
}
function dataURItoBlob(dataURI) {
  const byteString = window.atob(dataURI.split(',')[1]);
  const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  // const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i += 1) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new window.Blob([ia], { type: mimeString });
}
export default ImageProcess;

 

import Exif from 'exif-js';
/* eslint-disable func-names */
function ImageProcess( file, callback) {
let Orientation;
// 去获取拍照时的信息,解决拍出来的照片旋转问题
Exif. getData( file, function () {
Orientation = Exif. getTag( this, 'Orientation');
});
// console.log("Orientation", Orientation);
// 看支持不支持FileReader
if (! file || ! window. FileReader) return;
if ( / ^ image/. test( file. type)) {
// 创建一个reader
const reader = new window. FileReader();
// 将图片2将转成 base64 格式
reader. readAsDataURL( file);
// 读取成功后的回调
reader. onloadend = function () {
const img = new window. Image();
img. src = this. result;
img. onload = function () {
// 压缩图片
const data = ImageCompress( img, Orientation);
// console.log(dataURItoBlob(data));
callback( data);
};
};
}
}
function ImageCompress( img, Orientation) {
const canvas = document. createElement( 'canvas');
const ctx = canvas. getContext( '2d');
// 瓦片canvas
const tCanvas = document. createElement( 'canvas');
const tctx = tCanvas. getContext( '2d');
let { width, height } = img;

// 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio = ( width * height) / 4000000;
if ( ratio > 1) {
ratio = Math. sqrt( ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas. width = width;
canvas. height = height;
// 铺底色
ctx. fillStyle = '#fff';
ctx. fillRect( 0, 0, canvas. width, canvas. height);
// 如果图片像素大于100万则使用瓦片绘制
let count = ( width * height) / 1000000;
if ( count > 1) {
// 计算要分成多少块瓦片
count = ~~( Math. sqrt( count) + 1);
// 计算每块瓦片的宽和高
const nw = ~~( width / count);
const nh = ~~( height / count);
tCanvas. width = nw;
tCanvas. height = nh;
for ( let i = 0; i < count; i += 1) {
for ( let j = 0; j < count; j += 1) {
tctx. drawImage( img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
ctx. drawImage( tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx. drawImage( img, 0, 0, width, height);
}
// 修复ios上传图片的时候 被旋转的问题
if ( Orientation && Orientation !== 1) {
switch ( Orientation) {
case 6: // 需要顺时针(向左)90度旋转
rotateImg( img, 'left', canvas);
break;
case 8: // 需要逆时针(向右)90度旋转
rotateImg( img, 'right', canvas);
break;
case 3: // 需要180度旋转 转两次
rotateImg( img, 'right', canvas);
rotateImg( img, 'right', canvas);
break;
default: break;
}
}
// 进行最小压缩
const ndata = canvas. toDataURL( 'image/jpeg', 0.5);
// 清除canvas画布的宽高
tCanvas. width = 0;
tCanvas. height = 0;
canvas. width = 0;
canvas. height = 0;
// 打印压缩前后的大小,以及压缩比率
// const initSize = img.src.length;
// console.log('压缩前:' + initSize);
// console.log('压缩后:' + ndata.length);
// console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
// console.log(ndata);
return ndata;
}

function rotateImg( img, direction, cvs) {
const canvas = cvs;
// 最小与最大旋转方向,图片旋转4次后回到原方向
const minStep = 0;
const maxStep = 3;
if ( img == null) return;
// img的高度和宽度不能在img元素隐藏后获取,否则会出错
const { width, height } = img;
let step = 2;
if ( step == null) {
step = minStep;
}
if ( direction === 'right') {
step += 1;
// 旋转到原位置,即超过最大值
if ( step > maxStep) step = minStep;
} else {
step -= 1;
if ( step < minStep) step = maxStep;
}
// 旋转角度以弧度值为参数
const degree = ( step * 90 * Math.PI) / 180;
const 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;
default: break;
}
}
function dataURItoBlob( dataURI) {
const byteString = window. atob( dataURI. split( ',')[ 1]);
const mimeString = dataURI. split( ',')[ 0]. split( ':')[ 1]. split( ';')[ 0];
// const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array( byteString. length);
for ( let i = 0; i < byteString. length; i += 1) {
ia[ i] = byteString. charCodeAt( i);
}
return new window. Blob([ ia], { type: mimeString });
}
export default ImageProcess;
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部