2024-12-17 03:51:40 +00:00
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>libwebp 压缩图片的 wasm 实现</title>
|
|
|
|
|
</head>
|
2024-11-06 03:40:07 +00:00
|
|
|
|
<body>
|
|
|
|
|
WebP 图:
|
2024-12-17 02:34:06 +00:00
|
|
|
|
<span>压缩:<span id="webpSize"></span></span>
|
2024-11-06 03:40:07 +00:00
|
|
|
|
<img id="webpImage" alt="WebP Image">
|
|
|
|
|
<br>
|
|
|
|
|
<br>
|
2024-12-18 02:36:36 +00:00
|
|
|
|
<input type="file" id="imageUpload" accept="image/*" onchange="handleFileUpload(event)">
|
|
|
|
|
<br>
|
|
|
|
|
<label for="width">宽度:</label>
|
|
|
|
|
<input type="number" id="width" value="0">
|
|
|
|
|
<br>
|
|
|
|
|
<label for="height">高度:</label>
|
|
|
|
|
<input type="number" id="height" value="0">
|
|
|
|
|
<br>
|
|
|
|
|
<label for="quality">质量:</label>
|
|
|
|
|
<input type="number" id="quality" value="50" min="0" max="100">
|
|
|
|
|
<br>
|
2024-12-17 02:34:06 +00:00
|
|
|
|
<div id="result"></div>
|
2024-11-06 03:40:07 +00:00
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
function base64ToArrayBuffer(base64) {
|
|
|
|
|
var binaryString = atob(base64);
|
|
|
|
|
var len = binaryString.length;
|
|
|
|
|
var bytes = new Uint8Array(len);
|
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
|
|
|
bytes[i] = binaryString.charCodeAt(i);
|
|
|
|
|
}
|
|
|
|
|
// 返回 ArrayBuffer
|
|
|
|
|
return bytes.buffer;
|
|
|
|
|
}
|
|
|
|
|
// 将 WASM 生成的二进制数据转换成 Base64
|
|
|
|
|
function arrayBufferToBase64(buffer) {
|
|
|
|
|
let binary = '';
|
|
|
|
|
let len = buffer.byteLength;
|
|
|
|
|
for (let i = 0; i < len; i++) {
|
|
|
|
|
binary += String.fromCharCode(buffer[i]);
|
|
|
|
|
}
|
|
|
|
|
return btoa(binary); // 使用 JavaScript 的 btoa() 函数
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-17 02:34:06 +00:00
|
|
|
|
var fileurl = './image.png'
|
2024-11-06 03:40:07 +00:00
|
|
|
|
// 初始化 WebAssembly 模块
|
|
|
|
|
var Module = {
|
|
|
|
|
onRuntimeInitialized: function () {
|
|
|
|
|
|
2024-12-17 02:34:06 +00:00
|
|
|
|
// let baseData= document.getElementById("base64Image").src;
|
|
|
|
|
// baseData=baseData.split(",")[1];
|
|
|
|
|
// let buffer = base64ToArrayBuffer(baseData);
|
|
|
|
|
// decodeToWebpp(buffer);
|
|
|
|
|
// document.getElementById("base64Image").src = fileurl;
|
|
|
|
|
decodeIt();
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
onAbort:(e)=>{
|
|
|
|
|
alert(e);
|
2024-11-06 03:40:07 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
2024-12-17 02:34:06 +00:00
|
|
|
|
function clickIt(ti=4){
|
|
|
|
|
for(var i=0;i<ti;i++){
|
|
|
|
|
decodeIt(`./${i+1}.jpg`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var startTime=0;
|
|
|
|
|
function decodeIt(url) {
|
|
|
|
|
if (!url) {
|
|
|
|
|
url = fileurl;
|
|
|
|
|
}
|
|
|
|
|
fetch(url).then(response => response.arrayBuffer()).then(buffer => {
|
|
|
|
|
startTime=Date.now();
|
|
|
|
|
decodeToWebpp(buffer);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-18 02:36:36 +00:00
|
|
|
|
function handleFileUpload(event) {
|
|
|
|
|
const file = event.target.files[0];
|
|
|
|
|
if (file) {
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.onload = function(e) {
|
|
|
|
|
const buffer = base64ToArrayBuffer(e.target.result.split(",")[1]);
|
|
|
|
|
const targetWidth = document.getElementById("width").value;
|
|
|
|
|
const targetHeight = document.getElementById("height").value;
|
|
|
|
|
const qualityFactor = document.getElementById("quality").value;
|
|
|
|
|
decodeToWebpp(buffer,targetWidth,targetHeight,qualityFactor);
|
|
|
|
|
};
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-06 03:40:07 +00:00
|
|
|
|
|
2024-12-18 02:36:36 +00:00
|
|
|
|
/**
|
|
|
|
|
* 将图片转换为 WebP 格式
|
|
|
|
|
* @param {ArrayBuffer} buffer - 图片的二进制数据
|
|
|
|
|
* @param {number} targetWidth - 目标宽度
|
|
|
|
|
* @param {number} targetHeight - 目标高度
|
|
|
|
|
* @param {number} qualityFactor - 压缩质量 (0 - 100)
|
|
|
|
|
*/
|
|
|
|
|
function decodeToWebpp(buffer,targetWidth=0,targetHeight=0,qualityFactor=50) {
|
2024-11-06 03:40:07 +00:00
|
|
|
|
// 显示原始图片大小
|
2024-12-17 02:34:06 +00:00
|
|
|
|
let size = (buffer.byteLength / 1024).toFixed(2);
|
2024-11-06 03:40:07 +00:00
|
|
|
|
|
|
|
|
|
// 转换图像为 Uint8Array
|
|
|
|
|
var inputData = new Uint8Array(buffer);
|
|
|
|
|
|
|
|
|
|
// 分配内存以存储输出 WebP 大小
|
|
|
|
|
var outputSizePtr = Module._malloc(4); // 存储输出大小的指针
|
|
|
|
|
|
|
|
|
|
// 设置目标宽高和质量因子
|
|
|
|
|
var inputDataPtr = Module._malloc(inputData.length);
|
|
|
|
|
Module.HEAPU8.set(inputData, inputDataPtr);
|
|
|
|
|
var webpPtr = Module._convert_image_to_webp(inputDataPtr, inputData.length, targetWidth, targetHeight, qualityFactor, outputSizePtr);
|
2024-12-17 02:34:06 +00:00
|
|
|
|
|
|
|
|
|
// 调用 WebAssembly 函数进行图像转换,返回 WebP 数据指针
|
2024-11-06 03:40:07 +00:00
|
|
|
|
|
|
|
|
|
// 获取 WebP 数据大小
|
|
|
|
|
var outputSize = Module.getValue(outputSizePtr, 'i32');
|
|
|
|
|
|
|
|
|
|
// 从 WebAssembly 内存中读取 WebP 数据
|
|
|
|
|
var webpData = new Uint8Array(Module.HEAPU8.buffer, webpPtr, outputSize);
|
2024-12-17 02:34:06 +00:00
|
|
|
|
document.getElementById('result').innerText+=' '+(Date.now()-startTime) +'ms';
|
2024-11-06 03:40:07 +00:00
|
|
|
|
|
|
|
|
|
// 显示 WebP 图片大小
|
2024-12-17 02:34:06 +00:00
|
|
|
|
document.getElementById("webpSize").textContent =`${size}KB => ${(outputSize / 1024).toFixed(2)}KB`;
|
2024-11-06 03:40:07 +00:00
|
|
|
|
|
|
|
|
|
// 将 WebP 数据转换为 base64,并显示
|
|
|
|
|
let img = document.getElementById("webpImage");
|
|
|
|
|
img.src = "data:image/webp;base64," + arrayBufferToBase64(webpData);
|
|
|
|
|
|
|
|
|
|
// 使用完成后释放内存
|
|
|
|
|
Module._free(outputSizePtr);
|
|
|
|
|
Module._free(webpPtr);
|
|
|
|
|
Module._free(inputDataPtr);
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<script src="convert_image_to_webp.js"></script>
|