mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-14 17:49:52 +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
|
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()`
|
### `void free_result()`
|
||||||
|
|
||||||
Frees the result created by `encode()`.
|
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()`
|
```c++
|
||||||
|
struct MozJpegOptions {
|
||||||
Returns the length of the buffer holding the encoded data.
|
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 _ => {
|
module.onRuntimeInitialized = async _ => {
|
||||||
console.log('Version:', module.version().toString(16));
|
console.log('Version:', module.version().toString(16));
|
||||||
const image = await loadImage('../example.png');
|
const image = await loadImage('../example.png');
|
||||||
const p = module.create_buffer(image.width, image.height);
|
const result = module.encode(image.data, image.width, image.height, {
|
||||||
module.HEAP8.set(image.data, p);
|
|
||||||
module.encode(p, image.width, image.height, {
|
|
||||||
quality: 40,
|
quality: 40,
|
||||||
baseline: false,
|
baseline: false,
|
||||||
arithmetic: false,
|
arithmetic: false,
|
||||||
@@ -36,13 +34,6 @@
|
|||||||
trellis_opt_table: true,
|
trellis_opt_table: true,
|
||||||
trellis_loops: 1,
|
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 blob = new Blob([result], {type: 'image/jpeg'});
|
||||||
const blobURL = URL.createObjectURL(blob);
|
const blobURL = URL.createObjectURL(blob);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "emscripten.h"
|
#include <emscripten/bind.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <emscripten/bind.h>
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "jpeglib.h"
|
#include "jpeglib.h"
|
||||||
#include "cdjpeg.h"
|
#include "cdjpeg.h"
|
||||||
@@ -47,17 +47,10 @@ int version() {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_buffer(int width, int height) {
|
uint8_t* last_result;
|
||||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_buffer(int p) {
|
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
|
||||||
free((uint8_t*) p);
|
uint8_t* image_buffer = (uint8_t*) image_in.c_str();
|
||||||
}
|
|
||||||
|
|
||||||
int result[2];
|
|
||||||
void encode(int image_in, int image_width, int image_height, MozJpegOptions opts) {
|
|
||||||
uint8_t* image_buffer = (uint8_t*) image_in;
|
|
||||||
|
|
||||||
// The code below is basically the `write_JPEG_file` function from
|
// The code below is basically the `write_JPEG_file` function from
|
||||||
// https://github.com/mozilla/mozjpeg/blob/master/example.c
|
// 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);
|
jpeg_finish_compress(&cinfo);
|
||||||
/* Step 7: release JPEG compression object */
|
/* 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. */
|
/* This is an important step since it will release a good deal of memory. */
|
||||||
jpeg_destroy_compress(&cinfo);
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
last_result = output;
|
||||||
|
|
||||||
/* And we're done! */
|
/* And we're done! */
|
||||||
|
return val(typed_memory_view(size, output));
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_result() {
|
void free_result() {
|
||||||
free((void*)result[0]); // not sure if this is right with mozjpeg
|
free(last_result); // not sure if this is right with mozjpeg
|
||||||
}
|
|
||||||
|
|
||||||
int get_result_pointer() {
|
|
||||||
return result[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_result_size() {
|
|
||||||
return result[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_BINDINGS(my_module) {
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
@@ -229,10 +214,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
|||||||
;
|
;
|
||||||
|
|
||||||
function("version", &version);
|
function("version", &version);
|
||||||
function("create_buffer", &create_buffer, allow_raw_pointers());
|
function("encode", &encode);
|
||||||
function("destroy_buffer", &destroy_buffer, allow_raw_pointers());
|
|
||||||
function("encode", &encode, allow_raw_pointers());
|
|
||||||
function("free_result", &free_result);
|
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';
|
import { EncodeOptions } from '../../src/codecs/mozjpeg/encoder';
|
||||||
|
|
||||||
interface MozJPEGModule extends EmscriptenWasm.Module {
|
interface MozJPEGModule extends EmscriptenWasm.Module {
|
||||||
create_buffer(width: number, height: number): number;
|
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
|
||||||
encode(pointer: number, width: number, height: number, options: EncodeOptions): void;
|
|
||||||
get_result_pointer(): number;
|
|
||||||
get_result_size(): number;
|
|
||||||
free_result(): void;
|
free_result(): void;
|
||||||
destroy_buffer(pointer: number): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function(opts: EmscriptenWasm.ModuleOpts): MozJPEGModule;
|
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
|
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.
|
Encodes the given image with given dimension to WebP.
|
||||||
|
|
||||||
### `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.
|
|
||||||
|
|
||||||
### `void free_result()`
|
### `void free_result()`
|
||||||
|
|
||||||
Frees the result created by `encode()`.
|
Frees the last 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.
|
|
||||||
|
|||||||
@@ -20,14 +20,11 @@
|
|||||||
module.onRuntimeInitialized = async _ => {
|
module.onRuntimeInitialized = async _ => {
|
||||||
console.log('Version:', module.version().toString(16));
|
console.log('Version:', module.version().toString(16));
|
||||||
const image = await loadImage('../example.png');
|
const image = await loadImage('../example.png');
|
||||||
const p = module.create_buffer(image.width, image.height);
|
const result = module.encode(image.data, image.width, image.height, {
|
||||||
module.HEAP8.set(image.data, p);
|
quality: 75,
|
||||||
module.encode(p, image.width, image.height, {
|
|
||||||
quality: 100,
|
|
||||||
image_hint: 0,
|
|
||||||
target_size: 0,
|
target_size: 0,
|
||||||
target_PSNR: 0,
|
target_PSNR: 0,
|
||||||
method: 6,
|
method: 4,
|
||||||
sns_strength: 50,
|
sns_strength: 50,
|
||||||
filter_strength: 60,
|
filter_strength: 60,
|
||||||
filter_sharpness: 0,
|
filter_sharpness: 0,
|
||||||
@@ -42,7 +39,7 @@
|
|||||||
alpha_compression: 1,
|
alpha_compression: 1,
|
||||||
alpha_filtering: 1,
|
alpha_filtering: 1,
|
||||||
alpha_quality: 100,
|
alpha_quality: 100,
|
||||||
lossless: 1,
|
lossless: 0,
|
||||||
exact: 0,
|
exact: 0,
|
||||||
image_hint: 0,
|
image_hint: 0,
|
||||||
emulate_jpeg_size: 0,
|
emulate_jpeg_size: 0,
|
||||||
@@ -52,15 +49,11 @@
|
|||||||
use_delta_palette: 0,
|
use_delta_palette: 0,
|
||||||
use_sharp_yuv: 0,
|
use_sharp_yuv: 0,
|
||||||
});
|
});
|
||||||
const resultPointer = module.get_result_pointer();
|
console.log('size', result.length);
|
||||||
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/webp'});
|
const blob = new Blob([result], {type: 'image/webp'});
|
||||||
|
|
||||||
|
module.free_result();
|
||||||
|
|
||||||
const blobURL = URL.createObjectURL(blob);
|
const blobURL = URL.createObjectURL(blob);
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.src = blobURL;
|
img.src = blobURL;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "emscripten.h"
|
#include <emscripten/bind.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
#include "src/webp/encode.h"
|
#include "src/webp/encode.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <emscripten/bind.h>
|
#include <string.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace emscripten;
|
using namespace emscripten;
|
||||||
|
|
||||||
@@ -9,23 +11,19 @@ int version() {
|
|||||||
return WebPGetEncoderVersion();
|
return WebPGetEncoderVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_buffer(int width, int height) {
|
uint8_t* last_result;
|
||||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_buffer(int p) {
|
val encode(std::string img, int width, int height, WebPConfig config) {
|
||||||
free((uint8_t*) p);
|
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
|
// A lot of this is duplicated from Encode in picture_enc.c
|
||||||
WebPPicture pic;
|
WebPPicture pic;
|
||||||
WebPMemoryWriter wrt;
|
WebPMemoryWriter wrt;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
if (!WebPPictureInit(&pic)) {
|
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;
|
pic.use_argb = !!config.lossless;
|
||||||
@@ -40,23 +38,18 @@ void encode(int img_in, int width, int height, WebPConfig config) {
|
|||||||
WebPPictureFree(&pic);
|
WebPPictureFree(&pic);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
WebPMemoryWriterClear(&wrt);
|
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() {
|
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) {
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
enum_<WebPImageHint>("WebPImageHint")
|
enum_<WebPImageHint>("WebPImageHint")
|
||||||
@@ -97,10 +90,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
|||||||
;
|
;
|
||||||
|
|
||||||
function("version", &version);
|
function("version", &version);
|
||||||
function("create_buffer", &create_buffer, allow_raw_pointers());
|
function("encode", &encode);
|
||||||
function("destroy_buffer", &destroy_buffer, allow_raw_pointers());
|
|
||||||
function("encode", &encode, allow_raw_pointers());
|
|
||||||
function("free_result", &free_result);
|
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';
|
import { EncodeOptions } from '../../src/codecs/webp/encoder';
|
||||||
|
|
||||||
interface WebPModule extends EmscriptenWasm.Module {
|
interface WebPModule extends EmscriptenWasm.Module {
|
||||||
create_buffer(width: number, height: number): number;
|
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
|
||||||
encode(pointer: number, width: number, height: number, options: EncodeOptions): void;
|
|
||||||
get_result_pointer(): number;
|
|
||||||
get_result_size(): number;
|
|
||||||
free_result(): void;
|
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> {
|
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
||||||
const module = await this.emscriptenModule;
|
const module = await this.emscriptenModule;
|
||||||
|
const resultView = module.encode(data.data, data.width, data.height, options);
|
||||||
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 result = new Uint8Array(resultView);
|
const result = new Uint8Array(resultView);
|
||||||
module.free_result();
|
module.free_result();
|
||||||
module.destroy_buffer(p);
|
|
||||||
|
|
||||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||||
return result.buffer as ArrayBuffer;
|
return result.buffer as ArrayBuffer;
|
||||||
|
|||||||
@@ -34,17 +34,10 @@ export default class WebPEncoder {
|
|||||||
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
||||||
const module = await this.emscriptenModule;
|
const module = await this.emscriptenModule;
|
||||||
|
|
||||||
const p = module.create_buffer(data.width, data.height);
|
const resultView = module.encode(data.data, data.width, data.height, options);
|
||||||
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 result = new Uint8Array(resultView);
|
const result = new Uint8Array(resultView);
|
||||||
module.free_result();
|
module.free_result();
|
||||||
module.destroy_buffer(p);
|
|
||||||
|
|
||||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
|
||||||
return result.buffer as ArrayBuffer;
|
return result.buffer as ArrayBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user