imagescript 1.2.15 → 1.2.17
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 +233 -223
- package/ImageScript.js +1658 -1646
- package/LICENSE +12 -619
- package/LICENSE.AGPL-3.0 +619 -0
- package/LICENSE.MIT +19 -0
- package/README.md +51 -46
- package/bench/_.mjs +165 -165
- package/bench/all.mjs +3 -3
- package/bench/blur.mjs +58 -58
- package/bench/flip.mjs +62 -62
- package/bench/overlay.mjs +34 -34
- package/bench/package.json +6 -6
- package/bench/readme.md +63 -63
- package/bench/resize.mjs +51 -51
- package/codecs/LICENSE +20 -20
- package/codecs/lib.d.ts +49 -49
- package/codecs/lib.js +5 -5
- package/codecs/node/index.js +2 -2
- package/codecs/node/index.mjs +5 -5
- package/codecs/package.json +13 -13
- package/codecs/readme.md +37 -37
- package/package.json +41 -41
- package/png/node.js +1137 -1137
- package/png/src/crc.mjs +48 -48
- package/png/src/mem.mjs +23 -23
- package/png/src/png.mjs +254 -254
- package/png/src/zlib.mjs +617 -617
- package/tsconfig.json +21 -21
- package/utils/mem.js +25 -25
- package/v2/codecs/magic.js +24 -24
- package/v2/framebuffer.d.ts +66 -66
- package/v2/framebuffer.js +2352 -2352
- package/v2/framebuffer.mjs +125 -125
- package/v2/framebuffer.rs +1263 -1263
- package/v2/index.d.ts +83 -83
- package/v2/index.js +260 -260
- package/v2/ops/blur.mjs +302 -302
- package/v2/ops/color.mjs +276 -276
- package/v2/ops/crop.mjs +63 -63
- package/v2/ops/fill.mjs +32 -32
- package/v2/ops/flip.mjs +32 -32
- package/v2/ops/index.mjs +8 -8
- package/v2/ops/iterator.mjs +33 -33
- package/v2/ops/overlay.mjs +62 -62
- package/v2/ops/resize.mjs +165 -165
- package/v2/ops/rotate.mjs +116 -116
- package/v2/util/mem.mjs +23 -23
- package/wasm/node/font.js +141 -141
- package/wasm/node/gif.js +76 -76
- package/wasm/node/jpeg.js +91 -91
- package/wasm/node/png.js +49 -49
- package/wasm/node/svg.js +55 -55
- package/wasm/node/tiff.js +46 -46
package/png/src/crc.mjs
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
const table = new Uint32Array([
|
|
2
|
-
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
|
|
3
|
-
0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
|
|
4
|
-
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
|
|
5
|
-
0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
|
6
|
-
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
|
|
7
|
-
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
|
|
8
|
-
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
|
|
9
|
-
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
|
10
|
-
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
|
|
11
|
-
0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
|
|
12
|
-
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
|
|
13
|
-
0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
|
14
|
-
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
|
|
15
|
-
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
|
|
16
|
-
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
|
|
17
|
-
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
|
18
|
-
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
|
|
19
|
-
0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
|
|
20
|
-
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
|
|
21
|
-
0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
|
22
|
-
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
|
|
23
|
-
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
|
|
24
|
-
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
|
|
25
|
-
0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
|
26
|
-
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
|
|
27
|
-
0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
|
|
28
|
-
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
|
|
29
|
-
0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
|
30
|
-
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]);
|
|
31
|
-
|
|
32
|
-
export function crc32(buffer) {
|
|
33
|
-
let offset = 0 | 0;
|
|
34
|
-
let crc = 0xFFFFFFFF | 0;
|
|
35
|
-
const bl = (buffer.length - 4) | 0;
|
|
36
|
-
|
|
37
|
-
while (bl > offset) {
|
|
38
|
-
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
39
|
-
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
40
|
-
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
41
|
-
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
while (offset < buffer.length) {
|
|
45
|
-
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return (crc ^ 0xFFFFFFFF) >>> 0;
|
|
1
|
+
const table = new Uint32Array([
|
|
2
|
+
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
|
|
3
|
+
0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
|
|
4
|
+
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
|
|
5
|
+
0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
|
6
|
+
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
|
|
7
|
+
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
|
|
8
|
+
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
|
|
9
|
+
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
|
10
|
+
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
|
|
11
|
+
0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
|
|
12
|
+
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
|
|
13
|
+
0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
|
14
|
+
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
|
|
15
|
+
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
|
|
16
|
+
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
|
|
17
|
+
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
|
18
|
+
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
|
|
19
|
+
0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
|
|
20
|
+
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
|
|
21
|
+
0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
|
22
|
+
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
|
|
23
|
+
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
|
|
24
|
+
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
|
|
25
|
+
0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
|
26
|
+
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
|
|
27
|
+
0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
|
|
28
|
+
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
|
|
29
|
+
0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
|
30
|
+
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]);
|
|
31
|
+
|
|
32
|
+
export function crc32(buffer) {
|
|
33
|
+
let offset = 0 | 0;
|
|
34
|
+
let crc = 0xFFFFFFFF | 0;
|
|
35
|
+
const bl = (buffer.length - 4) | 0;
|
|
36
|
+
|
|
37
|
+
while (bl > offset) {
|
|
38
|
+
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
39
|
+
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
40
|
+
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
41
|
+
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
while (offset < buffer.length) {
|
|
45
|
+
crc = table[(crc ^ buffer[offset++]) & 0xff] ^ (crc >>> 8);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (crc ^ 0xFFFFFFFF) >>> 0;
|
|
49
49
|
}
|
package/png/src/mem.mjs
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
export function view(buffer, shared = false) {
|
|
2
|
-
if (buffer instanceof ArrayBuffer) return new Uint8Array(buffer);
|
|
3
|
-
if (shared && buffer instanceof SharedArrayBuffer) return new Uint8Array(buffer);
|
|
4
|
-
if (ArrayBuffer.isView(buffer)) return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
5
|
-
|
|
6
|
-
throw new TypeError("The provided value is not of type '(ArrayBuffer or ArrayBufferView)'");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function from_parts(buffers, shared = false) {
|
|
10
|
-
let length = 0;
|
|
11
|
-
let offset = 0;
|
|
12
|
-
buffers.forEach(buffer => length += (null == buffer.byteLength ? buffer.length : buffer.byteLength));
|
|
13
|
-
|
|
14
|
-
const u8 = new Uint8Array(shared ? new SharedArrayBuffer(length) : length);
|
|
15
|
-
|
|
16
|
-
buffers.forEach(buffer => {
|
|
17
|
-
const ref = Array.isArray(buffer) ? buffer : view(buffer, true);
|
|
18
|
-
|
|
19
|
-
u8.set(ref, offset);
|
|
20
|
-
offset += ref.length;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return u8;
|
|
1
|
+
export function view(buffer, shared = false) {
|
|
2
|
+
if (buffer instanceof ArrayBuffer) return new Uint8Array(buffer);
|
|
3
|
+
if (shared && buffer instanceof SharedArrayBuffer) return new Uint8Array(buffer);
|
|
4
|
+
if (ArrayBuffer.isView(buffer)) return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
5
|
+
|
|
6
|
+
throw new TypeError("The provided value is not of type '(ArrayBuffer or ArrayBufferView)'");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function from_parts(buffers, shared = false) {
|
|
10
|
+
let length = 0;
|
|
11
|
+
let offset = 0;
|
|
12
|
+
buffers.forEach(buffer => length += (null == buffer.byteLength ? buffer.length : buffer.byteLength));
|
|
13
|
+
|
|
14
|
+
const u8 = new Uint8Array(shared ? new SharedArrayBuffer(length) : length);
|
|
15
|
+
|
|
16
|
+
buffers.forEach(buffer => {
|
|
17
|
+
const ref = Array.isArray(buffer) ? buffer : view(buffer, true);
|
|
18
|
+
|
|
19
|
+
u8.set(ref, offset);
|
|
20
|
+
offset += ref.length;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return u8;
|
|
24
24
|
}
|
package/png/src/png.mjs
CHANGED
|
@@ -1,254 +1,254 @@
|
|
|
1
|
-
import { crc32 } from './crc.mjs';
|
|
2
|
-
import { from_parts } from './mem.mjs';
|
|
3
|
-
import { compress, decompress } from './zlib.mjs';
|
|
4
|
-
|
|
5
|
-
const __IHDR__ = new Uint8Array([73, 72, 68, 82]);
|
|
6
|
-
const __IDAT__ = new Uint8Array([73, 68, 65, 84]);
|
|
7
|
-
const __IEND__ = new Uint8Array([73, 69, 78, 68]);
|
|
8
|
-
const __IEND_CRC__ = crc32(new Uint8Array([73, 69, 78, 68]));
|
|
9
|
-
const HEAD = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
10
|
-
|
|
11
|
-
const color_types = {
|
|
12
|
-
GREYSCALE: 0,
|
|
13
|
-
TRUECOLOR: 2,
|
|
14
|
-
INDEXED_COLOR: 3,
|
|
15
|
-
GREYSCALE_ALPHA: 4,
|
|
16
|
-
TRUECOLOR_ALPHA: 6
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const channels_to_color_type = {
|
|
20
|
-
1: color_types.GREYSCALE,
|
|
21
|
-
2: color_types.GREYSCALE_ALPHA,
|
|
22
|
-
|
|
23
|
-
3: color_types.TRUECOLOR,
|
|
24
|
-
4: color_types.TRUECOLOR_ALPHA
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const utf8encoder = new TextEncoder; // replace with latin1 encoder or iext
|
|
28
|
-
|
|
29
|
-
export function encode(data, { text, width, height, channels, depth = 8, level = 0 }) {
|
|
30
|
-
let offset = 0;
|
|
31
|
-
let tmp_offset = 0;
|
|
32
|
-
const row_length = width * channels;
|
|
33
|
-
const tmp = new Uint8Array(height + data.length);
|
|
34
|
-
|
|
35
|
-
while (offset < data.length) {
|
|
36
|
-
tmp[tmp_offset++] = 0;
|
|
37
|
-
tmp.set(data.subarray(offset, (offset += row_length)), tmp_offset);
|
|
38
|
-
|
|
39
|
-
tmp_offset += row_length;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (text) {
|
|
43
|
-
let chunks = [];
|
|
44
|
-
for (const key in text) {
|
|
45
|
-
if (!text[key]) continue;
|
|
46
|
-
const kb = utf8encoder.encode(key);
|
|
47
|
-
const tb = utf8encoder.encode(text[key]);
|
|
48
|
-
const chunk = new Uint8Array(1 + 12 + kb.length + tb.length);
|
|
49
|
-
|
|
50
|
-
const view = new DataView(chunk.buffer);
|
|
51
|
-
|
|
52
|
-
chunk[4] = 0x74;
|
|
53
|
-
chunk[5] = 0x45;
|
|
54
|
-
chunk[6] = 0x58;
|
|
55
|
-
chunk[7] = 0x74;
|
|
56
|
-
chunk.set(kb, 8);
|
|
57
|
-
chunks.push(chunk);
|
|
58
|
-
chunk.set(tb, 9 + kb.length);
|
|
59
|
-
view.setUint32(0, chunk.length - 12);
|
|
60
|
-
view.setUint32(chunk.length - 4, crc32(chunk.subarray(4, chunk.length - 4)));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
text = from_parts(chunks);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
offset = text ? text.length : 0;
|
|
67
|
-
const compressed = compress(tmp, level);
|
|
68
|
-
const array = new Uint8Array(49 + offset + HEAD.length + compressed.length);
|
|
69
|
-
|
|
70
|
-
array[26] = 0;
|
|
71
|
-
array[27] = 0;
|
|
72
|
-
array[28] = 0;
|
|
73
|
-
array[24] = depth;
|
|
74
|
-
array.set(HEAD, 0);
|
|
75
|
-
array.set(__IHDR__, 12);
|
|
76
|
-
array.set(__IDAT__, 37);
|
|
77
|
-
array.set(compressed, 41);
|
|
78
|
-
array[25] = channels_to_color_type[channels];
|
|
79
|
-
if (text) array.set(text, 45 + compressed.length);
|
|
80
|
-
array.set(__IEND__, 49 + offset + compressed.length);
|
|
81
|
-
|
|
82
|
-
const view = new DataView(array.buffer);
|
|
83
|
-
|
|
84
|
-
view.setUint32(8, 13);
|
|
85
|
-
view.setUint32(16, width);
|
|
86
|
-
view.setUint32(20, height);
|
|
87
|
-
view.setUint32(33, compressed.length);
|
|
88
|
-
view.setUint32(45 + offset + compressed.length, 0);
|
|
89
|
-
view.setUint32(53 + offset + compressed.length, __IEND_CRC__);
|
|
90
|
-
view.setUint32(29, crc32(new Uint8Array(array.buffer, 12, 17)));
|
|
91
|
-
view.setUint32(41 + compressed.length, crc32(new Uint8Array(array.buffer, 37, 4 + compressed.length)));
|
|
92
|
-
|
|
93
|
-
return array;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function decode(array) {
|
|
97
|
-
let view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
98
|
-
|
|
99
|
-
const width = view.getUint32(16);
|
|
100
|
-
const height = view.getUint32(20);
|
|
101
|
-
const bpc = array[24];
|
|
102
|
-
const pixel_type = array[25];
|
|
103
|
-
let channels = ({ 3: 1, 0: 1, 4: 2, 2: 3, 6: 4 })[pixel_type];
|
|
104
|
-
const bytespp = channels * bpc / 8;
|
|
105
|
-
|
|
106
|
-
const row_length = width * bytespp;
|
|
107
|
-
let pixels = new Uint8Array(height * row_length);
|
|
108
|
-
|
|
109
|
-
let offset = 0;
|
|
110
|
-
let p_offset = 0;
|
|
111
|
-
|
|
112
|
-
let c_offset = 33;
|
|
113
|
-
const chunks = [];
|
|
114
|
-
|
|
115
|
-
let palette, alphaPalette;
|
|
116
|
-
|
|
117
|
-
const maxSearchOffset = array.length - 5;
|
|
118
|
-
|
|
119
|
-
let type;
|
|
120
|
-
while ((type = view.getUint32(4 + c_offset)) !== 1229278788) { // IEND
|
|
121
|
-
if (type === 1229209940) // IDAT
|
|
122
|
-
chunks.push(array.subarray(8 + c_offset, 8 + c_offset + view.getUint32(c_offset)));
|
|
123
|
-
else if (type === 1347179589) { // PLTE
|
|
124
|
-
if (palette)
|
|
125
|
-
throw new Error('PLTE can only occur once in an image');
|
|
126
|
-
palette = new Uint32Array(view.getUint32(c_offset));
|
|
127
|
-
for (let pxlOffset = 0; pxlOffset < palette.length * 8; pxlOffset += 3)
|
|
128
|
-
palette[pxlOffset / 3] = array[8 + c_offset + pxlOffset] << 24 | array[8 + c_offset + pxlOffset + 1] << 16 | array[8 + c_offset + pxlOffset + 2] << 8 | 0xff;
|
|
129
|
-
} else if (type === 1951551059) { // tRNS
|
|
130
|
-
if (alphaPalette)
|
|
131
|
-
throw new Error('tRNS can only occur once in an image');
|
|
132
|
-
alphaPalette = new Uint8Array(view.getUint32(c_offset));
|
|
133
|
-
for (let i = 0; i < alphaPalette.length; i++)
|
|
134
|
-
alphaPalette[i] = array[8 + c_offset + i];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
c_offset += 4 + 4 + 4 + view.getUint32(c_offset);
|
|
138
|
-
if (c_offset > maxSearchOffset) // missing IEND
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
array = decompress(chunks.length === 1 ? chunks[0] : from_parts(chunks), height + height * row_length);
|
|
143
|
-
|
|
144
|
-
while (offset < array.byteLength) {
|
|
145
|
-
const filter = array[offset++];
|
|
146
|
-
const slice = array.subarray(offset, offset += row_length);
|
|
147
|
-
|
|
148
|
-
if (0 === filter) pixels.set(slice, p_offset);
|
|
149
|
-
else if (1 === filter) filter_1(slice, pixels, p_offset, bytespp, row_length);
|
|
150
|
-
else if (2 === filter) filter_2(slice, pixels, p_offset, bytespp, row_length);
|
|
151
|
-
else if (3 === filter) filter_3(slice, pixels, p_offset, bytespp, row_length);
|
|
152
|
-
else if (4 === filter) filter_4(slice, pixels, p_offset, bytespp, row_length);
|
|
153
|
-
|
|
154
|
-
p_offset += row_length;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (pixel_type === 3) {
|
|
158
|
-
if (!palette)
|
|
159
|
-
throw new Error('Indexed color PNG has no PLTE');
|
|
160
|
-
|
|
161
|
-
if (alphaPalette)
|
|
162
|
-
for (let i = 0; i < alphaPalette.length; i++)
|
|
163
|
-
palette[i] &= 0xffffff00 | alphaPalette[i];
|
|
164
|
-
|
|
165
|
-
channels = 4;
|
|
166
|
-
const newPixels = new Uint8Array(width * height * 4);
|
|
167
|
-
const pixelView = new DataView(newPixels.buffer, newPixels.byteOffset, newPixels.byteLength);
|
|
168
|
-
for (let i = 0; i < pixels.length; i++)
|
|
169
|
-
pixelView.setUint32(i * 4, palette[pixels[i]], false);
|
|
170
|
-
pixels = newPixels;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (bpc !== 8) {
|
|
174
|
-
const newPixels = new Uint8Array(pixels.length / bpc * 8);
|
|
175
|
-
for (let i = 0; i < pixels.length; i += 2)
|
|
176
|
-
newPixels[i / 2] = pixels[i];
|
|
177
|
-
pixels = newPixels;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (channels !== 4) {
|
|
181
|
-
const newPixels = new Uint8Array(width * height * 4);
|
|
182
|
-
const view = new DataView(newPixels.buffer);
|
|
183
|
-
|
|
184
|
-
if (channels === 1) {
|
|
185
|
-
for (let i = 0; i < width * height; i++) {
|
|
186
|
-
const pixel = pixels[i];
|
|
187
|
-
view.setUint32(i * 4, pixel << 24 | pixel << 16 | pixel << 8 | 0xff, false);
|
|
188
|
-
}
|
|
189
|
-
} else if (channels === 2) {
|
|
190
|
-
for (let i = 0; i < width * height * 2; i += 2) {
|
|
191
|
-
const pixel = pixels[i];
|
|
192
|
-
view.setUint32(i * 2, pixel << 24 | pixel << 16 | pixel << 8 | pixels[i + 1], false);
|
|
193
|
-
}
|
|
194
|
-
} else if (channels === 3) {
|
|
195
|
-
newPixels.fill(0xff);
|
|
196
|
-
for (let i = 0; i < width * height; i++)
|
|
197
|
-
newPixels.set(pixels.subarray(i * 3, i * 3 + 3), i * 4);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
pixels = newPixels;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return { width, height, buffer: pixels };
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function filter_1(slice, pixels, p_offset, bytespp, row_length) {
|
|
207
|
-
let i = 0;
|
|
208
|
-
while (i < bytespp) pixels[i + p_offset] = slice[i++];
|
|
209
|
-
while (i < row_length) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - bytespp];
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function filter_2(slice, pixels, p_offset, bytespp, row_length) {
|
|
213
|
-
if (0 === p_offset) pixels.set(slice, p_offset);
|
|
214
|
-
else {
|
|
215
|
-
let i = 0;
|
|
216
|
-
while (i < row_length) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - row_length];
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function filter_3(slice, pixels, p_offset, bytespp, row_length) {
|
|
221
|
-
let i = 0;
|
|
222
|
-
|
|
223
|
-
if (0 === p_offset) {
|
|
224
|
-
while (i < bytespp) pixels[i] = slice[i++];
|
|
225
|
-
while (i < row_length) pixels[i] = slice[i] + (pixels[i++ - bytespp] >> 1);
|
|
226
|
-
} else {
|
|
227
|
-
while (i < bytespp) pixels[i + p_offset] = slice[i] + (pixels[i++ + p_offset - row_length] >> 1);
|
|
228
|
-
while (i < row_length) pixels[i + p_offset] = slice[i] + (pixels[i + p_offset - bytespp] + pixels[i++ + p_offset - row_length] >> 1);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function filter_4(slice, pixels, p_offset, bytespp, row_length) {
|
|
233
|
-
let i = 0;
|
|
234
|
-
|
|
235
|
-
if (0 === p_offset) {
|
|
236
|
-
while (i < bytespp) pixels[i] = slice[i++];
|
|
237
|
-
while (i < row_length) pixels[i] = slice[i] + pixels[i++ - bytespp];
|
|
238
|
-
} else {
|
|
239
|
-
while (i < bytespp) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - row_length];
|
|
240
|
-
|
|
241
|
-
while (i < row_length) {
|
|
242
|
-
const a = pixels[i + p_offset - bytespp];
|
|
243
|
-
const b = pixels[i + p_offset - row_length];
|
|
244
|
-
const c = pixels[i + p_offset - bytespp - row_length];
|
|
245
|
-
|
|
246
|
-
const p = a + b - c;
|
|
247
|
-
const pa = Math.abs(p - a);
|
|
248
|
-
const pb = Math.abs(p - b);
|
|
249
|
-
const pc = Math.abs(p - c);
|
|
250
|
-
|
|
251
|
-
pixels[i + p_offset] = slice[i++] + ((pa <= pb && pa <= pc) ? a : ((pb <= pc) ? b : c));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
1
|
+
import { crc32 } from './crc.mjs';
|
|
2
|
+
import { from_parts } from './mem.mjs';
|
|
3
|
+
import { compress, decompress } from './zlib.mjs';
|
|
4
|
+
|
|
5
|
+
const __IHDR__ = new Uint8Array([73, 72, 68, 82]);
|
|
6
|
+
const __IDAT__ = new Uint8Array([73, 68, 65, 84]);
|
|
7
|
+
const __IEND__ = new Uint8Array([73, 69, 78, 68]);
|
|
8
|
+
const __IEND_CRC__ = crc32(new Uint8Array([73, 69, 78, 68]));
|
|
9
|
+
const HEAD = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
10
|
+
|
|
11
|
+
const color_types = {
|
|
12
|
+
GREYSCALE: 0,
|
|
13
|
+
TRUECOLOR: 2,
|
|
14
|
+
INDEXED_COLOR: 3,
|
|
15
|
+
GREYSCALE_ALPHA: 4,
|
|
16
|
+
TRUECOLOR_ALPHA: 6
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const channels_to_color_type = {
|
|
20
|
+
1: color_types.GREYSCALE,
|
|
21
|
+
2: color_types.GREYSCALE_ALPHA,
|
|
22
|
+
|
|
23
|
+
3: color_types.TRUECOLOR,
|
|
24
|
+
4: color_types.TRUECOLOR_ALPHA
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const utf8encoder = new TextEncoder; // replace with latin1 encoder or iext
|
|
28
|
+
|
|
29
|
+
export function encode(data, { text, width, height, channels, depth = 8, level = 0 }) {
|
|
30
|
+
let offset = 0;
|
|
31
|
+
let tmp_offset = 0;
|
|
32
|
+
const row_length = width * channels;
|
|
33
|
+
const tmp = new Uint8Array(height + data.length);
|
|
34
|
+
|
|
35
|
+
while (offset < data.length) {
|
|
36
|
+
tmp[tmp_offset++] = 0;
|
|
37
|
+
tmp.set(data.subarray(offset, (offset += row_length)), tmp_offset);
|
|
38
|
+
|
|
39
|
+
tmp_offset += row_length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (text) {
|
|
43
|
+
let chunks = [];
|
|
44
|
+
for (const key in text) {
|
|
45
|
+
if (!text[key]) continue;
|
|
46
|
+
const kb = utf8encoder.encode(key);
|
|
47
|
+
const tb = utf8encoder.encode(text[key]);
|
|
48
|
+
const chunk = new Uint8Array(1 + 12 + kb.length + tb.length);
|
|
49
|
+
|
|
50
|
+
const view = new DataView(chunk.buffer);
|
|
51
|
+
|
|
52
|
+
chunk[4] = 0x74;
|
|
53
|
+
chunk[5] = 0x45;
|
|
54
|
+
chunk[6] = 0x58;
|
|
55
|
+
chunk[7] = 0x74;
|
|
56
|
+
chunk.set(kb, 8);
|
|
57
|
+
chunks.push(chunk);
|
|
58
|
+
chunk.set(tb, 9 + kb.length);
|
|
59
|
+
view.setUint32(0, chunk.length - 12);
|
|
60
|
+
view.setUint32(chunk.length - 4, crc32(chunk.subarray(4, chunk.length - 4)));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
text = from_parts(chunks);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
offset = text ? text.length : 0;
|
|
67
|
+
const compressed = compress(tmp, level);
|
|
68
|
+
const array = new Uint8Array(49 + offset + HEAD.length + compressed.length);
|
|
69
|
+
|
|
70
|
+
array[26] = 0;
|
|
71
|
+
array[27] = 0;
|
|
72
|
+
array[28] = 0;
|
|
73
|
+
array[24] = depth;
|
|
74
|
+
array.set(HEAD, 0);
|
|
75
|
+
array.set(__IHDR__, 12);
|
|
76
|
+
array.set(__IDAT__, 37);
|
|
77
|
+
array.set(compressed, 41);
|
|
78
|
+
array[25] = channels_to_color_type[channels];
|
|
79
|
+
if (text) array.set(text, 45 + compressed.length);
|
|
80
|
+
array.set(__IEND__, 49 + offset + compressed.length);
|
|
81
|
+
|
|
82
|
+
const view = new DataView(array.buffer);
|
|
83
|
+
|
|
84
|
+
view.setUint32(8, 13);
|
|
85
|
+
view.setUint32(16, width);
|
|
86
|
+
view.setUint32(20, height);
|
|
87
|
+
view.setUint32(33, compressed.length);
|
|
88
|
+
view.setUint32(45 + offset + compressed.length, 0);
|
|
89
|
+
view.setUint32(53 + offset + compressed.length, __IEND_CRC__);
|
|
90
|
+
view.setUint32(29, crc32(new Uint8Array(array.buffer, 12, 17)));
|
|
91
|
+
view.setUint32(41 + compressed.length, crc32(new Uint8Array(array.buffer, 37, 4 + compressed.length)));
|
|
92
|
+
|
|
93
|
+
return array;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function decode(array) {
|
|
97
|
+
let view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
98
|
+
|
|
99
|
+
const width = view.getUint32(16);
|
|
100
|
+
const height = view.getUint32(20);
|
|
101
|
+
const bpc = array[24];
|
|
102
|
+
const pixel_type = array[25];
|
|
103
|
+
let channels = ({ 3: 1, 0: 1, 4: 2, 2: 3, 6: 4 })[pixel_type];
|
|
104
|
+
const bytespp = channels * bpc / 8;
|
|
105
|
+
|
|
106
|
+
const row_length = width * bytespp;
|
|
107
|
+
let pixels = new Uint8Array(height * row_length);
|
|
108
|
+
|
|
109
|
+
let offset = 0;
|
|
110
|
+
let p_offset = 0;
|
|
111
|
+
|
|
112
|
+
let c_offset = 33;
|
|
113
|
+
const chunks = [];
|
|
114
|
+
|
|
115
|
+
let palette, alphaPalette;
|
|
116
|
+
|
|
117
|
+
const maxSearchOffset = array.length - 5;
|
|
118
|
+
|
|
119
|
+
let type;
|
|
120
|
+
while ((type = view.getUint32(4 + c_offset)) !== 1229278788) { // IEND
|
|
121
|
+
if (type === 1229209940) // IDAT
|
|
122
|
+
chunks.push(array.subarray(8 + c_offset, 8 + c_offset + view.getUint32(c_offset)));
|
|
123
|
+
else if (type === 1347179589) { // PLTE
|
|
124
|
+
if (palette)
|
|
125
|
+
throw new Error('PLTE can only occur once in an image');
|
|
126
|
+
palette = new Uint32Array(view.getUint32(c_offset));
|
|
127
|
+
for (let pxlOffset = 0; pxlOffset < palette.length * 8; pxlOffset += 3)
|
|
128
|
+
palette[pxlOffset / 3] = array[8 + c_offset + pxlOffset] << 24 | array[8 + c_offset + pxlOffset + 1] << 16 | array[8 + c_offset + pxlOffset + 2] << 8 | 0xff;
|
|
129
|
+
} else if (type === 1951551059) { // tRNS
|
|
130
|
+
if (alphaPalette)
|
|
131
|
+
throw new Error('tRNS can only occur once in an image');
|
|
132
|
+
alphaPalette = new Uint8Array(view.getUint32(c_offset));
|
|
133
|
+
for (let i = 0; i < alphaPalette.length; i++)
|
|
134
|
+
alphaPalette[i] = array[8 + c_offset + i];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
c_offset += 4 + 4 + 4 + view.getUint32(c_offset);
|
|
138
|
+
if (c_offset > maxSearchOffset) // missing IEND
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
array = decompress(chunks.length === 1 ? chunks[0] : from_parts(chunks), height + height * row_length);
|
|
143
|
+
|
|
144
|
+
while (offset < array.byteLength) {
|
|
145
|
+
const filter = array[offset++];
|
|
146
|
+
const slice = array.subarray(offset, offset += row_length);
|
|
147
|
+
|
|
148
|
+
if (0 === filter) pixels.set(slice, p_offset);
|
|
149
|
+
else if (1 === filter) filter_1(slice, pixels, p_offset, bytespp, row_length);
|
|
150
|
+
else if (2 === filter) filter_2(slice, pixels, p_offset, bytespp, row_length);
|
|
151
|
+
else if (3 === filter) filter_3(slice, pixels, p_offset, bytespp, row_length);
|
|
152
|
+
else if (4 === filter) filter_4(slice, pixels, p_offset, bytespp, row_length);
|
|
153
|
+
|
|
154
|
+
p_offset += row_length;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (pixel_type === 3) {
|
|
158
|
+
if (!palette)
|
|
159
|
+
throw new Error('Indexed color PNG has no PLTE');
|
|
160
|
+
|
|
161
|
+
if (alphaPalette)
|
|
162
|
+
for (let i = 0; i < alphaPalette.length; i++)
|
|
163
|
+
palette[i] &= 0xffffff00 | alphaPalette[i];
|
|
164
|
+
|
|
165
|
+
channels = 4;
|
|
166
|
+
const newPixels = new Uint8Array(width * height * 4);
|
|
167
|
+
const pixelView = new DataView(newPixels.buffer, newPixels.byteOffset, newPixels.byteLength);
|
|
168
|
+
for (let i = 0; i < pixels.length; i++)
|
|
169
|
+
pixelView.setUint32(i * 4, palette[pixels[i]], false);
|
|
170
|
+
pixels = newPixels;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (bpc !== 8) {
|
|
174
|
+
const newPixels = new Uint8Array(pixels.length / bpc * 8);
|
|
175
|
+
for (let i = 0; i < pixels.length; i += 2)
|
|
176
|
+
newPixels[i / 2] = pixels[i];
|
|
177
|
+
pixels = newPixels;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (channels !== 4) {
|
|
181
|
+
const newPixels = new Uint8Array(width * height * 4);
|
|
182
|
+
const view = new DataView(newPixels.buffer);
|
|
183
|
+
|
|
184
|
+
if (channels === 1) {
|
|
185
|
+
for (let i = 0; i < width * height; i++) {
|
|
186
|
+
const pixel = pixels[i];
|
|
187
|
+
view.setUint32(i * 4, pixel << 24 | pixel << 16 | pixel << 8 | 0xff, false);
|
|
188
|
+
}
|
|
189
|
+
} else if (channels === 2) {
|
|
190
|
+
for (let i = 0; i < width * height * 2; i += 2) {
|
|
191
|
+
const pixel = pixels[i];
|
|
192
|
+
view.setUint32(i * 2, pixel << 24 | pixel << 16 | pixel << 8 | pixels[i + 1], false);
|
|
193
|
+
}
|
|
194
|
+
} else if (channels === 3) {
|
|
195
|
+
newPixels.fill(0xff);
|
|
196
|
+
for (let i = 0; i < width * height; i++)
|
|
197
|
+
newPixels.set(pixels.subarray(i * 3, i * 3 + 3), i * 4);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
pixels = newPixels;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { width, height, buffer: pixels };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function filter_1(slice, pixels, p_offset, bytespp, row_length) {
|
|
207
|
+
let i = 0;
|
|
208
|
+
while (i < bytespp) pixels[i + p_offset] = slice[i++];
|
|
209
|
+
while (i < row_length) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - bytespp];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function filter_2(slice, pixels, p_offset, bytespp, row_length) {
|
|
213
|
+
if (0 === p_offset) pixels.set(slice, p_offset);
|
|
214
|
+
else {
|
|
215
|
+
let i = 0;
|
|
216
|
+
while (i < row_length) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - row_length];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function filter_3(slice, pixels, p_offset, bytespp, row_length) {
|
|
221
|
+
let i = 0;
|
|
222
|
+
|
|
223
|
+
if (0 === p_offset) {
|
|
224
|
+
while (i < bytespp) pixels[i] = slice[i++];
|
|
225
|
+
while (i < row_length) pixels[i] = slice[i] + (pixels[i++ - bytespp] >> 1);
|
|
226
|
+
} else {
|
|
227
|
+
while (i < bytespp) pixels[i + p_offset] = slice[i] + (pixels[i++ + p_offset - row_length] >> 1);
|
|
228
|
+
while (i < row_length) pixels[i + p_offset] = slice[i] + (pixels[i + p_offset - bytespp] + pixels[i++ + p_offset - row_length] >> 1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function filter_4(slice, pixels, p_offset, bytespp, row_length) {
|
|
233
|
+
let i = 0;
|
|
234
|
+
|
|
235
|
+
if (0 === p_offset) {
|
|
236
|
+
while (i < bytespp) pixels[i] = slice[i++];
|
|
237
|
+
while (i < row_length) pixels[i] = slice[i] + pixels[i++ - bytespp];
|
|
238
|
+
} else {
|
|
239
|
+
while (i < bytespp) pixels[i + p_offset] = slice[i] + pixels[i++ + p_offset - row_length];
|
|
240
|
+
|
|
241
|
+
while (i < row_length) {
|
|
242
|
+
const a = pixels[i + p_offset - bytespp];
|
|
243
|
+
const b = pixels[i + p_offset - row_length];
|
|
244
|
+
const c = pixels[i + p_offset - bytespp - row_length];
|
|
245
|
+
|
|
246
|
+
const p = a + b - c;
|
|
247
|
+
const pa = Math.abs(p - a);
|
|
248
|
+
const pb = Math.abs(p - b);
|
|
249
|
+
const pc = Math.abs(p - c);
|
|
250
|
+
|
|
251
|
+
pixels[i + p_offset] = slice[i++] + ((pa <= pb && pa <= pc) ? a : ((pb <= pc) ? b : c));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|