图片上传是件挺麻烦的事情,表单上传会刷新,虽然有 iframe 可以避免页面刷新但是还是挺麻烦,ajax 上传 base64 倒是个不错的办法,可惜图片小点还好,于是冒出了个压缩下 base64 编码的想法。
在线给一张图片编码,复制下来看了下编码的结构,目测着大概有些字符串会重复出现多次,于是要找长字符串里重复了比较多次数的又比较长的子字符串,然后替代成比较短的字符。 因为不太容易处理子字符串交叉的问题,所以只做了一组子字符串(最少四个字符,最少出现五次)的替换,替换为 ‘#1’ 。
结果在比较简单的图片(背景几乎为单色,图案很少集中在中心)上效果很棒,在尝试的图片里,效果最好的替换后长度可以缩短到原来的60%左右。但是对内容变化较大的照片,不管是几百k的 jpg 还是2MB多的 png,压缩后长度也就在 99.9%,虽然多替换几组的话效果也许会好些,或者可能有更长的未匹配到的字符串,但是感觉意义不是不大。
代码贴一下:
var Str = "Base64长字符串";
var Min = 4;
var _len = 5;
var _id = Str.length - _len;
var _str = Str.slice(_id, _id + _len);
var obj = {
len: _len,
id: _id,
str: _str,
find: [],
};
console.log(obj);
var Key = 1;
while (Key == 1) {
console.log(obj);
obj.str = Str.slice(obj.id, obj.id + obj.len);
obj.str = obj.str.replace(/\+/g, "\\+").replace(/\//g, "\/");
var _reg = new RegExp(obj.str, "g");
var _num = Str.match(_reg).length;
obj.num = _num;
obj.reg = _reg;
if (_num > Min) {
/* 有足量的符合预期的匹配 */
/* 试图扩张 */
while (true) {
var _id = obj.id - 1,
_str = Str.slice(_id, _id + obj.len),
_reg = new RegExp(_str, "g"),
_num = 0;
if (_id < 0) {
/* 结束 */
break;
}
// _str = Str.slice( _id, _id + obj.len);
// _reg = new RegExp( _str, 'g' );
_num = Str.match(_reg).length;
if (_num > Min) {
/*可以扩张*/
obj.str = _str;
obj.len = obj.len + 1;
obj.id = obj.id - 1;
} else {
/* 不能扩张 */
/* 保存当前结果 */
obj.find.push(obj.str);
obj.str = obj.str.replace(/\+/g, "\\+").replace(/\//g, "\\/");
obj._reg = new RegExp(obj.str, "g");
var _res = Str.replace(obj.reg, "#1");
console.log(
_res.length + " / " + Str.length + " | ", // + _res
);
obj.per = parseInt((_res.length / Str.length) * 1000) / 10 + "%";
Key = 0;
break;
}
}
} else {
/* 没有符合预期的匹配 */
/* 前移 */
if (obj.id - 1 >= 0) {
/* 可以前移 */
obj.id = obj.id - 1;
obj.str = Str.slice(obj.id, obj.id + obj.len);
} else {
/* 结束了 */
break;
}
}
}
console.log(obj.per);