131 lines
4.0 KiB
JavaScript
131 lines
4.0 KiB
JavaScript
// wasm图片压缩工具类
|
||
const wasmMgr = {
|
||
// 存储已加载的wasm模块
|
||
imageCompressModule: null,
|
||
|
||
// 获取图片压缩模块
|
||
getCompressImg() {
|
||
if (this.imageCompressModule) {
|
||
return Promise.resolve(this.imageCompressModule);
|
||
}
|
||
return new Promise((resolve, reject) => {
|
||
const wasmImports = {
|
||
__assert_fail: (condition, filename, line, func) => {
|
||
console.log(condition, filename, line, func);
|
||
},
|
||
emscripten_resize_heap: (size, old_size) => {
|
||
console.log(size, old_size);
|
||
},
|
||
fd_close: (fd) => {
|
||
console.log(fd);
|
||
},
|
||
fd_seek: (fd, offset, whence) => {
|
||
console.log(fd, offset, whence);
|
||
},
|
||
fd_write: (fd, buf, len, pos) => {
|
||
console.log(fd, buf, len, pos);
|
||
},
|
||
emscripten_memcpy_js: (dest, src, len) => {
|
||
this.imageCompressModule.HEAPU8.copyWithin(dest, src, src + len);
|
||
},
|
||
};
|
||
|
||
// 微信小程序环境
|
||
if (typeof WXWebAssembly !== "undefined") {
|
||
WXWebAssembly.instantiate(
|
||
"/convert_image_to_webp.wasm",
|
||
{
|
||
env: wasmImports,
|
||
wasi_snapshot_preview1: wasmImports,
|
||
}
|
||
).then((result) => {
|
||
this.imageCompressModule = {
|
||
_convert_image_to_webp: result.instance.exports.convert_image_to_webp,
|
||
_malloc: result.instance.exports.malloc,
|
||
_free: result.instance.exports.free,
|
||
};
|
||
this.imageCompressModule.HEAPU8 = new Uint8Array(
|
||
result.instance.exports.memory.buffer
|
||
);
|
||
console.log("convert_image_to_webp加载成功");
|
||
resolve(this.imageCompressModule);
|
||
}).catch((err) => {
|
||
console.error("Failed to load wasm script", err);
|
||
reject(err);
|
||
});
|
||
} else {
|
||
// H5环境或其他环境
|
||
console.error("当前环境不支持WebAssembly");
|
||
reject(new Error("当前环境不支持WebAssembly"));
|
||
}
|
||
});
|
||
},
|
||
|
||
// 图片压缩函数
|
||
async compressImg(file, quality = 0.5, w, h, target_w, target_h) {
|
||
const compressImgHandler = (inputData, module, isOrgin = false) => {
|
||
const inputDataPtr = module._malloc(inputData.length);
|
||
module.HEAPU8.set(inputData, inputDataPtr);
|
||
const outputSizePtr = module._malloc(4);
|
||
const webpPtr = module._convert_image_to_webp(
|
||
inputDataPtr,
|
||
inputData.length,
|
||
w,
|
||
h,
|
||
target_w,
|
||
target_h,
|
||
80 * (quality > 1 ? 1 : quality),
|
||
outputSizePtr,
|
||
1,
|
||
isOrgin ? 1 : 0
|
||
);
|
||
const outputSize =
|
||
module.HEAPU8[outputSizePtr] |
|
||
(module.HEAPU8[outputSizePtr + 1] << 8) |
|
||
(module.HEAPU8[outputSizePtr + 2] << 16) |
|
||
(module.HEAPU8[outputSizePtr + 3] << 24);
|
||
const webpData = new Uint8Array(module.HEAPU8.buffer, webpPtr, outputSize);
|
||
module._free(webpPtr);
|
||
module._free(outputSizePtr);
|
||
module._free(inputDataPtr);
|
||
//如果只需要二进制原始数据,可以直接返回webpdata 减少base64转换
|
||
// return webpData
|
||
return 'data:image/webp;base64,' + this.arrayBufferToBase64(webpData);
|
||
};
|
||
|
||
try {
|
||
const module = await this.getCompressImg();
|
||
|
||
if (file instanceof Uint8Array) {
|
||
return compressImgHandler(file, module, true);
|
||
} else {
|
||
return new Promise((resolve, reject) => {
|
||
wx.getFileSystemManager().readFile({
|
||
filePath: file,
|
||
success: res => {
|
||
resolve(compressImgHandler(new Uint8Array(res.data), module));
|
||
},
|
||
fail: e => {
|
||
console.error("读取文件失败", e);
|
||
reject(e);
|
||
},
|
||
});
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error("图片压缩失败", error);
|
||
throw error;
|
||
}
|
||
},
|
||
|
||
// 将ArrayBuffer转换为Base64
|
||
arrayBufferToBase64(buffer) {
|
||
|
||
return wx.arrayBufferToBase64(buffer);
|
||
|
||
}
|
||
};
|
||
|
||
module.exports = {
|
||
wasmMgr
|
||
}; |