{ // 压缩图片 const orientation = Exif.getTag(file, "Orientation"); const reader = ...">

JavaScript 前端图片压缩方案,支持方向识别和修正

可以用于浏览器的图片压缩方案

import Exif from "exif-js"; // 图片信息识别库,用于识别方向信息

const compress = (file, result) => {
  // 压缩图片
  const orientation = Exif.getTag(file, "Orientation");
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onloadend = ev => {
    const imgFile = ev.target.result;
    const img = new Image();
    img.src = imgFile;
    img.onload = () => {
      const compressBase64 = doCompress(img, orientation);
      result(compressBase64); //回调结果
    };
  };
};

const doCompress = (img, orientation) => {
  let imgWidth = img.width;
  let imgHeight = img.height;
  if (imgWidth > 1334) {
    imgHeight = imgHeight * (1334 / imgWidth);
    imgWidth = 1334;
  } else if (imgHeight > 1334) {
    imgWidth = imgWidth * (1334 / imgHeight);
    imgHeight = 1334;
  }

  let canvas = document.createElement("canvas");
  canvas.width = imgWidth;
  canvas.height = imgHeight;
  let ctx = canvas.getContext("2d");
  ctx.fillStyle = "#fff"; // 铺底色
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // 绘图之前 纠正图片的方向
  if (orientation && orientation != 1) {
    switch (orientation) {
      case 6:
        canvas.width = imgHeight;
        canvas.height = imgWidth;
        ctx.rotate(Math.PI / 2);
        ctx.drawImage(img, 0, -imgHeight, imgWidth, imgHeight);
        break;
      case 3:
        ctx.rotate(Math.PI);
        ctx.drawImage(img, -imgWidth, -imgHeight, imgWidth, imgHeight);
        break;
      case 8:
        canvas.width = imgHeight;
        canvas.height = imgWidth;
        ctx.rotate((3 * Math.PI) / 2);
        ctx.drawImage(img, -imgWidth, 0, imgWidth, imgHeight);
        break;
    }
  } else {
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  }

  //进行最小压缩
  const u = navigator.userAgent;
  const isAndroid = u.indexOf("Android") > -1 || u.indexOf("Adr") > -1; //android终端
  // const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  let pressedBase64 = canvas.toDataURL("image/jpeg", isAndroid ? 0.2 : 0.1);
  return pressedBase64;
};

const baseUrltoBlob = base64Data => {
  // base64转成bolb对象
  let byteString;
  if (base64Data.split(",")[0].indexOf("base64") >= 0) byteString = atob(base64Data.split(",")[1]);
  else byteString = unescape(base64Data.split(",")[1]);
  let mimeString = base64Data
    .split(",")[0]
    .split(":")[1]
    .split(";")[0];
  let ia = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ia], {
    type: mimeString,
  });
};

export { compress, baseUrltoBlob };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86