roxify 1.2.3 → 1.2.5
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/dist/cli.js +90 -51
- package/dist/index.d.ts +11 -127
- package/dist/index.js +11 -2547
- package/dist/minpng.js +31 -24
- package/dist/pack.d.ts +11 -10
- package/dist/pack.js +104 -62
- package/dist/utils/constants.d.ts +38 -0
- package/dist/utils/constants.js +22 -0
- package/dist/utils/crc.d.ts +4 -0
- package/dist/utils/crc.js +29 -0
- package/dist/utils/decoder.d.ts +4 -0
- package/dist/utils/decoder.js +626 -0
- package/dist/utils/encoder.d.ts +4 -0
- package/dist/utils/encoder.js +305 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/errors.js +18 -0
- package/dist/utils/helpers.d.ts +11 -0
- package/dist/utils/helpers.js +76 -0
- package/dist/utils/inspection.d.ts +14 -0
- package/dist/utils/inspection.js +388 -0
- package/dist/utils/optimization.d.ts +3 -0
- package/dist/utils/optimization.js +636 -0
- package/dist/utils/reconstitution.d.ts +3 -0
- package/dist/utils/reconstitution.js +266 -0
- package/dist/utils/types.d.ts +41 -0
- package/dist/utils/types.js +1 -0
- package/dist/utils/zstd.d.ts +17 -0
- package/dist/utils/zstd.js +118 -0
- package/package.json +1 -1
package/dist/minpng.js
CHANGED
|
@@ -19,26 +19,30 @@ function paeth(a, b, c) {
|
|
|
19
19
|
return b;
|
|
20
20
|
return c;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
const
|
|
22
|
+
function zigzagOrderIndices(width, height) {
|
|
23
|
+
const len = width * height;
|
|
24
|
+
const indices = new Int32Array(len);
|
|
25
|
+
let i = 0;
|
|
24
26
|
for (let y = 0; y < height; y++) {
|
|
25
27
|
if (y % 2 === 0) {
|
|
26
|
-
for (let x = 0; x < width; x++)
|
|
27
|
-
|
|
28
|
+
for (let x = 0; x < width; x++) {
|
|
29
|
+
indices[i++] = y * width + x;
|
|
30
|
+
}
|
|
28
31
|
}
|
|
29
32
|
else {
|
|
30
|
-
for (let x = width - 1; x >= 0; x--)
|
|
31
|
-
|
|
33
|
+
for (let x = width - 1; x >= 0; x--) {
|
|
34
|
+
indices[i++] = y * width + x;
|
|
35
|
+
}
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
|
-
return
|
|
38
|
+
return indices;
|
|
35
39
|
}
|
|
36
40
|
export async function encodeMinPng(rgb, width, height) {
|
|
37
41
|
const w = width, h = height;
|
|
38
42
|
const idx = (x, y) => (y * w + x) * 3;
|
|
39
|
-
const residualR =
|
|
40
|
-
const residualG =
|
|
41
|
-
const residualB =
|
|
43
|
+
const residualR = new Uint8Array(w * h);
|
|
44
|
+
const residualG = new Uint8Array(w * h);
|
|
45
|
+
const residualB = new Uint8Array(w * h);
|
|
42
46
|
for (let y = 0; y < h; y++) {
|
|
43
47
|
for (let x = 0; x < w; x++) {
|
|
44
48
|
const i = idx(x, y);
|
|
@@ -65,17 +69,20 @@ export async function encodeMinPng(rgb, width, height) {
|
|
|
65
69
|
residualB[y * w + x] = (b - predB + 256) & 0xff;
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
|
-
const
|
|
69
|
-
const transformed =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
const indices = zigzagOrderIndices(w, h);
|
|
73
|
+
const transformed = new Uint8Array(w * h * 3);
|
|
74
|
+
let tIdx = 0;
|
|
75
|
+
for (let i = 0; i < indices.length; i++) {
|
|
76
|
+
const pos = indices[i];
|
|
72
77
|
const g = residualG[pos];
|
|
73
78
|
const r = (residualR[pos] - g + 256) & 0xff;
|
|
74
79
|
const b = (residualB[pos] - g + 256) & 0xff;
|
|
75
|
-
transformed
|
|
80
|
+
transformed[tIdx++] = g;
|
|
81
|
+
transformed[tIdx++] = r;
|
|
82
|
+
transformed[tIdx++] = b;
|
|
76
83
|
}
|
|
77
84
|
const transformedBuf = Buffer.from(transformed);
|
|
78
|
-
const compressed = Buffer.from(await zstdCompress(transformedBuf,
|
|
85
|
+
const compressed = Buffer.from(await zstdCompress(transformedBuf, 19));
|
|
79
86
|
const header = Buffer.alloc(4 + 1 + 4 + 4);
|
|
80
87
|
PIXEL_MAGIC.copy(header, 0);
|
|
81
88
|
header[4] = 1;
|
|
@@ -174,7 +181,7 @@ export async function decodeMinPng(pngBuf) {
|
|
|
174
181
|
const headerStart = startIdxBytes;
|
|
175
182
|
if (headerStart + 13 > rawRGB.length)
|
|
176
183
|
return null;
|
|
177
|
-
if (!rawRGB.
|
|
184
|
+
if (!rawRGB.subarray(headerStart, headerStart + 4).equals(PIXEL_MAGIC))
|
|
178
185
|
return null;
|
|
179
186
|
const origW = rawRGB.readUInt32BE(headerStart + 5);
|
|
180
187
|
const origH = rawRGB.readUInt32BE(headerStart + 9);
|
|
@@ -182,20 +189,20 @@ export async function decodeMinPng(pngBuf) {
|
|
|
182
189
|
const compStart = headerStart + 17;
|
|
183
190
|
if (compStart + compressedLen > rawRGB.length)
|
|
184
191
|
return null;
|
|
185
|
-
const compressed = rawRGB.
|
|
192
|
+
const compressed = rawRGB.subarray(compStart, compStart + compressedLen);
|
|
186
193
|
const decompressed = Buffer.from(await zstdDecompress(compressed));
|
|
187
|
-
const
|
|
188
|
-
const residualR =
|
|
189
|
-
const residualG =
|
|
190
|
-
const residualB =
|
|
194
|
+
const indices = zigzagOrderIndices(origW, origH);
|
|
195
|
+
const residualR = new Uint8Array(origW * origH);
|
|
196
|
+
const residualG = new Uint8Array(origW * origH);
|
|
197
|
+
const residualB = new Uint8Array(origW * origH);
|
|
191
198
|
let p = 0;
|
|
192
|
-
for (
|
|
199
|
+
for (let i = 0; i < indices.length; i++) {
|
|
193
200
|
if (p + 3 > decompressed.length)
|
|
194
201
|
break;
|
|
195
202
|
const g = decompressed[p++];
|
|
196
203
|
const rminusg = decompressed[p++];
|
|
197
204
|
const bminusg = decompressed[p++];
|
|
198
|
-
const pos =
|
|
205
|
+
const pos = indices[i];
|
|
199
206
|
residualG[pos] = g;
|
|
200
207
|
residualR[pos] = (rminusg + g) & 0xff;
|
|
201
208
|
residualB[pos] = (bminusg + g) & 0xff;
|
package/dist/pack.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export interface PackedFile {
|
|
|
4
4
|
path: string;
|
|
5
5
|
buf: Buffer;
|
|
6
6
|
}
|
|
7
|
+
export interface VFSIndexEntry {
|
|
8
|
+
path: string;
|
|
9
|
+
blockId: number;
|
|
10
|
+
offset: number;
|
|
11
|
+
size: number;
|
|
12
|
+
}
|
|
7
13
|
export declare function packPaths(paths: string[], baseDir?: string, onProgress?: (readBytes: number, totalBytes: number, currentFile?: string) => void): {
|
|
8
14
|
buf: Buffer;
|
|
9
15
|
list: string[];
|
|
@@ -14,13 +20,8 @@ export declare function unpackBuffer(buf: Buffer, fileList?: string[]): {
|
|
|
14
20
|
buf: Buffer;
|
|
15
21
|
}[];
|
|
16
22
|
} | null;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
files: {
|
|
23
|
-
path: string;
|
|
24
|
-
size: number;
|
|
25
|
-
}[];
|
|
26
|
-
};
|
|
23
|
+
export declare function packPathsGenerator(paths: string[], baseDir?: string, onProgress?: (readBytes: number, totalBytes: number, currentFile?: string) => void): Promise<{
|
|
24
|
+
index: VFSIndexEntry[];
|
|
25
|
+
stream: AsyncGenerator<Buffer>;
|
|
26
|
+
totalSize: number;
|
|
27
|
+
}>;
|
package/dist/pack.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
function
|
|
4
|
-
const files = [];
|
|
1
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
2
|
+
import { extname, join, relative, resolve, sep } from 'path';
|
|
3
|
+
function* collectFilesGenerator(paths) {
|
|
5
4
|
for (const p of paths) {
|
|
6
5
|
const abs = resolve(p);
|
|
7
6
|
const st = statSync(abs);
|
|
8
7
|
if (st.isFile()) {
|
|
9
|
-
|
|
8
|
+
yield abs;
|
|
10
9
|
}
|
|
11
10
|
else if (st.isDirectory()) {
|
|
12
11
|
const names = readdirSync(abs);
|
|
13
12
|
const childPaths = names.map((n) => join(abs, n));
|
|
14
|
-
|
|
13
|
+
yield* collectFilesGenerator(childPaths);
|
|
15
14
|
}
|
|
16
15
|
}
|
|
17
|
-
return files;
|
|
18
16
|
}
|
|
19
17
|
export function packPaths(paths, baseDir, onProgress) {
|
|
20
|
-
const files =
|
|
18
|
+
const files = [];
|
|
19
|
+
for (const f of collectFilesGenerator(paths)) {
|
|
20
|
+
files.push(f);
|
|
21
|
+
}
|
|
21
22
|
const base = baseDir ? resolve(baseDir) : process.cwd();
|
|
22
23
|
const parts = [];
|
|
23
24
|
const list = [];
|
|
@@ -52,9 +53,35 @@ export function packPaths(paths, baseDir, onProgress) {
|
|
|
52
53
|
export function unpackBuffer(buf, fileList) {
|
|
53
54
|
if (buf.length < 8)
|
|
54
55
|
return null;
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
56
|
+
const magic = buf.readUInt32BE(0);
|
|
57
|
+
if (magic === 0x524f5849) {
|
|
58
|
+
const indexLen = buf.readUInt32BE(4);
|
|
59
|
+
const indexBuf = buf.slice(8, 8 + indexLen);
|
|
60
|
+
const index = JSON.parse(indexBuf.toString('utf8'));
|
|
61
|
+
const dataStart = 8 + indexLen;
|
|
62
|
+
const files = [];
|
|
63
|
+
const entriesToProcess = fileList
|
|
64
|
+
? index.filter((e) => fileList.includes(e.path))
|
|
65
|
+
: index;
|
|
66
|
+
for (const entry of entriesToProcess) {
|
|
67
|
+
const entryStart = dataStart + entry.offset;
|
|
68
|
+
let ptr = entryStart;
|
|
69
|
+
if (ptr + 2 > buf.length)
|
|
70
|
+
continue;
|
|
71
|
+
const nameLen = buf.readUInt16BE(ptr);
|
|
72
|
+
ptr += 2;
|
|
73
|
+
ptr += nameLen;
|
|
74
|
+
ptr += 8;
|
|
75
|
+
if (ptr + entry.size > buf.length)
|
|
76
|
+
continue;
|
|
77
|
+
const content = buf.slice(ptr, ptr + entry.size);
|
|
78
|
+
files.push({ path: entry.path, buf: content });
|
|
79
|
+
}
|
|
80
|
+
return { files };
|
|
81
|
+
}
|
|
82
|
+
if (magic !== 0x524f5850)
|
|
57
83
|
return null;
|
|
84
|
+
const header = buf.slice(0, 8);
|
|
58
85
|
const fileCount = header.readUInt32BE(4);
|
|
59
86
|
let offset = 8;
|
|
60
87
|
const files = [];
|
|
@@ -83,60 +110,75 @@ export function unpackBuffer(buf, fileList) {
|
|
|
83
110
|
}
|
|
84
111
|
return { files };
|
|
85
112
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
export async function packPathsGenerator(paths, baseDir, onProgress) {
|
|
114
|
+
const files = [];
|
|
115
|
+
for (const f of collectFilesGenerator(paths)) {
|
|
116
|
+
files.push(f);
|
|
117
|
+
}
|
|
118
|
+
files.sort((a, b) => {
|
|
119
|
+
const extA = extname(a);
|
|
120
|
+
const extB = extname(b);
|
|
121
|
+
if (extA !== extB)
|
|
122
|
+
return extA.localeCompare(extB);
|
|
123
|
+
return a.localeCompare(b);
|
|
124
|
+
});
|
|
125
|
+
const base = baseDir ? resolve(baseDir) : process.cwd();
|
|
126
|
+
const BLOCK_SIZE = 8 * 1024 * 1024;
|
|
127
|
+
const index = [];
|
|
128
|
+
let currentBlockId = 0;
|
|
129
|
+
let currentBlockSize = 0;
|
|
130
|
+
let globalDataOffset = 0;
|
|
131
|
+
let totalSize = 0;
|
|
132
|
+
for (const f of files) {
|
|
133
|
+
const st = statSync(f);
|
|
134
|
+
const rel = relative(base, f).split(sep).join('/');
|
|
135
|
+
const nameBuf = Buffer.from(rel, 'utf8');
|
|
136
|
+
const entrySize = 2 + nameBuf.length + 8 + st.size;
|
|
137
|
+
if (currentBlockSize + entrySize > BLOCK_SIZE && currentBlockSize > 0) {
|
|
138
|
+
currentBlockId++;
|
|
139
|
+
currentBlockSize = 0;
|
|
140
|
+
}
|
|
141
|
+
index.push({
|
|
142
|
+
path: rel,
|
|
143
|
+
blockId: currentBlockId,
|
|
144
|
+
offset: globalDataOffset,
|
|
145
|
+
size: st.size,
|
|
146
|
+
});
|
|
147
|
+
currentBlockSize += entrySize;
|
|
148
|
+
globalDataOffset += entrySize;
|
|
149
|
+
totalSize += st.size;
|
|
150
|
+
}
|
|
151
|
+
async function* streamGenerator() {
|
|
152
|
+
const indexBuf = Buffer.from(JSON.stringify(index), 'utf8');
|
|
153
|
+
const indexHeader = Buffer.alloc(8);
|
|
154
|
+
indexHeader.writeUInt32BE(0x524f5849, 0);
|
|
155
|
+
indexHeader.writeUInt32BE(indexBuf.length, 4);
|
|
156
|
+
yield Buffer.concat([indexHeader, indexBuf]);
|
|
157
|
+
let currentBuffer = Buffer.alloc(0);
|
|
158
|
+
let readSoFar = 0;
|
|
159
|
+
for (let i = 0; i < files.length; i++) {
|
|
160
|
+
const f = files[i];
|
|
161
|
+
const rel = relative(base, f).split(sep).join('/');
|
|
162
|
+
const content = readFileSync(f);
|
|
163
|
+
const nameBuf = Buffer.from(rel, 'utf8');
|
|
164
|
+
const nameLen = Buffer.alloc(2);
|
|
165
|
+
nameLen.writeUInt16BE(nameBuf.length, 0);
|
|
111
166
|
const sizeBuf = Buffer.alloc(8);
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
const outPath = join(baseDir, name);
|
|
120
|
-
const outDir = dirname(outPath);
|
|
121
|
-
mkdirSync(outDir, { recursive: true });
|
|
122
|
-
const ws = createWriteStream(outPath);
|
|
123
|
-
let remaining = size;
|
|
124
|
-
const chunk = Buffer.alloc(64 * 1024);
|
|
125
|
-
while (remaining > 0) {
|
|
126
|
-
const toRead = Math.min(remaining, chunk.length);
|
|
127
|
-
const bytesRead = readSync(fd, chunk, 0, toRead, offset);
|
|
128
|
-
if (bytesRead <= 0)
|
|
129
|
-
break;
|
|
130
|
-
ws.write(chunk.slice(0, bytesRead));
|
|
131
|
-
offset += bytesRead;
|
|
132
|
-
remaining -= bytesRead;
|
|
167
|
+
sizeBuf.writeBigUInt64BE(BigInt(content.length), 0);
|
|
168
|
+
const entry = Buffer.concat([nameLen, nameBuf, sizeBuf, content]);
|
|
169
|
+
if (currentBuffer.length + entry.length > BLOCK_SIZE &&
|
|
170
|
+
currentBuffer.length > 0) {
|
|
171
|
+
yield currentBuffer;
|
|
172
|
+
currentBuffer = Buffer.alloc(0);
|
|
133
173
|
}
|
|
134
|
-
|
|
135
|
-
|
|
174
|
+
currentBuffer = Buffer.concat([currentBuffer, entry]);
|
|
175
|
+
readSoFar += content.length;
|
|
176
|
+
if (onProgress)
|
|
177
|
+
onProgress(readSoFar, totalSize, rel);
|
|
178
|
+
}
|
|
179
|
+
if (currentBuffer.length > 0) {
|
|
180
|
+
yield currentBuffer;
|
|
136
181
|
}
|
|
137
|
-
return { files };
|
|
138
|
-
}
|
|
139
|
-
finally {
|
|
140
|
-
closeSync(fd);
|
|
141
182
|
}
|
|
183
|
+
return { index, stream: streamGenerator(), totalSize };
|
|
142
184
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
export declare const CHUNK_TYPE = "rXDT";
|
|
4
|
+
export declare const MAGIC: Buffer;
|
|
5
|
+
export declare const PIXEL_MAGIC: Buffer;
|
|
6
|
+
export declare const ENC_NONE = 0;
|
|
7
|
+
export declare const ENC_AES = 1;
|
|
8
|
+
export declare const ENC_XOR = 2;
|
|
9
|
+
export declare const FILTER_ZERO: Buffer;
|
|
10
|
+
export declare const PNG_HEADER: Buffer;
|
|
11
|
+
export declare const PNG_HEADER_HEX: string;
|
|
12
|
+
export declare const MARKER_COLORS: {
|
|
13
|
+
r: number;
|
|
14
|
+
g: number;
|
|
15
|
+
b: number;
|
|
16
|
+
}[];
|
|
17
|
+
export declare const MARKER_START: {
|
|
18
|
+
r: number;
|
|
19
|
+
g: number;
|
|
20
|
+
b: number;
|
|
21
|
+
}[];
|
|
22
|
+
export declare const MARKER_END: {
|
|
23
|
+
r: number;
|
|
24
|
+
g: number;
|
|
25
|
+
b: number;
|
|
26
|
+
}[];
|
|
27
|
+
export declare const COMPRESSION_MARKERS: {
|
|
28
|
+
zstd: {
|
|
29
|
+
r: number;
|
|
30
|
+
g: number;
|
|
31
|
+
b: number;
|
|
32
|
+
}[];
|
|
33
|
+
lzma: {
|
|
34
|
+
r: number;
|
|
35
|
+
g: number;
|
|
36
|
+
b: number;
|
|
37
|
+
}[];
|
|
38
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const CHUNK_TYPE = 'rXDT';
|
|
2
|
+
export const MAGIC = Buffer.from('ROX1');
|
|
3
|
+
export const PIXEL_MAGIC = Buffer.from('PXL1');
|
|
4
|
+
export const ENC_NONE = 0;
|
|
5
|
+
export const ENC_AES = 1;
|
|
6
|
+
export const ENC_XOR = 2;
|
|
7
|
+
export const FILTER_ZERO = Buffer.from([0]);
|
|
8
|
+
export const PNG_HEADER = Buffer.from([
|
|
9
|
+
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
|
|
10
|
+
]);
|
|
11
|
+
export const PNG_HEADER_HEX = PNG_HEADER.toString('hex');
|
|
12
|
+
export const MARKER_COLORS = [
|
|
13
|
+
{ r: 255, g: 0, b: 0 },
|
|
14
|
+
{ r: 0, g: 255, b: 0 },
|
|
15
|
+
{ r: 0, g: 0, b: 255 },
|
|
16
|
+
];
|
|
17
|
+
export const MARKER_START = MARKER_COLORS;
|
|
18
|
+
export const MARKER_END = [...MARKER_COLORS].reverse();
|
|
19
|
+
export const COMPRESSION_MARKERS = {
|
|
20
|
+
zstd: [{ r: 0, g: 255, b: 0 }],
|
|
21
|
+
lzma: [{ r: 255, g: 255, b: 0 }],
|
|
22
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const CRC_TABLE = [];
|
|
2
|
+
for (let n = 0; n < 256; n++) {
|
|
3
|
+
let c = n;
|
|
4
|
+
for (let k = 0; k < 8; k++) {
|
|
5
|
+
if (c & 1) {
|
|
6
|
+
c = 0xedb88320 ^ (c >>> 1);
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
c = c >>> 1;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
CRC_TABLE[n] = c;
|
|
13
|
+
}
|
|
14
|
+
export function crc32(buf, previous = 0) {
|
|
15
|
+
let crc = previous ^ 0xffffffff;
|
|
16
|
+
for (let i = 0; i < buf.length; i++) {
|
|
17
|
+
crc = CRC_TABLE[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
|
18
|
+
}
|
|
19
|
+
return crc ^ 0xffffffff;
|
|
20
|
+
}
|
|
21
|
+
export function adler32(buf, prev = 1) {
|
|
22
|
+
let s1 = prev & 0xffff;
|
|
23
|
+
let s2 = (prev >>> 16) & 0xffff;
|
|
24
|
+
for (let i = 0; i < buf.length; i++) {
|
|
25
|
+
s1 = (s1 + buf[i]) % 65521;
|
|
26
|
+
s2 = (s2 + s1) % 65521;
|
|
27
|
+
}
|
|
28
|
+
return ((s2 << 16) | s1) >>> 0;
|
|
29
|
+
}
|