mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-16 02:29:50 +00:00
WebP encode options (#110)
* Flailing * Holy shit struct binding * Options in the encoder! * Integrating webp options * Addressing feedback * This isn't needed anymore
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<script src='webp_enc.js'></script>
|
||||
<script>
|
||||
const Module = webp_enc();
|
||||
const module = webp_enc();
|
||||
|
||||
async function loadImage(src) {
|
||||
// Load image
|
||||
@@ -17,27 +17,48 @@
|
||||
return ctx.getImageData(0, 0, img.width, img.height);
|
||||
}
|
||||
|
||||
Module.onRuntimeInitialized = async _ => {
|
||||
const api = {
|
||||
version: Module.cwrap('version', 'number', []),
|
||||
create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
|
||||
destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
|
||||
encode: Module.cwrap('encode', '', ['number', 'number', 'number', 'number']),
|
||||
free_result: Module.cwrap('free_result', '', ['number']),
|
||||
get_result_pointer: Module.cwrap('get_result_pointer', 'number', []),
|
||||
get_result_size: Module.cwrap('get_result_size', 'number', []),
|
||||
};
|
||||
console.log('Version:', api.version().toString(16));
|
||||
module.onRuntimeInitialized = async _ => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../example.png');
|
||||
const p = api.create_buffer(image.width, image.height);
|
||||
Module.HEAP8.set(image.data, p);
|
||||
api.encode(p, image.width, image.height, 2);
|
||||
const resultPointer = api.get_result_pointer();
|
||||
const resultSize = api.get_result_size();
|
||||
const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const p = module.create_buffer(image.width, image.height);
|
||||
module.HEAP8.set(image.data, p);
|
||||
module.encode(p, image.width, image.height, {
|
||||
quality: 100,
|
||||
image_hint: 0,
|
||||
target_size: 0,
|
||||
target_PSNR: 0,
|
||||
method: 6,
|
||||
sns_strength: 50,
|
||||
filter_strength: 60,
|
||||
filter_sharpness: 0,
|
||||
filter_type: 1,
|
||||
partitions: 0,
|
||||
segments: 4,
|
||||
pass: 1,
|
||||
show_compressed: 0,
|
||||
preprocessing: 0,
|
||||
autofilter: 0,
|
||||
partition_limit: 0,
|
||||
alpha_compression: 1,
|
||||
alpha_filtering: 1,
|
||||
alpha_quality: 100,
|
||||
lossless: 1,
|
||||
exact: 0,
|
||||
image_hint: 0,
|
||||
emulate_jpeg_size: 0,
|
||||
thread_level: 0,
|
||||
low_memory: 0,
|
||||
near_lossless: 100,
|
||||
use_delta_palette: 0,
|
||||
use_sharp_yuv: 0,
|
||||
});
|
||||
const resultPointer = module.get_result_pointer();
|
||||
const resultSize = module.get_result_size();
|
||||
console.log('size', resultSize);
|
||||
const resultView = new Uint8Array(module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const result = new Uint8Array(resultView);
|
||||
api.free_result(resultPointer);
|
||||
api.destroy_buffer(p);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
const blob = new Blob([result], {type: 'image/webp'});
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "webp_enc",
|
||||
"scripts": {
|
||||
"install": "napa",
|
||||
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_enc\"' -I node_modules/libwebp -o ./webp_enc.js webp_enc.c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c"
|
||||
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc --bind -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_enc\"' -I node_modules/libwebp -o ./webp_enc.js -x c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c -x c++ -std=c++11 webp_enc.cpp "
|
||||
},
|
||||
"napa": {
|
||||
"libwebp": "webmproject/libwebp#v1.0.0"
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#include "emscripten.h"
|
||||
#include "src/webp/encode.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int version() {
|
||||
return WebPGetEncoderVersion();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
uint8_t* create_buffer(int width, int height) {
|
||||
return malloc(width * height * 4 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void destroy_buffer(uint8_t* p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
int result[2];
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void encode(uint8_t* img_in, int width, int height, float quality) {
|
||||
uint8_t* img_out;
|
||||
size_t size;
|
||||
size = WebPEncodeRGBA(img_in, width, height, width * 4, quality, &img_out);
|
||||
result[0] = (int)img_out;
|
||||
result[1] = size;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void free_result() {
|
||||
WebPFree(result[0]);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_size() {
|
||||
return result[1];
|
||||
}
|
||||
|
||||
106
codecs/webp_enc/webp_enc.cpp
Normal file
106
codecs/webp_enc/webp_enc.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "emscripten.h"
|
||||
#include "src/webp/encode.h"
|
||||
#include <stdlib.h>
|
||||
#include <emscripten/bind.h>
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
int version() {
|
||||
return WebPGetEncoderVersion();
|
||||
}
|
||||
|
||||
int create_buffer(int width, int height) {
|
||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
void destroy_buffer(int p) {
|
||||
free((uint8_t*) p);
|
||||
}
|
||||
|
||||
int result[2];
|
||||
void encode(int img_in, int width, int height, WebPConfig config) {
|
||||
// A lot of this is duplicated from Encode in picture_enc.c
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter wrt;
|
||||
int ok;
|
||||
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
return; // shouldn't happen, except if system installation is broken
|
||||
}
|
||||
|
||||
pic.use_argb = !!config.lossless;
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &wrt;
|
||||
|
||||
WebPMemoryWriterInit(&wrt);
|
||||
|
||||
ok = WebPPictureImportRGBA(&pic, (uint8_t*) img_in, width * 4) && WebPEncode(&config, &pic);
|
||||
WebPPictureFree(&pic);
|
||||
if (!ok) {
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
return;
|
||||
}
|
||||
result[0] = (int)wrt.mem;
|
||||
result[1] = wrt.size;
|
||||
}
|
||||
|
||||
void free_result() {
|
||||
WebPFree((void*)result[0]);
|
||||
}
|
||||
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
int get_result_size() {
|
||||
return result[1];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
enum_<WebPImageHint>("WebPImageHint")
|
||||
.value("WEBP_HINT_DEFAULT", WebPImageHint::WEBP_HINT_DEFAULT)
|
||||
.value("WEBP_HINT_PICTURE", WebPImageHint::WEBP_HINT_PICTURE)
|
||||
.value("WEBP_HINT_PHOTO", WebPImageHint::WEBP_HINT_PHOTO)
|
||||
.value("WEBP_HINT_GRAPH", WebPImageHint::WEBP_HINT_GRAPH)
|
||||
;
|
||||
|
||||
value_object<WebPConfig>("WebPConfig")
|
||||
.field("lossless", &WebPConfig::lossless)
|
||||
.field("quality", &WebPConfig::quality)
|
||||
.field("method", &WebPConfig::method)
|
||||
.field("image_hint", &WebPConfig::image_hint)
|
||||
.field("target_size", &WebPConfig::target_size)
|
||||
.field("target_PSNR", &WebPConfig::target_PSNR)
|
||||
.field("segments", &WebPConfig::segments)
|
||||
.field("sns_strength", &WebPConfig::sns_strength)
|
||||
.field("filter_strength", &WebPConfig::filter_strength)
|
||||
.field("filter_sharpness", &WebPConfig::filter_sharpness)
|
||||
.field("filter_type", &WebPConfig::filter_type)
|
||||
.field("autofilter", &WebPConfig::autofilter)
|
||||
.field("alpha_compression", &WebPConfig::alpha_compression)
|
||||
.field("alpha_filtering", &WebPConfig::alpha_filtering)
|
||||
.field("alpha_quality", &WebPConfig::alpha_quality)
|
||||
.field("pass", &WebPConfig::pass)
|
||||
.field("show_compressed", &WebPConfig::show_compressed)
|
||||
.field("preprocessing", &WebPConfig::preprocessing)
|
||||
.field("partitions", &WebPConfig::partitions)
|
||||
.field("partition_limit", &WebPConfig::partition_limit)
|
||||
.field("emulate_jpeg_size", &WebPConfig::emulate_jpeg_size)
|
||||
.field("thread_level", &WebPConfig::thread_level)
|
||||
.field("low_memory", &WebPConfig::low_memory)
|
||||
.field("near_lossless", &WebPConfig::near_lossless)
|
||||
.field("exact", &WebPConfig::exact)
|
||||
.field("use_delta_palette", &WebPConfig::use_delta_palette)
|
||||
.field("use_sharp_yuv", &WebPConfig::use_sharp_yuv)
|
||||
;
|
||||
|
||||
function("version", &version);
|
||||
function("create_buffer", &create_buffer, allow_raw_pointers());
|
||||
function("destroy_buffer", &destroy_buffer, allow_raw_pointers());
|
||||
function("encode", &encode, allow_raw_pointers());
|
||||
function("free_result", &free_result);
|
||||
function("get_result_pointer", &get_result_pointer, allow_raw_pointers());
|
||||
function("get_result_size", &get_result_size, allow_raw_pointers());
|
||||
}
|
||||
14
codecs/webp_enc/webp_enc.d.ts
vendored
14
codecs/webp_enc/webp_enc.d.ts
vendored
@@ -1 +1,13 @@
|
||||
export default function(opts: EmscriptenWasm.ModuleOpts): EmscriptenWasm.Module;
|
||||
import { EncodeOptions } from '../../src/codecs/webp/encoder';
|
||||
|
||||
interface WebPModule extends EmscriptenWasm.Module {
|
||||
create_buffer(width: number, height: number): number;
|
||||
encode(pointer: number, width: number, height: number, options: EncodeOptions): void;
|
||||
get_result_pointer(): number;
|
||||
get_result_size(): number;
|
||||
free_result(): void;
|
||||
destroy_buffer(pointer: number): void;
|
||||
}
|
||||
|
||||
|
||||
export default function(opts: EmscriptenWasm.ModuleOpts): WebPModule;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Reference in New Issue
Block a user