加了子线程的测试代码
This commit is contained in:
parent
5cda7db400
commit
0b5d9b11fd
76
test/convert_image_to_webp.cpp
Normal file
76
test/convert_image_to_webp.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "webp/encode.h" // WebP 头文件,用于编码 WebP
|
||||||
|
#include "stb_image.h" // stb_image 头文件,用于解码 PNG/JPG
|
||||||
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
|
#include "stb_image_resize.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// 将输入的 JPG/PNG 数据转换为 WebP,并返回 WebP 数据
|
||||||
|
unsigned char *convert_image_to_webp(const uint8_t *input_data, size_t input_size,int input_width,int input_height, int target_width, int target_height, float quality_factor, size_t *output_size, int preserve_alpha = 0,int is_original = 0) {
|
||||||
|
int width, height, channels;
|
||||||
|
|
||||||
|
unsigned char *decoded_data = nullptr;
|
||||||
|
if (!is_original) {
|
||||||
|
decoded_data = stbi_load_from_memory(input_data, input_size, &width, &height, &channels, preserve_alpha ? 4 : 3); // 根据是否保留 alpha 通道加载
|
||||||
|
} else {
|
||||||
|
decoded_data = (unsigned char *)input_data;
|
||||||
|
// 当使用原始数据时,需要确保width和height已设置
|
||||||
|
width = input_width;
|
||||||
|
height = input_height;
|
||||||
|
channels = preserve_alpha ? 4 : 3;
|
||||||
|
}
|
||||||
|
// 使用 stb_image 解码输入图像(根据 preserve_alpha 决定加载通道数)
|
||||||
|
|
||||||
|
if (!decoded_data) {
|
||||||
|
return nullptr; // 图像解码失败
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果需要调整尺寸,则进行调整
|
||||||
|
unsigned char *resized_data = decoded_data;
|
||||||
|
if (target_width > 0 && target_height > 0) {
|
||||||
|
// 分配用于存储调整大小后图像的缓冲区
|
||||||
|
resized_data = (unsigned char *)malloc(target_width * target_height * (preserve_alpha ? 4 : 3)); // 根据是否保留 alpha 通道调整缓冲区大小
|
||||||
|
|
||||||
|
if (!resized_data) {
|
||||||
|
// 内存分配失败的处理
|
||||||
|
fprintf(stderr, "Failed to allocate memory for resized image.\n");
|
||||||
|
stbi_image_free(decoded_data); // 释放原始解码数据
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 stb_image_resize 调整图像大小
|
||||||
|
int result = stbir_resize_uint8(decoded_data, width, height, 0,
|
||||||
|
resized_data, target_width, target_height, 0, preserve_alpha ? 4 : 3);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
// 如果调整大小失败,释放已分配的内存
|
||||||
|
fprintf(stderr, "Image resizing failed.\n");
|
||||||
|
free(resized_data);
|
||||||
|
stbi_image_free(decoded_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target_width = width;
|
||||||
|
target_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 libwebp 的有损编码函数(WebPEncodeRGB)将 RGB 图像编码为 WebP
|
||||||
|
unsigned char *webp_output = NULL;
|
||||||
|
if (preserve_alpha) {
|
||||||
|
*output_size = WebPEncodeRGBA(resized_data, target_width, target_height, target_width * 4, quality_factor, &webp_output);
|
||||||
|
} else {
|
||||||
|
*output_size = WebPEncodeRGB(resized_data, target_width, target_height, target_width * 3, quality_factor, &webp_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放解码后的图像内存
|
||||||
|
stbi_image_free(decoded_data);
|
||||||
|
if (resized_data != decoded_data) {
|
||||||
|
free(resized_data); // 如果调整了大小,则释放调整大小后的数据
|
||||||
|
}
|
||||||
|
|
||||||
|
return webp_output; // 返回 WebP 编码后的数据
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
1
test/convert_image_to_webp.wasm.map
Normal file
1
test/convert_image_to_webp.wasm.map
Normal file
File diff suppressed because one or more lines are too long
@ -3,6 +3,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>libwebp 压缩图片的 wasm 实现</title>
|
<title>libwebp 压缩图片的 wasm 实现</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
WebP 图:
|
WebP 图:
|
||||||
<span>压缩:<span id="webpSize"></span></span>
|
<span>压缩:<span id="webpSize"></span></span>
|
||||||
@ -57,22 +58,22 @@
|
|||||||
decodeIt();
|
decodeIt();
|
||||||
|
|
||||||
},
|
},
|
||||||
onAbort:(e)=>{
|
onAbort: (e) => {
|
||||||
alert(e);
|
alert(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function clickIt(ti=4){
|
function clickIt(ti = 4) {
|
||||||
for(var i=0;i<ti;i++){
|
for (var i = 0; i < ti; i++) {
|
||||||
decodeIt(`./${i+1}.jpg`);
|
decodeIt(`./${i + 1}.jpg`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var startTime=0;
|
var startTime = 0;
|
||||||
function decodeIt(url) {
|
function decodeIt(url) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
url = fileurl;
|
url = fileurl;
|
||||||
}
|
}
|
||||||
fetch(url).then(response => response.arrayBuffer()).then(buffer => {
|
fetch(url).then(response => response.arrayBuffer()).then(buffer => {
|
||||||
startTime=Date.now();
|
startTime = Date.now();
|
||||||
decodeToWebpp(buffer);
|
decodeToWebpp(buffer);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -81,13 +82,13 @@
|
|||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = function(e) {
|
reader.onload = function (e) {
|
||||||
startTime=Date.now();
|
startTime = Date.now();
|
||||||
const buffer = base64ToArrayBuffer(e.target.result.split(",")[1]);
|
const buffer = base64ToArrayBuffer(e.target.result.split(",")[1]);
|
||||||
const targetWidth = document.getElementById("width").value;
|
const targetWidth = document.getElementById("width").value;
|
||||||
const targetHeight = document.getElementById("height").value;
|
const targetHeight = document.getElementById("height").value;
|
||||||
const qualityFactor = document.getElementById("quality").value;
|
const qualityFactor = document.getElementById("quality").value;
|
||||||
decodeToWebpp(buffer,targetWidth,targetHeight,qualityFactor);
|
decodeToWebpp(buffer, targetWidth, targetHeight, qualityFactor);
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}
|
}
|
||||||
@ -100,7 +101,12 @@
|
|||||||
* @param {number} targetHeight - 目标高度
|
* @param {number} targetHeight - 目标高度
|
||||||
* @param {number} qualityFactor - 压缩质量 (0 - 100)
|
* @param {number} qualityFactor - 压缩质量 (0 - 100)
|
||||||
*/
|
*/
|
||||||
function decodeToWebpp(buffer,targetWidth=0,targetHeight=0,qualityFactor=50) {
|
function decodeToWebpp(buffer, targetWidth = 0, targetHeight = 0, qualityFactor = 50) {
|
||||||
|
setTimeout(() => {
|
||||||
|
decodeItbyworker(buffer);
|
||||||
|
|
||||||
|
}, 1000);
|
||||||
|
return
|
||||||
// 显示原始图片大小
|
// 显示原始图片大小
|
||||||
let size = (buffer.byteLength / 1024).toFixed(2);
|
let size = (buffer.byteLength / 1024).toFixed(2);
|
||||||
|
|
||||||
@ -114,7 +120,7 @@
|
|||||||
var inputDataPtr = Module._malloc(inputData.length);
|
var inputDataPtr = Module._malloc(inputData.length);
|
||||||
Module.HEAPU8.set(inputData, inputDataPtr);
|
Module.HEAPU8.set(inputData, inputDataPtr);
|
||||||
var webpPtr = Module._convert_image_to_webp(inputDataPtr, inputData.length, targetWidth, targetHeight, qualityFactor, outputSizePtr);
|
var webpPtr = Module._convert_image_to_webp(inputDataPtr, inputData.length, targetWidth, targetHeight, qualityFactor, outputSizePtr);
|
||||||
|
|
||||||
// 调用 WebAssembly 函数进行图像转换,返回 WebP 数据指针
|
// 调用 WebAssembly 函数进行图像转换,返回 WebP 数据指针
|
||||||
|
|
||||||
// 获取 WebP 数据大小
|
// 获取 WebP 数据大小
|
||||||
@ -122,10 +128,10 @@
|
|||||||
|
|
||||||
// 从 WebAssembly 内存中读取 WebP 数据
|
// 从 WebAssembly 内存中读取 WebP 数据
|
||||||
var webpData = new Uint8Array(Module.HEAPU8.buffer, webpPtr, outputSize);
|
var webpData = new Uint8Array(Module.HEAPU8.buffer, webpPtr, outputSize);
|
||||||
document.getElementById('result').innerText+=' '+(Date.now()-startTime) +'ms';
|
document.getElementById('result').innerText += ' ' + (Date.now() - startTime) + 'ms';
|
||||||
|
|
||||||
// 显示 WebP 图片大小
|
// 显示 WebP 图片大小
|
||||||
document.getElementById("webpSize").textContent =`${size}KB => ${(outputSize / 1024).toFixed(2)}KB`;
|
document.getElementById("webpSize").textContent = `${size}KB => ${(outputSize / 1024).toFixed(2)}KB`;
|
||||||
|
|
||||||
// 将 WebP 数据转换为 base64,并显示
|
// 将 WebP 数据转换为 base64,并显示
|
||||||
let img = document.getElementById("webpImage");
|
let img = document.getElementById("webpImage");
|
||||||
@ -136,5 +142,24 @@
|
|||||||
Module._free(webpPtr);
|
Module._free(webpPtr);
|
||||||
Module._free(inputDataPtr);
|
Module._free(inputDataPtr);
|
||||||
}
|
}
|
||||||
|
var worker = new Worker('./worker.js');
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
console.log(e.data);
|
||||||
|
switch(e.data.type){
|
||||||
|
case 'webp':
|
||||||
|
let img = document.getElementById("webpImage");
|
||||||
|
img.src = "data:image/webp;base64," + arrayBufferToBase64(e.data.webpData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function decodeItbyworker(buffer, width=0, height=0, quality=50) {
|
||||||
|
worker.postMessage({
|
||||||
|
buffer,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script src="convert_image_to_webp.js"></script>
|
<script src="convert_image_to_webp.js"></script>
|
77
test/worker.js
Normal file
77
test/worker.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// 导入wasm模块
|
||||||
|
let wasmModule;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var Module = {
|
||||||
|
onRuntimeInitialized: function (e) {
|
||||||
|
|
||||||
|
// let baseData= document.getElementById("base64Image").src;
|
||||||
|
// baseData=baseData.split(",")[1];
|
||||||
|
// let buffer = base64ToArrayBuffer(baseData);
|
||||||
|
// decodeToWebpp(buffer);
|
||||||
|
// document.getElementById("base64Image").src = fileurl;
|
||||||
|
// decodeIt();
|
||||||
|
postMessage({ type: 'ready' });
|
||||||
|
console.log(Module._malloc(4))
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
onAbort: (e) => {
|
||||||
|
alert(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 初始化wasm模块
|
||||||
|
self.importScripts('convert_image_to_webp.js');
|
||||||
|
// CreateModule().then(module => {
|
||||||
|
// wasmModule = module;
|
||||||
|
// postMessage({ type: 'ready' });
|
||||||
|
// }).catch(err => {
|
||||||
|
// postMessage({ type: 'error', error: 'Failed to load WASM module: ' + err.message });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 处理主线程发来的消息
|
||||||
|
self.onmessage = async function (e) {
|
||||||
|
|
||||||
|
const {
|
||||||
|
buffer,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality,
|
||||||
|
} = e.data;
|
||||||
|
// 显示原始图片大小
|
||||||
|
let size = (buffer.byteLength / 1024).toFixed(2);
|
||||||
|
|
||||||
|
// 转换图像为 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, width, height,0,0, quality, outputSizePtr);
|
||||||
|
|
||||||
|
// 调用 WebAssembly 函数进行图像转换,返回 WebP 数据指针
|
||||||
|
|
||||||
|
// 获取 WebP 数据大小
|
||||||
|
var outputSize = Module.getValue(outputSizePtr, 'i32');
|
||||||
|
|
||||||
|
// 从 WebAssembly 内存中读取 WebP 数据
|
||||||
|
var webpData = new Uint8Array(Module.HEAPU8.buffer, webpPtr, outputSize);
|
||||||
|
// document.getElementById('result').innerText += ' ' + (Date.now() - startTime) + 'ms';
|
||||||
|
|
||||||
|
// 显示 WebP 图片大小
|
||||||
|
// document.getElementById("webpSize").textContent = `${size}KB => ${(outputSize / 1024).toFixed(2)}KB`;
|
||||||
|
|
||||||
|
// 将 WebP 数据转换为 base64,并显示
|
||||||
|
// let img = document.getElementById("webpImage");
|
||||||
|
// img.src = "data:image/webp;base64," + arrayBufferToBase64(webpData);
|
||||||
|
|
||||||
|
// 使用完成后释放内存
|
||||||
|
Module._free(outputSizePtr);
|
||||||
|
Module._free(webpPtr);
|
||||||
|
Module._free(inputDataPtr);
|
||||||
|
postMessage({ type: 'webp', webpData });
|
||||||
|
};
|
3
生成
3
生成
@ -1,4 +1,5 @@
|
|||||||
docker run --rm -v $(pwd):/src emscripten/emsdk emcc convert_image_to_webp.cpp stb_image.c libwebp.a libsharpyuv.a libwebpdecoder.a libwebpdemux.a libwebpmux.a -o ./test/convert_image_to_webp.js -s WASM=1 -s INITIAL_MEMORY=34340864 -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]'
|
# 调试模式
|
||||||
|
docker run --rm -v $(pwd):/src emscripten/emsdk emcc convert_image_to_webp.cpp stb_image.c libwebp.a libsharpyuv.a libwebpdecoder.a libwebpdemux.a libwebpmux.a -o ./test/convert_image_to_webp.js -g -s WASM=1 -s INITIAL_MEMORY=34340864 -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]' -gsource-map
|
||||||
|
|
||||||
|
|
||||||
# 优化后的命令
|
# 优化后的命令
|
||||||
|
Loading…
Reference in New Issue
Block a user