wasm-webp 0.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +239 -0
- package/dist/cjs/index.js +82 -0
- package/dist/cjs/webp-wasm.js +3324 -0
- package/dist/cjs/webp-wasm.wasm +0 -0
- package/dist/esm/index.js +70 -0
- package/dist/esm/webp-wasm.js +3337 -0
- package/dist/esm/webp-wasm.wasm +0 -0
- package/dist/index.d.ts +30 -0
- package/dist/types.d.ts +17 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 nieyuyao0826@hotmail.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# WIP
|
|
2
|
+
|
|
3
|
+
# `webp.wasm`
|
|
4
|
+
|
|
5
|
+
webp.wasm is a pure Webassembly / Javascript port of libwebp.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## APIs
|
|
10
|
+
|
|
11
|
+
### Encode
|
|
12
|
+
|
|
13
|
+
#### encode
|
|
14
|
+
|
|
15
|
+
Get encoder encoderVersion.
|
|
16
|
+
|
|
17
|
+
`function encoderVersion(): Promise<string>`
|
|
18
|
+
|
|
19
|
+
##### Example
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const version = await encoderVersion()
|
|
23
|
+
console.log(version) // 1.3.2
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
#### encodeRGB
|
|
27
|
+
|
|
28
|
+
Encodes rgb bitmap an returns WebP Uint8Array. The `width` and `height` parameters of the bitmap should be provided.
|
|
29
|
+
|
|
30
|
+
`function encodeRGB(rgb: Uint8Array, width: number, height: number, quality?: number): Promise<Nullable<Uint8Array>>`
|
|
31
|
+
|
|
32
|
+
##### Example
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
...
|
|
36
|
+
const ctx = canvas.getContext('2d')!
|
|
37
|
+
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
38
|
+
const buf = new Uint8Array(3 * canvas.width, canvas.height)
|
|
39
|
+
let j = 0
|
|
40
|
+
// remove alpha
|
|
41
|
+
imgData.data.forEach((pixel, i) => {
|
|
42
|
+
if ((i + 1) % 4 === 0) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
buf[j] = pixel
|
|
46
|
+
j++
|
|
47
|
+
})
|
|
48
|
+
const webpData = await encodeRGB(buf, canvas.width, canvas.height)
|
|
49
|
+
const blob = new Blob([webpData!], {type: 'image/webp'})
|
|
50
|
+
const blobURL = URL.createObjectURL(blob);
|
|
51
|
+
// download webp
|
|
52
|
+
const a = document.createElement('a')
|
|
53
|
+
a.download = '1.webp'
|
|
54
|
+
a.href = blobURL
|
|
55
|
+
document.body.appendChild(a)
|
|
56
|
+
a.click()
|
|
57
|
+
a.remove()
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### encodeRGBA
|
|
61
|
+
|
|
62
|
+
Encodes rgba bitmap an returns WebP Uint8Array.
|
|
63
|
+
|
|
64
|
+
`function encodeRGBA(rgba: Uint8Array, width: number, height: number, quality?: number): Promise<Nullable<Uint8Array>>`
|
|
65
|
+
|
|
66
|
+
##### Example
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
...
|
|
70
|
+
const ctx = canvas.getContext('2d')!
|
|
71
|
+
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
72
|
+
const webpData = await encodeRGBA(imgData.data, canvas.width, canvas.height)
|
|
73
|
+
// download webp
|
|
74
|
+
...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### encode
|
|
78
|
+
|
|
79
|
+
A more advanced API is based on the WebPConfig. <b>Only the lossless and quality parameters are supported now !!!</b>. You can generate low-quality webp with this function.
|
|
80
|
+
|
|
81
|
+
`function encodeRGBA(data: Uint8Array, width: number, height: number, hasAlpha: boolean,config: Partial<WebPConfig>): Promise<Nullable<Uint8Array>>`
|
|
82
|
+
|
|
83
|
+
- hasAlpha: boolean
|
|
84
|
+
|
|
85
|
+
Whether to include alpha chanel.
|
|
86
|
+
|
|
87
|
+
- WebPConfig.lossless: number
|
|
88
|
+
|
|
89
|
+
Lossless encoding (0=lossy(default), 1=lossless).
|
|
90
|
+
|
|
91
|
+
- WebPConfig.quality: number
|
|
92
|
+
|
|
93
|
+
Between 0 and 100. Default value is 100.
|
|
94
|
+
|
|
95
|
+
##### Example
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
...
|
|
99
|
+
const ctx = canvas.getContext('2d')!
|
|
100
|
+
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
101
|
+
const webpData = await encode(imgData.data, canvas.width, canvas.height, true, { lossless: 0 })
|
|
102
|
+
// download webp
|
|
103
|
+
...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### encodeAnimation
|
|
107
|
+
|
|
108
|
+
Returns animated WebP like `GIF`.
|
|
109
|
+
|
|
110
|
+
`function encodeAnimation(width: number, height: number, hasAlpha: boolean, frames: WebPAnimationFrame[]): Promise<Nullable<Uint8Array>>`
|
|
111
|
+
|
|
112
|
+
- hasAlpha: boolean
|
|
113
|
+
|
|
114
|
+
Whether to include alpha chanel.
|
|
115
|
+
|
|
116
|
+
The WebPAnimationFrame has follow properties:
|
|
117
|
+
|
|
118
|
+
- WebPAnimationFrame.data: Uint8Array
|
|
119
|
+
|
|
120
|
+
Frame bitmap.
|
|
121
|
+
|
|
122
|
+
- WebPAnimationFrame.duration: number
|
|
123
|
+
|
|
124
|
+
Duration of frame.
|
|
125
|
+
|
|
126
|
+
##### Example
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
...
|
|
130
|
+
// record each frame
|
|
131
|
+
frames.push({
|
|
132
|
+
data: ctx.getImageData(0, 0, 100, 100).data,
|
|
133
|
+
duration: 20
|
|
134
|
+
})
|
|
135
|
+
const webpData = await encodeAnimation(100, 100, true, frames)
|
|
136
|
+
...
|
|
137
|
+
// download webp
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Decode
|
|
141
|
+
|
|
142
|
+
#### decoderVersion
|
|
143
|
+
|
|
144
|
+
Get decoder version.
|
|
145
|
+
|
|
146
|
+
`function decoderVersion(): Promise<string>`
|
|
147
|
+
|
|
148
|
+
##### Example
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
const version = await decoderVersion()
|
|
152
|
+
console.log(version) // 1.3.2
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### decodeRGB
|
|
156
|
+
|
|
157
|
+
Decodes webp and outputs `WebPDecodedImageData` contains rgb bitmap.
|
|
158
|
+
|
|
159
|
+
`function decodeRGB(data: Uint8Array): Promise<Nullable<WebPDecodedImageData>>`
|
|
160
|
+
|
|
161
|
+
##### Example
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
...
|
|
165
|
+
const fr = new FileReader()
|
|
166
|
+
fr.onload = () => {
|
|
167
|
+
if (!fr.result) {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
webpData = fr.result as Uint8Array
|
|
171
|
+
const result = await decodeRGB(webpData)
|
|
172
|
+
// draw imageData
|
|
173
|
+
const ctx = canvas.getContext('2d')!
|
|
174
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
175
|
+
canvas.style.width = `${result.width}px`
|
|
176
|
+
canvas.style.height = `${result.height}px`
|
|
177
|
+
canvas.width = result.width
|
|
178
|
+
canvas.height = result.height
|
|
179
|
+
ctx.putImageData(result, 0, 0)
|
|
180
|
+
}
|
|
181
|
+
// read webp file
|
|
182
|
+
fr.readAsArrayBuffer(file)
|
|
183
|
+
...
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### decodeRGBA
|
|
187
|
+
|
|
188
|
+
Decodes webp and outputs `WebPDecodedImageData` contains rgba bitmap.
|
|
189
|
+
|
|
190
|
+
`function decodeRGB(data: Uint8Array): Promise<Nullable<WebPDecodedImageData>>`
|
|
191
|
+
|
|
192
|
+
##### Example
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
...
|
|
196
|
+
const fr = new FileReader()
|
|
197
|
+
fr.onload = () => {
|
|
198
|
+
if (!fr.result) {
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
webpData = fr.result as Uint8Array
|
|
202
|
+
const result = await decodeRGBA(webpData)
|
|
203
|
+
// draw imageData
|
|
204
|
+
...
|
|
205
|
+
}
|
|
206
|
+
// webp file
|
|
207
|
+
fr.readAsArrayBuffer(file)
|
|
208
|
+
...
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### WebPDecodedImageData
|
|
212
|
+
|
|
213
|
+
The object have the following properties:
|
|
214
|
+
|
|
215
|
+
- WebPDecodedImageData.width: number
|
|
216
|
+
|
|
217
|
+
The image width in pixels.
|
|
218
|
+
|
|
219
|
+
- WebPDecodedImageData.height: number
|
|
220
|
+
|
|
221
|
+
The image height in pixels.
|
|
222
|
+
|
|
223
|
+
- WebPDecodedImageData.data: Uint8Array
|
|
224
|
+
|
|
225
|
+
Raw data in pixels.
|
|
226
|
+
|
|
227
|
+
> Note: It looks like an `ImageData` object, but it is not. There is actually no `ImageData` in node.
|
|
228
|
+
|
|
229
|
+
## Playing Examples
|
|
230
|
+
|
|
231
|
+
```shell
|
|
232
|
+
npm run dev
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Building
|
|
236
|
+
|
|
237
|
+
```shell
|
|
238
|
+
npm run build
|
|
239
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.decodeRGBA = exports.decodeRGB = exports.decoderVersion = exports.encodeAnimation = exports.encode = exports.encodeRGBA = exports.encodeRGB = exports.encoderVersion = void 0;
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
const webp_wasm_1 = __importDefault(require("./webp-wasm"));
|
|
18
|
+
// default webp config
|
|
19
|
+
const defaultWebpConfig = {
|
|
20
|
+
lossless: 0,
|
|
21
|
+
quality: 100,
|
|
22
|
+
};
|
|
23
|
+
const encoderVersion = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
25
|
+
return module.encoder_version();
|
|
26
|
+
});
|
|
27
|
+
exports.encoderVersion = encoderVersion;
|
|
28
|
+
const encodeRGB = (rgb, width, height, quality) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
30
|
+
quality = typeof quality !== 'number' ? 100 : Math.min(Math.max(0, quality));
|
|
31
|
+
return module.encodeRGB(rgb, width, height, quality);
|
|
32
|
+
});
|
|
33
|
+
exports.encodeRGB = encodeRGB;
|
|
34
|
+
const encodeRGBA = (rgba, width, height, quality) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
36
|
+
quality = typeof quality !== 'number' ? 100 : Math.min(Math.max(0, quality));
|
|
37
|
+
return module.encodeRGBA(rgba, width, height, quality);
|
|
38
|
+
});
|
|
39
|
+
exports.encodeRGBA = encodeRGBA;
|
|
40
|
+
const encode = (data, width, height, hasAlpha, config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
42
|
+
const webpConfig = Object.assign(Object.assign({}, defaultWebpConfig), config);
|
|
43
|
+
return module.encode(data, width, height, hasAlpha, webpConfig);
|
|
44
|
+
});
|
|
45
|
+
exports.encode = encode;
|
|
46
|
+
const encodeAnimation = (width, height, hasAlpha, frames) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
48
|
+
const durations = [];
|
|
49
|
+
const dataLength = frames.reduce((acc, frame) => {
|
|
50
|
+
acc += frame.data.length;
|
|
51
|
+
return acc;
|
|
52
|
+
}, 0);
|
|
53
|
+
const data = new Uint8ClampedArray(dataLength);
|
|
54
|
+
let offset = 0;
|
|
55
|
+
frames.forEach(frame => {
|
|
56
|
+
data.set(frame.data, offset);
|
|
57
|
+
offset += frame.data.length;
|
|
58
|
+
durations.push(frame.duration);
|
|
59
|
+
});
|
|
60
|
+
return module.encodeAnimation(width, height, hasAlpha, durations, data);
|
|
61
|
+
});
|
|
62
|
+
exports.encodeAnimation = encodeAnimation;
|
|
63
|
+
const decoderVersion = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
65
|
+
return module.decoder_version();
|
|
66
|
+
});
|
|
67
|
+
exports.decoderVersion = decoderVersion;
|
|
68
|
+
const decodeRGB = (rgb) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
70
|
+
return module.decodeRGB(rgb);
|
|
71
|
+
});
|
|
72
|
+
exports.decodeRGB = decodeRGB;
|
|
73
|
+
const decodeRGBA = (rgba) => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
+
const module = yield (0, webp_wasm_1.default)();
|
|
75
|
+
return module.decodeRGBA(rgba);
|
|
76
|
+
});
|
|
77
|
+
exports.decodeRGBA = decodeRGBA;
|
|
78
|
+
// TODO:
|
|
79
|
+
// export const decode = async (data: Uint8ClampedArray, hasAlpha: boolean) => {
|
|
80
|
+
// const module = await Module()
|
|
81
|
+
// return module.decode(data, hasAlpha)
|
|
82
|
+
// }
|