mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-14 09:39:15 +00:00
* Returning an object seems to work well * This doesn't work * This does! * Better cast? * Updating usage in Squoosh
This commit is contained in:
@@ -19,26 +19,27 @@ See `example.html`
|
||||
|
||||
Returns the version of MozJPEG as a number. va.b.c is encoded as 0x0a0b0c
|
||||
|
||||
### `uint8_t* create_buffer(int width, int height)`
|
||||
|
||||
Allocates an RGBA buffer for an image with the given dimension.
|
||||
|
||||
### `void destroy_buffer(uint8_t* p)`
|
||||
|
||||
Frees a buffer created with `create_buffer`.
|
||||
|
||||
### `void encode(uint8_t* image_buffer, int image_width, int image_height, int quality)`
|
||||
|
||||
Encodes the given image with given dimension to JPEG. `quality` is a number between 0 and 100. The higher the number, the better the quality of the encoded image. The result is implicitly stored and can be accessed using the `get_result_*()` functions.
|
||||
|
||||
### `void free_result()`
|
||||
|
||||
Frees the result created by `encode()`.
|
||||
|
||||
### `int get_result_pointer()`
|
||||
### `Uint8Array encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts)`
|
||||
|
||||
Returns the pointer to the start of the buffer holding the encoded data.
|
||||
Encodes the given image with given dimension to JPEG. Options looks like this:
|
||||
|
||||
### `int get_result_size()`
|
||||
|
||||
Returns the length of the buffer holding the encoded data.
|
||||
```c++
|
||||
struct MozJpegOptions {
|
||||
int quality;
|
||||
bool baseline;
|
||||
bool arithmetic;
|
||||
bool progressive;
|
||||
bool optimize_coding;
|
||||
int smoothing;
|
||||
int color_space;
|
||||
int quant_table;
|
||||
bool trellis_multipass;
|
||||
bool trellis_opt_zero;
|
||||
bool trellis_opt_table;
|
||||
int trellis_loops;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
module.onRuntimeInitialized = async _ => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../example.png');
|
||||
const p = module.create_buffer(image.width, image.height);
|
||||
module.HEAP8.set(image.data, p);
|
||||
module.encode(p, image.width, image.height, {
|
||||
const result = module.encode(image.data, image.width, image.height, {
|
||||
quality: 40,
|
||||
baseline: false,
|
||||
arithmetic: false,
|
||||
@@ -36,13 +34,6 @@
|
||||
trellis_opt_table: true,
|
||||
trellis_loops: 1,
|
||||
});
|
||||
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);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
const blob = new Blob([result], {type: 'image/jpeg'});
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "emscripten.h"
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <emscripten/bind.h>
|
||||
#include "config.h"
|
||||
#include "jpeglib.h"
|
||||
#include "cdjpeg.h"
|
||||
@@ -47,17 +47,10 @@ int version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
int create_buffer(int width, int height) {
|
||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
||||
}
|
||||
uint8_t* last_result;
|
||||
|
||||
void destroy_buffer(int p) {
|
||||
free((uint8_t*) p);
|
||||
}
|
||||
|
||||
int result[2];
|
||||
void encode(int image_in, int image_width, int image_height, MozJpegOptions opts) {
|
||||
uint8_t* image_buffer = (uint8_t*) image_in;
|
||||
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
|
||||
uint8_t* image_buffer = (uint8_t*) image_in.c_str();
|
||||
|
||||
// The code below is basically the `write_JPEG_file` function from
|
||||
// https://github.com/mozilla/mozjpeg/blob/master/example.c
|
||||
@@ -191,25 +184,17 @@ void encode(int image_in, int image_width, int image_height, MozJpegOptions opts
|
||||
jpeg_finish_compress(&cinfo);
|
||||
/* Step 7: release JPEG compression object */
|
||||
|
||||
result[0] = (int)output;
|
||||
result[1] = size;
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
last_result = output;
|
||||
|
||||
/* And we're done! */
|
||||
return val(typed_memory_view(size, output));
|
||||
}
|
||||
|
||||
void free_result() {
|
||||
free((void*)result[0]); // not sure if this is right with mozjpeg
|
||||
}
|
||||
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
int get_result_size() {
|
||||
return result[1];
|
||||
free(last_result); // not sure if this is right with mozjpeg
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
@@ -229,10 +214,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
||||
;
|
||||
|
||||
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("encode", &encode);
|
||||
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());
|
||||
}
|
||||
|
||||
7
codecs/mozjpeg_enc/mozjpeg_enc.d.ts
vendored
7
codecs/mozjpeg_enc/mozjpeg_enc.d.ts
vendored
@@ -1,13 +1,8 @@
|
||||
import { EncodeOptions } from '../../src/codecs/mozjpeg/encoder';
|
||||
|
||||
interface MozJPEGModule 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;
|
||||
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
|
||||
free_result(): void;
|
||||
destroy_buffer(pointer: number): void;
|
||||
}
|
||||
|
||||
|
||||
export default function(opts: EmscriptenWasm.ModuleOpts): MozJPEGModule;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -17,26 +17,10 @@ See `example.html`
|
||||
|
||||
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
|
||||
|
||||
### `uint8_t* create_buffer(int width, int height)`
|
||||
### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height, WebPConfig config)`
|
||||
|
||||
Allocates an RGBA buffer for an image with the given dimension.
|
||||
|
||||
### `void destroy_buffer(uint8_t* p)`
|
||||
|
||||
Frees a buffer created with `create_buffer`.
|
||||
|
||||
### `void encode(uint8_t* image_buffer, int image_width, int image_height, float quality)`
|
||||
|
||||
Encodes the given image with given dimension to WebP. `quality` is a number between 0 and 100. The higher the number, the better the quality of the encoded image. The result is implicitly stored and can be accessed using the `get_result_*()` functions.
|
||||
Encodes the given image with given dimension to WebP.
|
||||
|
||||
### `void free_result()`
|
||||
|
||||
Frees the result created by `encode()`.
|
||||
|
||||
### `int get_result_pointer()`
|
||||
|
||||
Returns the pointer to the start of the buffer holding the encoded data.
|
||||
|
||||
### `int get_result_size()`
|
||||
|
||||
Returns the length of the buffer holding the encoded data.
|
||||
Frees the last result created by `encode()`.
|
||||
|
||||
@@ -20,14 +20,11 @@
|
||||
module.onRuntimeInitialized = async _ => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../example.png');
|
||||
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,
|
||||
const result = module.encode(image.data, image.width, image.height, {
|
||||
quality: 75,
|
||||
target_size: 0,
|
||||
target_PSNR: 0,
|
||||
method: 6,
|
||||
method: 4,
|
||||
sns_strength: 50,
|
||||
filter_strength: 60,
|
||||
filter_sharpness: 0,
|
||||
@@ -42,7 +39,7 @@
|
||||
alpha_compression: 1,
|
||||
alpha_filtering: 1,
|
||||
alpha_quality: 100,
|
||||
lossless: 1,
|
||||
lossless: 0,
|
||||
exact: 0,
|
||||
image_hint: 0,
|
||||
emulate_jpeg_size: 0,
|
||||
@@ -52,15 +49,11 @@
|
||||
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);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
console.log('size', result.length);
|
||||
const blob = new Blob([result], {type: 'image/webp'});
|
||||
|
||||
module.free_result();
|
||||
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
const img = document.createElement('img');
|
||||
img.src = blobURL;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "emscripten.h"
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include "src/webp/encode.h"
|
||||
#include <stdlib.h>
|
||||
#include <emscripten/bind.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
@@ -9,23 +11,19 @@ int version() {
|
||||
return WebPGetEncoderVersion();
|
||||
}
|
||||
|
||||
int create_buffer(int width, int height) {
|
||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
||||
}
|
||||
uint8_t* last_result;
|
||||
|
||||
void destroy_buffer(int p) {
|
||||
free((uint8_t*) p);
|
||||
}
|
||||
val encode(std::string img, int width, int height, WebPConfig config) {
|
||||
uint8_t* img_in = (uint8_t*) img.c_str();
|
||||
|
||||
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
|
||||
// shouldn't happen, except if system installation is broken
|
||||
throw std::runtime_error("Unexpected error");
|
||||
}
|
||||
|
||||
pic.use_argb = !!config.lossless;
|
||||
@@ -40,23 +38,18 @@ void encode(int img_in, int width, int height, WebPConfig config) {
|
||||
WebPPictureFree(&pic);
|
||||
if (!ok) {
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
return;
|
||||
throw std::runtime_error("Encode failed");
|
||||
}
|
||||
result[0] = (int)wrt.mem;
|
||||
result[1] = wrt.size;
|
||||
|
||||
last_result = wrt.mem;
|
||||
|
||||
return val(typed_memory_view(wrt.size, wrt.mem));
|
||||
}
|
||||
|
||||
void free_result() {
|
||||
WebPFree((void*)result[0]);
|
||||
WebPFree(last_result);
|
||||
}
|
||||
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
int get_result_size() {
|
||||
return result[1];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
enum_<WebPImageHint>("WebPImageHint")
|
||||
@@ -97,10 +90,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
||||
;
|
||||
|
||||
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("encode", &encode);
|
||||
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());
|
||||
}
|
||||
|
||||
6
codecs/webp_enc/webp_enc.d.ts
vendored
6
codecs/webp_enc/webp_enc.d.ts
vendored
@@ -1,12 +1,8 @@
|
||||
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;
|
||||
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
|
||||
free_result(): void;
|
||||
destroy_buffer(pointer: number): void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -33,16 +33,9 @@ export default class MozJpegEncoder {
|
||||
|
||||
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
||||
const module = await this.emscriptenModule;
|
||||
|
||||
const p = module.create_buffer(data.width, data.height);
|
||||
module.HEAP8.set(data.data, p);
|
||||
module.encode(p, data.width, data.height, options);
|
||||
const resultPointer = module.get_result_pointer();
|
||||
const resultSize = module.get_result_size();
|
||||
const resultView = new Uint8Array(module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const resultView = module.encode(data.data, data.width, data.height, options);
|
||||
const result = new Uint8Array(resultView);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||
return result.buffer as ArrayBuffer;
|
||||
|
||||
@@ -34,17 +34,10 @@ export default class WebPEncoder {
|
||||
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
||||
const module = await this.emscriptenModule;
|
||||
|
||||
const p = module.create_buffer(data.width, data.height);
|
||||
module.HEAP8.set(data.data, p);
|
||||
module.encode(p, data.width, data.height, options);
|
||||
const resultPointer = module.get_result_pointer();
|
||||
const resultSize = module.get_result_size();
|
||||
const resultView = new Uint8Array(module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const resultView = module.encode(data.data, data.width, data.height, options);
|
||||
const result = new Uint8Array(resultView);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||
return result.buffer as ArrayBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user