前端使用canvas对图片进行压缩

纯前端对图片压缩

纯前端因为可以调用FileReader和canvas接口,在图片压缩方面非常便捷.思路就是获取图形数据后,找到相对比较短的边, 以他为基准压缩到一个比较小的比例(如640*480),图像的大小最终取决于三个因素:图片像素、编码质量和位深度,图形像素在执行完这条个函数之后就达到一个比较小的范围了,一般不会超过100k,而编码质量是一种类似于PS中表面模糊的效果,使用的是插值算法,一般编程80-90区间内可以对图像进行进一步的压缩,但是不建议压的太多,会失真。这里由于我们对图片大小有64k的严格限制,所以在对分辨率进行压缩之后,对编码质量又进行了一次压缩.

在这里因为canvas绘出来的图形都是base64格式,base64是一种牺牲空间来换兼容性的编码,在编码中每三字节会扩充成四字节,这使得数据量会增加1/3,所以在计算图片大小时要除4/3,也就是乘0.75,这才是真正的图形数据

 compress(fileObj) {
      let reader = new FileReader();
      let that = this;
      reader.onload = function(e) {
        let image = new Image();
        image.src = e.target.result;
        image.onload = function() {
          let canvas = document.createElement('canvas');
          let context = canvas.getContext('2d');
          let imageWidth = image.width; //压缩后图片的大小
          let imageHeight = image.height;
          let data = '';
          let loopVar = imageWidth > imageHeight ? imageHeight : imageWidth;
          let compressRio = 0.9;
          let n = 0;
          //保证短边小于480
          while (loopVar >= 480) {
            loopVar = loopVar * compressRio;
            imageWidth = imageWidth * compressRio;
            imageHeight = imageHeight * compressRio;
            n++;
          }
          that.compressRio = compressRio * n;
          that.compressWidth = Math.floor(imageWidth);
          that.compressHeight = Math.floor(imageHeight);
          canvas.width = imageWidth;
          canvas.height = imageHeight;

          context.drawImage(image, 0, 0, imageWidth, imageHeight);
          data = canvas.toDataURL('image/jpeg', 0.85);
          //保证大小小于64K
            let imgSize = data.length *0.75 / 1024;
            let quatity = 0.85;
            while (imgSize > 64) {
              quatity = quatity * compressRio;
              data = canvas.toDataURL('image/jpeg', quatity);
              imgSize = data.length *0.75 / 1024;
            }
           //压缩完成
        };
      };
      reader.readAsDataURL(fileObj);
    }

用canvas压缩完成后此时得到的是base64编码的图片,可以在前端展示,但是要进行存储还是要转成二进制格式,转换函数如下

 convertBase64UrlToBlob(urlData) {
      //去掉url的头
      var arr = urlData.split(','),
        //获取后缀名
        mime = arr[0].match(/:(.*?);/)[1],
        //base64转换为byte
        bstr = atob(arr[1]),
        n = bstr.length,
        //新建无符号整形数组
        u8arr = new Uint8Array(n);
      while (n--) {
        //返回值的ascll编码
        u8arr[n] = bstr.charCodeAt(n);
      }
      return u8arr;
    }

你可能感兴趣的:(前端使用canvas对图片进行压缩)