imagescript 1.2.9 → 1.2.15
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/ImageScript.d.ts +223 -0
- package/ImageScript.js +10 -46
- package/LICENSE +619 -0
- package/README.md +17 -16
- package/bench/_.mjs +166 -0
- package/bench/all.mjs +4 -0
- package/bench/blur.mjs +59 -0
- package/bench/flip.mjs +63 -0
- package/bench/overlay.mjs +35 -0
- package/bench/package.json +7 -0
- package/bench/readme.md +64 -0
- package/bench/resize.mjs +52 -0
- package/codecs/LICENSE +21 -0
- package/codecs/lib.d.ts +50 -0
- package/codecs/lib.js +6 -0
- package/codecs/lib.mjs +1 -0
- package/codecs/node/bin/arm64-darwin.node +0 -0
- package/{node → codecs/node/bin}/arm64-linux.node +0 -0
- package/codecs/node/bin/x64-darwin.node +0 -0
- package/{node → codecs/node/bin}/x64-linux.node +0 -0
- package/{node → codecs/node/bin}/x64-win32.node +0 -0
- package/codecs/node/index.js +3 -0
- package/codecs/node/index.mjs +6 -0
- package/codecs/package.json +14 -0
- package/codecs/readme.md +38 -0
- package/{wasm/simd.wasm → codecs/tests/gif.js} +0 -0
- package/{wasm/unknown.wasm → codecs/tests/jpeg.js} +0 -0
- package/codecs/tests/png.js +0 -0
- package/codecs/tests/results/gif/1024.nis.gif +0 -0
- package/codecs/tests/results/gif/1024.skyra.gif +0 -0
- package/codecs/tests/results/gif/256.nis.gif +0 -0
- package/codecs/tests/results/gif/256.skyra.gif +0 -0
- package/codecs/tests/results/jpeg/256.jpegjs.jpeg +0 -0
- package/codecs/tests/results/jpeg/256.nis.jpeg +0 -0
- package/codecs/tests/results/jpeg/256.sharp.jpeg +0 -0
- package/codecs/tests/results/jpeg/512.jpegjs.jpeg +0 -0
- package/codecs/tests/results/jpeg/512.nis.jpeg +0 -0
- package/codecs/tests/results/jpeg/512.sharp.jpeg +0 -0
- package/codecs/tests/results/jpeg/64.jpegjs.jpeg +0 -0
- package/codecs/tests/results/jpeg/64.nis.jpeg +0 -0
- package/codecs/tests/results/jpeg/64.sharp.jpeg +0 -0
- package/codecs/tests/results/png/256.jis.png +0 -0
- package/codecs/tests/results/png/256.nis.png +0 -0
- package/codecs/tests/results/png/256.sharp.png +0 -0
- package/codecs/tests/results/png/256.upng.png +0 -0
- package/codecs/tests/results/png/512.jis.png +0 -0
- package/codecs/tests/results/png/512.nis.png +0 -0
- package/codecs/tests/results/png/512.sharp.png +0 -0
- package/codecs/tests/results/png/512.upng.png +0 -0
- package/codecs/tests/results/png/64.jis.png +0 -0
- package/codecs/tests/results/png/64.nis.png +0 -0
- package/codecs/tests/results/png/64.sharp.png +0 -0
- package/codecs/tests/results/png/64.upng.png +0 -0
- package/codecs/tests/webp.js +0 -0
- package/codecs/wasm/bin/codecs.wasm +0 -0
- package/codecs/wasm/bin/simd.wasm +0 -0
- package/codecs/wasm/bundle/browser.js +1 -0
- package/codecs/wasm/index.js +1 -0
- package/codecs/wasm/index.mjs +1 -0
- package/package.json +17 -4
- package/png/src/{crc.js → crc.mjs} +0 -0
- package/png/src/{mem.js → mem.mjs} +0 -0
- package/png/src/{png.js → png.mjs} +3 -3
- package/png/src/{zlib.js → zlib.mjs} +0 -0
- package/tsconfig.json +21 -0
- package/v2/framebuffer.js +93 -112
- package/v2/framebuffer.mjs +8 -8
- package/v2/framebuffer.rs +1264 -0
- package/v2/index.js +1 -1
- package/v2/ops/{blur.js → blur.mjs} +0 -0
- package/v2/ops/{color.js → color.mjs} +0 -0
- package/v2/ops/{crop.js → crop.mjs} +0 -0
- package/v2/ops/{fill.js → fill.mjs} +0 -0
- package/v2/ops/{flip.js → flip.mjs} +0 -0
- package/v2/ops/index.mjs +9 -0
- package/v2/ops/{iterator.js → iterator.mjs} +6 -6
- package/v2/ops/overlay.mjs +63 -0
- package/v2/ops/{resize.js → resize.mjs} +3 -3
- package/v2/ops/{rotate.js → rotate.mjs} +8 -9
- package/v2/util/{mem.js → mem.mjs} +3 -5
- package/wasm/any/font.wasm +0 -0
- package/wasm/any/png.wasm +0 -0
- package/wasm/node/png.js +49 -0
- package/node/arm64-darwin.node +0 -0
- package/node/index.js +0 -7
- package/node/x64-darwin.node +0 -0
- package/v2/ops/index.js +0 -9
- package/v2/ops/overlay.js +0 -56
- package/wasm/node.js +0 -23
- package/wasm/web.js +0 -10
package/ImageScript.d.ts
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
export class Image {
|
|
2
|
+
private __width__: number;
|
|
3
|
+
private __height__: number;
|
|
4
|
+
private __buffer__: ArrayBuffer;
|
|
5
|
+
private __view__: DataView;
|
|
6
|
+
private __u32__: Uint32Array;
|
|
7
|
+
bitmap: Uint8ClampedArray;
|
|
8
|
+
|
|
9
|
+
constructor(width: number, height: number);
|
|
10
|
+
|
|
11
|
+
private toString(): string;
|
|
12
|
+
|
|
13
|
+
get width(): number;
|
|
14
|
+
|
|
15
|
+
get height(): number;
|
|
16
|
+
|
|
17
|
+
* [Symbol.iterator](): void;
|
|
18
|
+
|
|
19
|
+
* iterateWithColors(): Generator<[x: number, y: number, color: number], void, unknown>;
|
|
20
|
+
|
|
21
|
+
static rgbaToColor(r: number, g: number, b: number, a: number): number;
|
|
22
|
+
|
|
23
|
+
static rgbToColor(r: number, g: number, b: number): number;
|
|
24
|
+
|
|
25
|
+
static hslaToColor(h: number, s: number, l: number, a: number): number;
|
|
26
|
+
|
|
27
|
+
static hslToColor(h: number, s: number, l: number): number;
|
|
28
|
+
|
|
29
|
+
static rgbaToHSLA(r: number, g: number, b: number, a: number): number[];
|
|
30
|
+
|
|
31
|
+
static colorToRGBA(color: number): number[];
|
|
32
|
+
|
|
33
|
+
static colorToRGB(color: number): number[];
|
|
34
|
+
|
|
35
|
+
getPixelAt(x: number, y: number): number;
|
|
36
|
+
|
|
37
|
+
getRGBAAt(x: number, y: number): Uint8ClampedArray;
|
|
38
|
+
|
|
39
|
+
setPixelAt(x: number, y: number, pixelColor: number): Image;
|
|
40
|
+
|
|
41
|
+
private __set_pixel__(x: number, y: number, pixelColor: number): void;
|
|
42
|
+
|
|
43
|
+
private __check_boundaries__(x: number, y: number): void;
|
|
44
|
+
|
|
45
|
+
private static get __out_of_bounds__(): string;
|
|
46
|
+
|
|
47
|
+
fill(color: number | colorFunction): Image;
|
|
48
|
+
|
|
49
|
+
clone(): Image;
|
|
50
|
+
|
|
51
|
+
static get RESIZE_NEAREST_NEIGHBOR(): string;
|
|
52
|
+
|
|
53
|
+
static get RESIZE_AUTO(): number;
|
|
54
|
+
|
|
55
|
+
scale(factor: number, mode?: string): Image;
|
|
56
|
+
|
|
57
|
+
private __scale__(factor: number, mode?: string);
|
|
58
|
+
|
|
59
|
+
resize(width: number, height: number, mode?: string): Image;
|
|
60
|
+
|
|
61
|
+
contain(width: number, height: number, mode?: string): Image;
|
|
62
|
+
|
|
63
|
+
fit(width: number, height: number, mode?: string): Image;
|
|
64
|
+
|
|
65
|
+
cover(width: number, height: number, mode?: string): Image;
|
|
66
|
+
|
|
67
|
+
private __resize__(width: number, height: number, mode?: string): Image;
|
|
68
|
+
|
|
69
|
+
private __resize_nearest_neighbor__(width: number, height: number): Image;
|
|
70
|
+
|
|
71
|
+
crop(x: number, y: number, width: number, height: number): Image;
|
|
72
|
+
|
|
73
|
+
private __crop__(x: number, y: number, width: number, height: number): Image;
|
|
74
|
+
|
|
75
|
+
drawBox(x: number, y: number, width: number, height: number, color: number | colorFunction): Image;
|
|
76
|
+
|
|
77
|
+
private __fast_box__(x: number, y: number, width: number, height: number, color: number): Image;
|
|
78
|
+
|
|
79
|
+
drawCircle(x: number, y: number, radius: number, color: number | colorFunction): Image;
|
|
80
|
+
|
|
81
|
+
cropCircle(max?: boolean, feathering?: number): Image;
|
|
82
|
+
|
|
83
|
+
opacity(opacity: number, absolute?: boolean): Image;
|
|
84
|
+
|
|
85
|
+
red(saturation: number, absolute?: boolean): Image;
|
|
86
|
+
|
|
87
|
+
green(saturation: number, absolute?: boolean): Image;
|
|
88
|
+
|
|
89
|
+
blue(saturation: number, absolute?: boolean): Image;
|
|
90
|
+
|
|
91
|
+
private __set_channel_value__(value: number, absolute: boolean, offset: number): void;
|
|
92
|
+
|
|
93
|
+
lightness(value: number, absolute?: boolean): Image;
|
|
94
|
+
|
|
95
|
+
saturation(value: number, absolute?: boolean): Image;
|
|
96
|
+
|
|
97
|
+
composite(source: Image, x?: number, y?: number): Image;
|
|
98
|
+
|
|
99
|
+
invert(): Image;
|
|
100
|
+
|
|
101
|
+
invertValue(): Image;
|
|
102
|
+
|
|
103
|
+
invertSaturation(): Image;
|
|
104
|
+
|
|
105
|
+
invertHue(): Image;
|
|
106
|
+
|
|
107
|
+
hueShift(degrees: number): Image;
|
|
108
|
+
|
|
109
|
+
averageColor(): number;
|
|
110
|
+
|
|
111
|
+
dominantColor(ignoreBlack?: boolean, ignoreWhite?: boolean, bwThreshold?: number): number;
|
|
112
|
+
|
|
113
|
+
rotate(angle: number, resize?: boolean): Image;
|
|
114
|
+
|
|
115
|
+
private __apply__(image: Image | Frame): Image | Frame;
|
|
116
|
+
|
|
117
|
+
static gradient(colors: { [position: number]: number; }): ((position: number) => number);
|
|
118
|
+
|
|
119
|
+
roundCorners(radius?: number): Image;
|
|
120
|
+
|
|
121
|
+
private static __gradient__(startColor: number, endColor: number): number;
|
|
122
|
+
|
|
123
|
+
fisheye(radius?: number): Image;
|
|
124
|
+
|
|
125
|
+
async encode(compression?: number, metadata?: PNGMetadata): Promise<Uint8Array>;
|
|
126
|
+
async encode(metadata?: PNGMetadata): Promise<Uint8Array>;
|
|
127
|
+
|
|
128
|
+
async encodeJPEG(quality?: number): Promise<Uint8Array>;
|
|
129
|
+
|
|
130
|
+
async encodeWEBP(quality?: null | number): Promise<Uint8Array>;
|
|
131
|
+
|
|
132
|
+
static async encode(data: Buffer | Uint8Array): Promise<Image>
|
|
133
|
+
|
|
134
|
+
static get SVG_MODE_SCALE(): number;
|
|
135
|
+
|
|
136
|
+
static get SVG_MODE_WIDTH(): number;
|
|
137
|
+
|
|
138
|
+
static get SVG_MODE_HEIGHT(): number;
|
|
139
|
+
|
|
140
|
+
static async renderSVG(svg: string, size?: number, mode?: number): Promise<Image>;
|
|
141
|
+
|
|
142
|
+
static async renderText(font: Uint8Array, scale: number, text: string, color?: number, layout?: TextLayout): Promise<Image>;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export class Frame extends Image {
|
|
146
|
+
static get DISPOSAL_KEEP(): string;
|
|
147
|
+
|
|
148
|
+
static get DISPOSAL_PREVIOUS(): string;
|
|
149
|
+
|
|
150
|
+
static get DISPOSAL_BACKGROUND(): string
|
|
151
|
+
|
|
152
|
+
private static __convert_disposal_mode__(mode: string | number): any;
|
|
153
|
+
|
|
154
|
+
constructor(width: number, height: number, duration?: number, xOffset?: number, yOffset?: number, disposalMode?: typeof Frame.DISPOSAL_KEEP | string);
|
|
155
|
+
|
|
156
|
+
toString(): string;
|
|
157
|
+
|
|
158
|
+
static from(image: Image, duration?: number, xOffset?: number, yOffset?: number, disposalMode?: typeof Frame.DISPOSAL_KEEP | string): Frame;
|
|
159
|
+
|
|
160
|
+
resize(width: number, height: number, mode?: typeof Image.RESIZE_NEAREST_NEIGHBOR | string): Image;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export class GIF extends Array {
|
|
164
|
+
constructor(frames: Frame[], loopCount?: number);
|
|
165
|
+
|
|
166
|
+
get width(): number;
|
|
167
|
+
|
|
168
|
+
get height(): number;
|
|
169
|
+
|
|
170
|
+
toString(): string;
|
|
171
|
+
|
|
172
|
+
* [Symbol.iterator](): Generator<Frame, void, *>
|
|
173
|
+
|
|
174
|
+
slice(start: number, end: number): GIF;
|
|
175
|
+
|
|
176
|
+
get duration(): number;
|
|
177
|
+
|
|
178
|
+
async encode(quality?: number): Promise<Uint8Array>
|
|
179
|
+
|
|
180
|
+
static async decode(data: Buffer | Uint8Array, onlyExtractFirstFrame?: boolean): Promise<GIF>;
|
|
181
|
+
|
|
182
|
+
resize(width: number, height: number, mode?: typeof Image.RESIZE_NEAREST_NEIGHBOR | string): void;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export class TextLayout {
|
|
186
|
+
constructor(options?: {
|
|
187
|
+
maxWidth?: number,
|
|
188
|
+
maxHeight?: number,
|
|
189
|
+
wrapStyle?: string,
|
|
190
|
+
verticalAlign?: string,
|
|
191
|
+
horizontalAlign?: string,
|
|
192
|
+
wrapHardBreaks?: boolean
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export class ImageType {
|
|
197
|
+
static getType(data: Buffer | Uint8Array): string | null;
|
|
198
|
+
|
|
199
|
+
static isPNG(view: DataView): boolean;
|
|
200
|
+
|
|
201
|
+
static isJPEG(view: DataView): boolean;
|
|
202
|
+
|
|
203
|
+
static isTIFF(view: DataView): boolean;
|
|
204
|
+
|
|
205
|
+
static isGIF(view: DataView): boolean;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export function decode(data: Uint8Array | Buffer, onlyExtractFirstFrame?: boolean): Promise<GIF | Image>;
|
|
209
|
+
|
|
210
|
+
type colorFunction = (x: number, y: number) => number;
|
|
211
|
+
|
|
212
|
+
type PNGMetadata = {
|
|
213
|
+
title?: string,
|
|
214
|
+
author?: string,
|
|
215
|
+
description?: string,
|
|
216
|
+
copyright?: string,
|
|
217
|
+
creationTime?: string | number | Date,
|
|
218
|
+
software?: string,
|
|
219
|
+
disclaimer?: string,
|
|
220
|
+
warning?: string,
|
|
221
|
+
source?: string,
|
|
222
|
+
comment?: string
|
|
223
|
+
};
|
package/ImageScript.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
const png = require('./png/node.js');
|
|
2
2
|
const mem = require('./utils/mem.js');
|
|
3
|
-
const codecs = require('./node/index.js');
|
|
4
3
|
const {version} = require('./package.json');
|
|
4
|
+
const codecs = require('./codecs/node/index.js');
|
|
5
5
|
const { default: v2 } = require('./v2/framebuffer.js');
|
|
6
6
|
|
|
7
7
|
// old
|
|
8
8
|
const svglib = require('./wasm/node/svg.js');
|
|
9
9
|
const giflib = require('./wasm/node/gif.js');
|
|
10
|
+
const pnglib = require('./wasm/node/png.js');
|
|
10
11
|
const fontlib = require('./wasm/node/font.js');
|
|
11
12
|
const jpeglib = require('./wasm/node/jpeg.js');
|
|
12
13
|
const tifflib = require('./wasm/node/tiff.js');
|
|
@@ -83,16 +84,16 @@ class Image {
|
|
|
83
84
|
* @yields {number[]} The coordinates of the pixel ([x, y])
|
|
84
85
|
* @returns {void}
|
|
85
86
|
*/
|
|
86
|
-
[Symbol.iterator]() {
|
|
87
|
-
|
|
87
|
+
*[Symbol.iterator]() {
|
|
88
|
+
for (const x of new v2(this.width, this.height, this.bitmap)[Symbol.iterator]()) yield (x[0]++, x[1]++, x)
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
/**
|
|
91
92
|
* Yields an [x, y, color] array for every pixel in the image
|
|
92
93
|
* @yields {number[]} The coordinates and color of the pixel ([x, y, color])
|
|
93
94
|
*/
|
|
94
|
-
iterateWithColors() {
|
|
95
|
-
|
|
95
|
+
*iterateWithColors() {
|
|
96
|
+
for (const x of new v2(this.width, this.height, this.bitmap).pixels('int')) yield (x[0]++, x[1]++, x);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
/**
|
|
@@ -693,48 +694,11 @@ class Image {
|
|
|
693
694
|
* @returns {Image}
|
|
694
695
|
*/
|
|
695
696
|
composite(source, x = 0, y = 0) {
|
|
696
|
-
|
|
697
|
-
y = ~~y;
|
|
698
|
-
|
|
699
|
-
for (let yy = 0; yy < source.height; yy++) {
|
|
700
|
-
let y_offset = y + yy;
|
|
701
|
-
if (y_offset < 0) continue;
|
|
702
|
-
if (y_offset >= this.height) break;
|
|
703
|
-
|
|
704
|
-
for (let xx = 0; xx < source.width; xx++) {
|
|
705
|
-
let x_offset = x + xx;
|
|
706
|
-
if (x_offset < 0) continue;
|
|
707
|
-
if (x_offset >= this.width) break;
|
|
708
|
-
|
|
709
|
-
const offset = 4 * (x_offset + y_offset * this.width);
|
|
710
|
-
const fg = source.__view__.getUint32(4 * (xx + yy * source.width), false);
|
|
711
|
-
const bg = this.__view__.getUint32(offset, false);
|
|
712
|
-
|
|
713
|
-
if ((fg & 0xff) === 0xff) this.__view__.setUint32(offset, fg, false);
|
|
714
|
-
else if ((fg & 0xff) === 0x00) this.__view__.setUint32(offset, bg, false);
|
|
715
|
-
else this.__view__.setUint32(offset, Image.__alpha_blend__(fg, bg), false);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
697
|
+
new v2(this.width, this.height, this.bitmap).overlay(new v2(source.width, source.height, source.bitmap), x, y);
|
|
718
698
|
|
|
719
699
|
return this;
|
|
720
700
|
}
|
|
721
701
|
|
|
722
|
-
/**
|
|
723
|
-
* @private
|
|
724
|
-
* @param {number} fg
|
|
725
|
-
* @param {number} bg
|
|
726
|
-
* @returns {number}
|
|
727
|
-
*/
|
|
728
|
-
static __alpha_blend__(fg, bg) {
|
|
729
|
-
const fa = fg & 0xff;
|
|
730
|
-
const alpha = fa + 1;
|
|
731
|
-
const inv_alpha = 256 - fa;
|
|
732
|
-
const r = (alpha * (fg >>> 24) + inv_alpha * (bg >>> 24)) >> 8;
|
|
733
|
-
const b = (alpha * (fg >> 8 & 0xff) + inv_alpha * (bg >> 8 & 0xff)) >> 8;
|
|
734
|
-
const g = (alpha * (fg >> 16 & 0xff) + inv_alpha * (bg >> 16 & 0xff)) >> 8;
|
|
735
|
-
return (((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | (Math.max(fa, bg & 0xff) & 0xff));
|
|
736
|
-
}
|
|
737
|
-
|
|
738
702
|
/**
|
|
739
703
|
* Inverts the images colors
|
|
740
704
|
* @returns {Image}
|
|
@@ -1119,9 +1083,9 @@ class Image {
|
|
|
1119
1083
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
1120
1084
|
|
|
1121
1085
|
if (ImageType.isPNG(view)) { // PNG
|
|
1122
|
-
const {width, height,
|
|
1086
|
+
const {width, height, framebuffer} = (await pnglib.init()).decode(data);
|
|
1123
1087
|
image = new Image(width, height);
|
|
1124
|
-
image.bitmap.set(
|
|
1088
|
+
image.bitmap.set(framebuffer);
|
|
1125
1089
|
} else if (ImageType.isJPEG(view)) { // JPEG
|
|
1126
1090
|
const framebuffer = (await jpeglib.init()).decode(data);
|
|
1127
1091
|
|
|
@@ -1535,7 +1499,7 @@ class GIF extends Array {
|
|
|
1535
1499
|
}
|
|
1536
1500
|
|
|
1537
1501
|
else if (0 === mode || 1 === mode) {
|
|
1538
|
-
t8.set(u8)
|
|
1502
|
+
t8.set(u8);
|
|
1539
1503
|
for (let y = 0 | 0; y < height; y++) {
|
|
1540
1504
|
const y_offset = fx + gwidth * (y + fy) | 0;
|
|
1541
1505
|
|