if (!HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { value: function (callback, type, quality) { var canvas = this; setTimeout(function() { var binStr = atob( canvas.toDataURL(type, quality).split(',')[1] ), len = binStr.length, arr = new Uint8Array(len); for (var i = 0; i < len; i++ ) { arr[i] = binStr.charCodeAt(i); } callback( new Blob( [arr], {type: type || 'image/jpeg'} ) ); }); } });}// 必要条件window.URL = window.URL || window.webkitURL;// 获取旋转info:-2 = not jpeg, -1 = no data, 1..8 = orientationsfunction getExifOrientation(file, callback) { // 这里只是为了取得文件的EXIF特征 // if (file.slice) { // file = file.slice(0, 131072); // } else if (file.webkitSlice) { // file = file.webkitSlice(0, 131072); // } else if(file.mozSlice) { // file = file.mozSlice(0, 131072); // } var reader = new FileReader(); reader.onload = function (e) { var view = new DataView(e.target.result); if (view.getUint16(0, false) != 0xFFD8) { callback(-2); return; } var length = view.byteLength, offset = 2; while (offset < length) { var marker = view.getUint16(offset, false); offset += 2; if (marker == 0xFFE1) { if (view.getUint32(offset += 2, false) != 0x45786966) { callback(-1); return; } var little = view.getUint16(offset += 6, false) == 0x4949; offset += view.getUint32(offset + 4, little); var tags = view.getUint16(offset, little); offset += 2; for (var i = 0; i < tags; i++) if (view.getUint16(offset + (i * 12), little) == 0x0112) { callback(view.getUint16(offset + (i * 12) + 8, little)); return; } } else if ((marker & 0xFF00) != 0xFF00) break; else offset += view.getUint16(offset, false); } callback(-1); }; reader.readAsArrayBuffer(file);}// Derived from cc by-safunction imgToCanvasWithOrientation(img, rawWidth, rawHeight, orientation) { var canvas = document.createElement('canvas'); if (orientation > 4) { canvas.width = rawHeight; canvas.height = rawWidth; } else { canvas.width = rawWidth; canvas.height = rawHeight; } var ctx = canvas.getContext('2d'); // 注:360移动浏览器在android下, ctx.transform 会造成问题 if (orientation > 1) { // console.log("EXIF orientation = " + orientation + ", rotating picture"); switch (orientation) { case 2: ctx.transform(-1, 0, 0, 1, rawWidth, 0); break; case 3: ctx.transform(-1, 0, 0, -1, rawWidth, rawHeight); break; case 4: ctx.transform(1, 0, 0, -1, 0, rawHeight); break; case 5: ctx.transform(0, 1, 1, 0, 0, 0); break; case 6: ctx.transform(0, 1, -1, 0, rawHeight, 0); break; case 7: ctx.transform(0, -1, -1, 0, rawHeight, rawWidth); break; case 8: ctx.transform(0, -1, 1, 0, 0, rawWidth); break; } } ctx.drawImage(img, 0, 0, rawWidth, rawHeight); return canvas;}// 重构压缩图片文件function compressIMG(file, options, callback) { // 兼容性判断 if (!(window.File && window.FileReader && window.FileList && window.Blob)) { // alert('The File APIs are not fully supported in this browser.'); alert('当前浏览器版本不支持图片压缩功能,请更换或升级浏览器,推荐使用chrome浏览器。'); return false; } // 图片文件最大 100 KB ( 原图低于100kb不压缩) var acceptFileSize = options.acceptFileSize || 100 * 1024; // 图片质量默认压缩为 0.7 var quality = options.quality || 0.7; // 默认输出格式:'image/jpeg' var imageType = options.type || 'image/jpeg'; // 默认最大宽度: 1920 px; var maxWidth = options.maxWidth || 1200; // 默认最大高度: 无限大 var maxHeight = options.maxHeight || Infinity; // 低于100KB 的jpeg 不压缩, 质量改为1 if (file.size <= acceptFileSize) { // callback(file); quality = 1; } // console出原文件大小 // console.log('图片原始大小', parseFloat(file.size / 1024 / 1024).toFixed(2), 'MB');// 旋转角度初始化 var orientation = 0; // 异步获取角度,需要时间,由于各浏览器内核的差异,不宜将图像绘制放在回到内部处理。 getExifOrientation(file, function (ori) { orientation = ori }); var img = new Image(); img.onerror = function () { URL.revokeObjectURL(this.src); // 图像revoke,内存回收 img = null; // 考虑移动小内存,回收img // callback(file); alert('图片无法识别,文件格式不对或可能已损坏。'); }; img.onload = function () { URL.revokeObjectURL(this.src); // 图像revoke,内存回收 // console.log('旋转度:', orientation) var oW = img.width, oH = img.height; // 留出500ms,确保角度计算完成,一些客户端性能很差。 setTimeout(function(){ var orient =(orientation || 0); var scale = (orient > 4 ? Math.min(maxHeight / oW, maxWidth / oH, 1): Math.min(maxWidth / oW, maxHeight / oH, 1)); var h = Math.round(oH * scale); var w = Math.round(oW * scale); var canvas = imgToCanvasWithOrientation(img, w, h, orient); img = null; // 考虑移动小内存,回收img canvas.toBlob(function (blob) { canvas = null; // 考虑移动小内存,回收canvas callback(blob, file.name); }, imageType, quality); },500) }; img.src = URL.createObjectURL(file);}
使用方法
compressIMG(file, {quality: 0.7 }, function (blob) {
})