纯前端对图片压缩
纯前端因为可以调用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;
}
网友评论