前端如何压缩图片质量

开篇语

我的博客,“生活”这模块里,经常需要上传图片。这些图片一般都是我用手机拍摄的,图片质量一般在2-5M左右。所以,我会在图片上传后,使用tinypng接口进行图片压缩。这样,显示的图片会在几百KB左右,点击大图预览才会加载原图。

惊人,后端竟对前端提出这样的要求

就在前两个月,在团队项目里。甲方提出了一个需求,要求对上传的图片进行压缩。在我的思维逻辑里,压缩工作是在图片上传后,后端去进行处理的。
经过小组的讨论分析,后端想要把图片质量压缩的工作放在前端去进行处理,这样可以减少请求时间,客户体验感会更好。当时的有点懵逼,前端还能去处理图片的压缩?

常用的压缩方法

  1. 图片上传到阿里云或者七牛云,云端会压缩图片;
  2. 后端对图片尺寸大小进行压缩,比如tinypng等接口,都可以完成,但压缩时间很久;
  3. 前端用Canvas作为媒介压缩图片;

显然团队的项目更适用于第三种方法。而且网上一大堆相关的资料。

Canvas压缩图片的重要知识点

  • file对象转成Data URL
  • 使用canvas对图片进行缩放,从而达到压缩质量的目的;
  • canvas元素所展示的图片再次转换成Data URL
  • 最后把Data URL转成blob

详细代码解释如下:

function compress (file,callback) {
    var reader = new FileReader();

    // 将file 对象转成 Data URL
    reader.readAsDataURL(file);
    reader.onload = function(e) {
        // 新建一个img 标签(还没嵌入DOM节点)
        var image = new Image();
        image.src = e.target.result;
        image.onload = function() {
            // canvas.getContext 进行宽高的改变,从而达到压缩质量的目的
            var canvas      = document.createElement('canvas'), 
                context     = canvas.getContext('2d');
                imageWidth  = 300,  // 压缩质量宽度
                imageHeight = 300,  // 压缩质量高度
                compactData = '';

            canvas.width  = imageWidth;
            canvas.height = imageHeight;
            context.drawImage(image, 0, 0, imageWidth, imageHeight);
            
            // 将canvas 元素所展示的图片再次转换成 Data URL
            // 到这已经压缩完成了
            compactData = canvas.toDataURL(file.type);

            // 最后把Data URL 转成 blob
            var byteString, mimeString, u8arr, blob;

            if ( compactData.split(",")[0].indexOf("compactData") >= 0 ) {
                byteString = atob(compactData.split(",")[1]); 
            } else{ 
                byteString = unescape(compactData.split(",")[1]); 
            }

            mimeString = compactData .split(",")[0] .split(":")[1] .split(";")[0]; 
            u8arr      = new Uint8Array(byteString.length); 

            for ( var i = 0; i < byteString.length; i++ ) { 
                u8arr[i] = byteString.charCodeAt(i); 
            } 

            blob = new Blob([u8arr], { type: mimeString }); 	
			
            // 返回原file 对象、压缩后的file 对象、压缩后的 Data URL
            callback && callback(file, blob, compactData);
        };
    };
};

在上述样例中,主要是经历了图片 -->canvas缩放压缩 --> 图片的过程。在图片压缩完成后,看个人所需,可以做不同的处理。例如将压缩后的图片显示在页面,作为略缩图,或者直接上传压缩图片。

但要注意的是,上传图片必须是blob对象,所以在压缩后,必须转换成blob对象才能进行上传。转换blob对象的方法好几种,原生的canvas也提供转换blob的方法。有兴趣可以去了解。

demo下载

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章