更新了wasm 支持了渐进式jpg
This commit is contained in:
parent
408a1cd8d5
commit
f9d6e45dc7
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
output/.DS_Store
|
||||
output/output/.DS_Store
|
||||
output/output/convert_image_to_webp(H5原始胶水代码).js
|
||||
output/output/readme.md
|
||||
output/output/utils(小程序兼容代码).js
|
||||
output/output/256MB/convert_image_to_webp.js
|
||||
output/output/512MB/convert_image_to_webp.wasm
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -3,6 +3,7 @@
|
||||
"*.sdp": "xml",
|
||||
"*.json": "jsonc",
|
||||
"vector": "cpp",
|
||||
"type_traits": "cpp"
|
||||
"type_traits": "cpp",
|
||||
"__config": "cpp"
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,12 @@
|
||||
#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_IMPLEMENTATION
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image.h" // stb_image 头文件,用于解码 PNG/JPG
|
||||
#include "stb_image_resize.h"
|
||||
#include "webp/encode.h" // WebP 头文件,用于编码 WebP
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -14,7 +16,7 @@ extern "C" {
|
||||
|
||||
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 通道加载
|
||||
decoded_data = stbi_load_from_memory(input_data, input_size, &width, &height, &channels, 0); // 0自动判断是否保留 alpha 通道加载
|
||||
} else {
|
||||
decoded_data = (unsigned char *)input_data;
|
||||
// 当使用原始数据时,需要确保width和height已设置
|
||||
@ -25,6 +27,7 @@ extern "C" {
|
||||
// 使用 stb_image 解码输入图像(根据 preserve_alpha 决定加载通道数)
|
||||
|
||||
if (!decoded_data) {
|
||||
// printf("stbi_failure_reason: %s\n", stbi_failure_reason());
|
||||
return nullptr; // 图像解码失败
|
||||
}
|
||||
|
||||
@ -32,7 +35,7 @@ extern "C" {
|
||||
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 通道调整缓冲区大小
|
||||
resized_data = (unsigned char *)malloc(target_width * target_height * channels); // 根据是否保留 alpha 通道调整缓冲区大小
|
||||
|
||||
if (!resized_data) {
|
||||
// 内存分配失败的处理
|
||||
@ -43,7 +46,7 @@ extern "C" {
|
||||
|
||||
// 使用 stb_image_resize 调整图像大小
|
||||
int result = stbir_resize_uint8(decoded_data, width, height, 0,
|
||||
resized_data, target_width, target_height, 0, preserve_alpha ? 4 : 3);
|
||||
resized_data, target_width, target_height, 0, channels);
|
||||
|
||||
if (!result) {
|
||||
// 如果调整大小失败,释放已分配的内存
|
||||
@ -59,9 +62,9 @@ extern "C" {
|
||||
|
||||
// 使用 libwebp 的有损编码函数(WebPEncodeRGB)将 RGB 图像编码为 WebP
|
||||
unsigned char *webp_output = NULL;
|
||||
if (preserve_alpha) {
|
||||
if (channels == 4) {
|
||||
*output_size = WebPEncodeRGBA(resized_data, target_width, target_height, target_width * 4, quality_factor, &webp_output);
|
||||
} else {
|
||||
} else if (channels == 3) {
|
||||
*output_size = WebPEncodeRGB(resized_data, target_width, target_height, target_width * 3, quality_factor, &webp_output);
|
||||
}
|
||||
|
||||
|
||||
1
output/convert_image_to_webp.js
Normal file
1
output/convert_image_to_webp.js
Normal file
File diff suppressed because one or more lines are too long
BIN
output/convert_image_to_webp.wasm
Executable file
BIN
output/convert_image_to_webp.wasm
Executable file
Binary file not shown.
4678
stb_image.c
4678
stb_image.c
File diff suppressed because it is too large
Load Diff
@ -7985,4 +7985,4 @@ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
*/
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
#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_IMPLEMENTATION
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image.h" // stb_image 头文件,用于解码 PNG/JPG
|
||||
#include "stb_image_resize.h"
|
||||
#include "webp/encode.h" // WebP 头文件,用于编码 WebP
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -25,6 +26,7 @@ extern "C" {
|
||||
// 使用 stb_image 解码输入图像(根据 preserve_alpha 决定加载通道数)
|
||||
|
||||
if (!decoded_data) {
|
||||
printf("stbi_failure_reason: %s\n", stbi_failure_reason());
|
||||
return nullptr; // 图像解码失败
|
||||
}
|
||||
|
||||
|
||||
@ -1111,79 +1111,16 @@ function dbg(...args) {
|
||||
var _emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
|
||||
|
||||
var getHeapMax = () =>
|
||||
// Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
|
||||
// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
|
||||
// for any code that deals with heap sizes, which would require special
|
||||
// casing all heap size related code to treat 0 specially.
|
||||
2147483648;
|
||||
HEAPU8.length;
|
||||
|
||||
var growMemory = (size) => {
|
||||
var b = wasmMemory.buffer;
|
||||
var pages = (size - b.byteLength + 65535) / 65536;
|
||||
try {
|
||||
// round size grow request up to wasm page size (fixed 64KB per spec)
|
||||
wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size
|
||||
updateMemoryViews();
|
||||
return 1 /*success*/;
|
||||
} catch(e) {
|
||||
err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`);
|
||||
}
|
||||
// implicit 0 return to save code size (caller will cast "undefined" into 0
|
||||
// anyhow)
|
||||
var abortOnCannotGrowMemory = (requestedSize) => {
|
||||
abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`);
|
||||
};
|
||||
var _emscripten_resize_heap = (requestedSize) => {
|
||||
var oldSize = HEAPU8.length;
|
||||
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
|
||||
requestedSize >>>= 0;
|
||||
// With multithreaded builds, races can happen (another thread might increase the size
|
||||
// in between), so return a failure, and let the caller retry.
|
||||
assert(requestedSize > oldSize);
|
||||
|
||||
// Memory resize rules:
|
||||
// 1. Always increase heap size to at least the requested size, rounded up
|
||||
// to next page multiple.
|
||||
// 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
|
||||
// geometrically: increase the heap size according to
|
||||
// MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
|
||||
// overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
|
||||
// 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
|
||||
// linearly: increase the heap size by at least
|
||||
// MEMORY_GROWTH_LINEAR_STEP bytes.
|
||||
// 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
|
||||
// MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
|
||||
// 4. If we were unable to allocate as much memory, it may be due to
|
||||
// over-eager decision to excessively reserve due to (3) above.
|
||||
// Hence if an allocation fails, cut down on the amount of excess
|
||||
// growth, in an attempt to succeed to perform a smaller allocation.
|
||||
|
||||
// A limit is set for how much we can grow. We should not exceed that
|
||||
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
|
||||
var maxHeapSize = getHeapMax();
|
||||
if (requestedSize > maxHeapSize) {
|
||||
err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
|
||||
|
||||
// Loop through potential heap size increases. If we attempt a too eager
|
||||
// reservation that fails, cut down on the attempted size and reserve a
|
||||
// smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
|
||||
for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
|
||||
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
|
||||
// but limit overreserving (default to capping at +96MB overgrowth at most)
|
||||
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
|
||||
|
||||
var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
|
||||
|
||||
var replacement = growMemory(newSize);
|
||||
if (replacement) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);
|
||||
return false;
|
||||
abortOnCannotGrowMemory(requestedSize);
|
||||
};
|
||||
|
||||
var SYSCALLS = {
|
||||
@ -1436,8 +1373,8 @@ var wasmImports = {
|
||||
};
|
||||
var wasmExports = createWasm();
|
||||
var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors');
|
||||
var _malloc = Module['_malloc'] = createExportWrapper('malloc');
|
||||
var _free = Module['_free'] = createExportWrapper('free');
|
||||
var _malloc = Module['_malloc'] = createExportWrapper('malloc');
|
||||
var _convert_image_to_webp = Module['_convert_image_to_webp'] = createExportWrapper('convert_image_to_webp');
|
||||
var _fflush = createExportWrapper('fflush');
|
||||
var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])();
|
||||
@ -1469,6 +1406,7 @@ var missingLibrarySymbols = [
|
||||
'convertU32PairToI53',
|
||||
'zeroMemory',
|
||||
'exitJS',
|
||||
'growMemory',
|
||||
'isLeapYear',
|
||||
'ydayFromDate',
|
||||
'arraySum',
|
||||
@ -1663,7 +1601,7 @@ var unexportedSymbols = [
|
||||
'convertI32PairToI53Checked',
|
||||
'ptrToString',
|
||||
'getHeapMax',
|
||||
'growMemory',
|
||||
'abortOnCannotGrowMemory',
|
||||
'ENV',
|
||||
'MONTH_DAYS_REGULAR',
|
||||
'MONTH_DAYS_LEAP',
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -13,10 +13,10 @@
|
||||
<input type="file" id="imageUpload" accept="image/*" onchange="handleFileUpload(event)">
|
||||
<br>
|
||||
<label for="width">宽度:</label>
|
||||
<input type="number" id="width" value="0">
|
||||
<input type="number" id="width" value="1920">
|
||||
<br>
|
||||
<label for="height">高度:</label>
|
||||
<input type="number" id="height" value="0">
|
||||
<input type="number" id="height" value="1080">
|
||||
<br>
|
||||
<label for="quality">质量:</label>
|
||||
<input type="number" id="quality" value="50" min="0" max="100">
|
||||
@ -45,7 +45,7 @@
|
||||
return btoa(binary); // 使用 JavaScript 的 btoa() 函数
|
||||
}
|
||||
|
||||
var fileurl = './image.bin'
|
||||
var fileurl = './img1.jpg'
|
||||
// 初始化 WebAssembly 模块
|
||||
var Module = {
|
||||
onRuntimeInitialized: function () {
|
||||
@ -102,11 +102,11 @@
|
||||
* @param {number} qualityFactor - 压缩质量 (0 - 100)
|
||||
*/
|
||||
function decodeToWebpp(buffer, targetWidth = 0, targetHeight = 0, qualityFactor = 50) {
|
||||
setTimeout(() => {
|
||||
decodeItbyworker(buffer);
|
||||
// setTimeout(() => {
|
||||
// decodeItbyworker(buffer);
|
||||
|
||||
}, 1000);
|
||||
return
|
||||
// }, 1000);
|
||||
// return
|
||||
// 显示原始图片大小
|
||||
let size = (buffer.byteLength / 1024).toFixed(2);
|
||||
|
||||
@ -119,7 +119,9 @@
|
||||
// 设置目标宽高和质量因子
|
||||
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);
|
||||
var webpPtr = Module._convert_image_to_webp(
|
||||
inputDataPtr, inputData.length, 0,0,targetWidth, targetHeight, qualityFactor, outputSizePtr,0,0
|
||||
);
|
||||
|
||||
// 调用 WebAssembly 函数进行图像转换,返回 WebP 数据指针
|
||||
|
||||
@ -142,16 +144,16 @@
|
||||
Module._free(webpPtr);
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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,
|
||||
|
||||
Binary file not shown.
4
生成
4
生成
@ -1,6 +1,6 @@
|
||||
# 调试模式
|
||||
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=20MB -s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]' -gsource-map
|
||||
docker run --rm -v $(pwd):/src emscripten/emsdk emcc convert_image_to_webp.cpp libwebp.a libsharpyuv.a libwebpdecoder.a libwebpdemux.a libwebpmux.a -o ./test/convert_image_to_webp.js -g -s WASM=1 -s INITIAL_MEMORY=256MB -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]' -gsource-map
|
||||
|
||||
|
||||
# 优化后的命令
|
||||
docker run --rm -v $(pwd):/src emscripten/emsdk emcc convert_image_to_webp.cpp stb_image.c libwebp.a libsharpyuv.a -o ./output/convert_image_to_webp.js -s WASM=1 -s NO_FILESYSTEM=1 -s INITIAL_MEMORY=512MB -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]' -O2
|
||||
docker run --rm -v $(pwd):/src emscripten/emsdk emcc convert_image_to_webp.cpp libwebp.a libsharpyuv.a -o ./output/convert_image_to_webp.js -s WASM=1 -s NO_FILESYSTEM=1 -s INITIAL_MEMORY=64MB -s EXPORTED_FUNCTIONS="['_free','_malloc','_convert_image_to_webp']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "getValue"]' -O2
|
||||
Loading…
Reference in New Issue
Block a user