Replace png encode dependency with optimized CRC32 calculation

ba397fa70a2f0d7cb7533f410172b19f8b513a34

Cohee <18619528+Cohee1207@users.noreply.github.com>

4 files changed, +88 -28Ignore whitespace
package-lock.json+18 -25
@@ -48,6 +48,7 @@
48 "cookie-parser": "^1.4.6",48 "cookie-parser": "^1.4.6",
49 "cookie-session": "^2.1.0",49 "cookie-session": "^2.1.0",
50 "cors": "^2.8.5",50 "cors": "^2.8.5",
51 "crc": "^4.3.2",
51 "csrf-sync": "^4.0.3",52 "csrf-sync": "^4.0.3",
52 "diff-match-patch": "^1.0.5",53 "diff-match-patch": "^1.0.5",
53 "dompurify": "^3.2.4",54 "dompurify": "^3.2.4",
@@ -76,7 +77,6 @@
76 "node-persist": "^4.0.4",77 "node-persist": "^4.0.4",
77 "open": "^8.4.2",78 "open": "^8.4.2",
78 "png-chunk-text": "^1.0.0",79 "png-chunk-text": "^1.0.0",
79 "png-chunks-encode": "^1.0.0",
80 "png-chunks-extract": "^1.0.0",80 "png-chunks-extract": "^1.0.0",
81 "proxy-agent": "^6.5.0",81 "proxy-agent": "^6.5.0",
82 "rate-limiter-flexible": "^5.0.5",82 "rate-limiter-flexible": "^5.0.5",
@@ -121,7 +121,6 @@
121 "@types/node": "^18.19.80",121 "@types/node": "^18.19.80",
122 "@types/node-persist": "^3.1.8",122 "@types/node-persist": "^3.1.8",
123 "@types/png-chunk-text": "^1.0.3",123 "@types/png-chunk-text": "^1.0.3",
124 "@types/png-chunks-encode": "^1.0.2",
125 "@types/png-chunks-extract": "^1.0.2",124 "@types/png-chunks-extract": "^1.0.2",
126 "@types/response-time": "^2.3.8",125 "@types/response-time": "^2.3.8",
127 "@types/select2": "^4.0.63",126 "@types/select2": "^4.0.63",
@@ -2033,13 +2032,6 @@
2033 "dev": true,2032 "dev": true,
2034 "license": "MIT"2033 "license": "MIT"
2035 },2034 },
2036 "node_modules/@types/png-chunks-encode": {
2037 "version": "1.0.2",
2038 "resolved": "https://registry.npmjs.org/@types/png-chunks-encode/-/png-chunks-encode-1.0.2.tgz",
2039 "integrity": "sha512-Dxn0aXEcSg1wVeHjvNlygm/+fKBDzWMCdxJYhjGUTeefFW/jYxWcrg+W7ppLBfH44iJMqeVBHtHBwtYQUeYvgw==",
2040 "dev": true,
2041 "license": "MIT"
2042 },
2043 "node_modules/@types/png-chunks-extract": {2035 "node_modules/@types/png-chunks-extract": {
2044 "version": "1.0.2",2036 "version": "1.0.2",
2045 "resolved": "https://registry.npmjs.org/@types/png-chunks-extract/-/png-chunks-extract-1.0.2.tgz",2037 "resolved": "https://registry.npmjs.org/@types/png-chunks-extract/-/png-chunks-extract-1.0.2.tgz",
@@ -3542,6 +3534,23 @@
3542 "node": ">= 0.10"3534 "node": ">= 0.10"
3543 }3535 }
3544 },3536 },
3537 "node_modules/crc": {
3538 "version": "4.3.2",
3539 "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz",
3540 "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==",
3541 "license": "MIT",
3542 "engines": {
3543 "node": ">=12"
3544 },
3545 "peerDependencies": {
3546 "buffer": ">=6.0.3"
3547 },
3548 "peerDependenciesMeta": {
3549 "buffer": {
3550 "optional": true
3551 }
3552 }
3553 },
3545 "node_modules/crc-32": {3554 "node_modules/crc-32": {
3546 "version": "0.3.0",3555 "version": "0.3.0",
3547 "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-0.3.0.tgz",3556 "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-0.3.0.tgz",
@@ -6686,16 +6695,6 @@
6686 "integrity": "sha512-DEROKU3SkkLGWNMzru3xPVgxyd48UGuMSZvioErCure6yhOc/pRH2ZV+SEn7nmaf7WNf3NdIpH+UTrRdKyq9Lw==",6695 "integrity": "sha512-DEROKU3SkkLGWNMzru3xPVgxyd48UGuMSZvioErCure6yhOc/pRH2ZV+SEn7nmaf7WNf3NdIpH+UTrRdKyq9Lw==",
6687 "license": "MIT"6696 "license": "MIT"
6688 },6697 },
6689 "node_modules/png-chunks-encode": {
6690 "version": "1.0.0",
6691 "resolved": "https://registry.npmjs.org/png-chunks-encode/-/png-chunks-encode-1.0.0.tgz",
6692 "integrity": "sha512-J1jcHgbQRsIIgx5wxW9UmCymV3wwn4qCCJl6KYgEU/yHCh/L2Mwq/nMOkRPtmV79TLxRZj5w3tH69pvygFkDqA==",
6693 "license": "MIT",
6694 "dependencies": {
6695 "crc-32": "^0.3.0",
6696 "sliced": "^1.0.1"
6697 }
6698 },
6699 "node_modules/png-chunks-extract": {6698 "node_modules/png-chunks-extract": {
6700 "version": "1.0.0",6699 "version": "1.0.0",
6701 "resolved": "https://registry.npmjs.org/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz",6700 "resolved": "https://registry.npmjs.org/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz",
@@ -7532,12 +7531,6 @@
7532 "dev": true,7531 "dev": true,
7533 "license": "ISC"7532 "license": "ISC"
7534 },7533 },
7535 "node_modules/sliced": {
7536 "version": "1.0.1",
7537 "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
7538 "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==",
7539 "license": "MIT"
7540 },
7541 "node_modules/slidetoggle": {7534 "node_modules/slidetoggle": {
7542 "version": "4.0.0",7535 "version": "4.0.0",
7543 "resolved": "https://registry.npmjs.org/slidetoggle/-/slidetoggle-4.0.0.tgz",7536 "resolved": "https://registry.npmjs.org/slidetoggle/-/slidetoggle-4.0.0.tgz",
package.json+1 -2
@@ -38,6 +38,7 @@
38 "cookie-parser": "^1.4.6",38 "cookie-parser": "^1.4.6",
39 "cookie-session": "^2.1.0",39 "cookie-session": "^2.1.0",
40 "cors": "^2.8.5",40 "cors": "^2.8.5",
41 "crc": "^4.3.2",
41 "csrf-sync": "^4.0.3",42 "csrf-sync": "^4.0.3",
42 "diff-match-patch": "^1.0.5",43 "diff-match-patch": "^1.0.5",
43 "dompurify": "^3.2.4",44 "dompurify": "^3.2.4",
@@ -66,7 +67,6 @@
66 "node-persist": "^4.0.4",67 "node-persist": "^4.0.4",
67 "open": "^8.4.2",68 "open": "^8.4.2",
68 "png-chunk-text": "^1.0.0",69 "png-chunk-text": "^1.0.0",
69 "png-chunks-encode": "^1.0.0",
70 "png-chunks-extract": "^1.0.0",70 "png-chunks-extract": "^1.0.0",
71 "proxy-agent": "^6.5.0",71 "proxy-agent": "^6.5.0",
72 "rate-limiter-flexible": "^5.0.5",72 "rate-limiter-flexible": "^5.0.5",
@@ -151,7 +151,6 @@
151 "@types/node": "^18.19.80",151 "@types/node": "^18.19.80",
152 "@types/node-persist": "^3.1.8",152 "@types/node-persist": "^3.1.8",
153 "@types/png-chunk-text": "^1.0.3",153 "@types/png-chunk-text": "^1.0.3",
154 "@types/png-chunks-encode": "^1.0.2",
155 "@types/png-chunks-extract": "^1.0.2",154 "@types/png-chunks-extract": "^1.0.2",
156 "@types/response-time": "^2.3.8",155 "@types/response-time": "^2.3.8",
157 "@types/select2": "^4.0.63",156 "@types/select2": "^4.0.63",
src/character-card-parser.js+1 -1
@@ -1,7 +1,7 @@
1import fs from 'node:fs';1import fs from 'node:fs';
2import { Buffer } from 'node:buffer';2import { Buffer } from 'node:buffer';
33
4import encode from 'png-chunks-encode';4import encode from './png/encode.js';
5import extract from 'png-chunks-extract';5import extract from 'png-chunks-extract';
6import PNGtext from 'png-chunk-text';6import PNGtext from 'png-chunk-text';
77
src/png/encode.js+68 -0
@@ -0,0 +1,68 @@
1import { crc32 } from 'crc';
2
3/**
4 * Encodes PNG chunks into a PNG file format buffer.
5 * @param {Array<{ name: string; data: Uint8Array }>} chunks Array of PNG chunks
6 * @returns {Uint8Array} Encoded PNG data
7 * @copyright Based on https://github.com/hughsk/png-chunks-encode (MIT)
8 */
9export default function encode(chunks) {
10 const uint8 = new Uint8Array(4);
11 const int32 = new Int32Array(uint8.buffer);
12 const uint32 = new Uint32Array(uint8.buffer);
13
14 let totalSize = 8;
15 let idx = totalSize;
16
17 for (let i = 0; i < chunks.length; i++) {
18 totalSize += chunks[i].data.length;
19 totalSize += 12;
20 }
21
22 const output = new Uint8Array(totalSize);
23
24 output[0] = 0x89;
25 output[1] = 0x50;
26 output[2] = 0x4E;
27 output[3] = 0x47;
28 output[4] = 0x0D;
29 output[5] = 0x0A;
30 output[6] = 0x1A;
31 output[7] = 0x0A;
32
33 for (let i = 0; i < chunks.length; i++) {
34 const { name, data } = chunks[i];
35 const size = data.length;
36 const nameChars = [
37 name.charCodeAt(0),
38 name.charCodeAt(1),
39 name.charCodeAt(2),
40 name.charCodeAt(3),
41 ];
42
43 uint32[0] = size;
44 output[idx++] = uint8[3];
45 output[idx++] = uint8[2];
46 output[idx++] = uint8[1];
47 output[idx++] = uint8[0];
48
49 output[idx++] = nameChars[0];
50 output[idx++] = nameChars[1];
51 output[idx++] = nameChars[2];
52 output[idx++] = nameChars[3];
53
54 for (let j = 0; j < size;) {
55 output[idx++] = data[j++];
56 }
57
58 const crc = crc32(data, crc32(new Uint8Array(nameChars)));
59
60 int32[0] = crc;
61 output[idx++] = uint8[3];
62 output[idx++] = uint8[2];
63 output[idx++] = uint8[1];
64 output[idx++] = uint8[0];
65 }
66
67 return output;
68}