input选择图片后对图片转换和压缩处理

PatWu16

我们常常在选择完图片后需要对图片进行处理,包括格式转换以及压缩等,最近遇到此场景,故整理汇总为如下:

// 图片处理, 输入文件,输出base64和文件
  dealImg(file: File, callback: any) {
    this.fileToBase64(file, (base64: any) => {
      this.compressImg(base64, (compressBase64: any) => {
        callback({
          base64,
          file: this.base64ToFile(compressBase64, file.name)
        });
      });
    });
  }

  // 获取图片用于展示,输入文件,输出base64
  fileToBase64(file: File, callback: any) {
    const fr = new FileReader();
    fr.onload = (evt: any) => {
      callback(evt.target.result);
    };
    fr.readAsDataURL(file);
  }

  // 图片压缩,输入base64,输出base64
  compressImg(base64: any, callback: any, w: number = 1000) {
    const newImage = new Image();
    const quality = 0.8;    // 压缩系数0-1之间
    newImage.src = base64;
    newImage.setAttribute("crossOrigin", 'Anonymous');    // url为外域时需要
    let imgWidth;
    let imgHeight;
    newImage.onload = function() {
      // @ts-ignore
      imgWidth = this.width;
      // @ts-ignore
      imgHeight = this.height;
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d") as any;
      if (Math.max(imgWidth, imgHeight) > w) {
        if (imgWidth > imgHeight) {
          canvas.width = w;
          canvas.height = w * imgHeight / imgWidth;
        } else {
          canvas.height = w;
          canvas.width = w * imgWidth / imgHeight;
        }
      } else {
        canvas.width = imgWidth;
        canvas.height = imgHeight;
      }
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      // @ts-ignore
      ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
      const newBase64 = canvas.toDataURL("image/jpeg", quality);
      callback(newBase64); // 必须通过回调函数返回,否则无法及时拿到该值
    }
  }
  
  // 将base64转换为文件格式
  base64ToFile(base64: string, fileName: string): File {
    const arr = base64.split(',');
    // @ts-ignore
    const mime = arr[0].match(/:(.*?);/)[1];
    const bytes = atob(arr[1]);
    const bytesLength = bytes.length;
    const u8arr = new Uint8Array(bytesLength);
    for (let i = 0; i < bytes.length; i++) {
      u8arr[i] = bytes.charCodeAt(i);
    }
    const blob = new Blob([u8arr], { type: mime })
    return new File([blob], fileName, {
      type: 'image/jpeg'
    });
  }

调用方式如下:

// 单个文件处理,如果有有多文件可以遍历处理
onSingleFileChange(e: any) {
    const files = e.target.files;
    this.dealImg(files[0], (result: any) => {
      console.log(result);
    });
  }
阅读 382
13 声望
0 粉丝
0 条评论
13 声望
0 粉丝
宣传栏