roxify 1.4.1 → 1.5.0

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.
@@ -1,10 +1,9 @@
1
- import extract from 'png-chunks-extract';
2
- import sharp from 'sharp';
3
1
  import * as zlib from 'zlib';
4
2
  import { unpackBuffer } from '../pack.js';
5
3
  import { CHUNK_TYPE, ENC_AES, ENC_XOR, MAGIC, MARKER_COLORS, PIXEL_MAGIC, } from './constants.js';
6
4
  import { decodePngToBinary } from './decoder.js';
7
5
  import { PassphraseRequiredError } from './errors.js';
6
+ import { native } from './native.js';
8
7
  import { cropAndReconstitute } from './reconstitution.js';
9
8
  /**
10
9
  * List files in a Rox PNG archive without decoding the full payload.
@@ -14,7 +13,7 @@ import { cropAndReconstitute } from './reconstitution.js';
14
13
  */
15
14
  export async function listFilesInPng(pngBuf, opts = {}) {
16
15
  try {
17
- const chunks = extract(pngBuf);
16
+ const chunks = native.extractPngChunks(pngBuf);
18
17
  const ihdr = chunks.find((c) => c.name === 'IHDR');
19
18
  const idatChunks = chunks.filter((c) => c.name === 'IDAT');
20
19
  if (ihdr && idatChunks.length > 0) {
@@ -147,15 +146,13 @@ export async function listFilesInPng(pngBuf, opts = {}) {
147
146
  }
148
147
  try {
149
148
  try {
150
- const { data, info } = await sharp(pngBuf)
151
- .ensureAlpha()
152
- .raw()
153
- .toBuffer({ resolveWithObject: true });
154
- const currentWidth = info.width;
155
- const currentHeight = info.height;
149
+ const rawData = native.sharpToRaw(pngBuf);
150
+ const data = rawData.pixels;
151
+ const currentWidth = rawData.width;
152
+ const currentHeight = rawData.height;
156
153
  const rawRGB = Buffer.alloc(currentWidth * currentHeight * 3);
157
154
  for (let i = 0; i < currentWidth * currentHeight; i++) {
158
- rawRGB[i * 3] = data[i * 4];
155
+ rawRGB[i * 3] = data[i * 3];
159
156
  rawRGB[i * 3 + 1] = data[i * 4 + 1];
160
157
  rawRGB[i * 3 + 2] = data[i * 4 + 2];
161
158
  }
@@ -219,17 +216,15 @@ export async function listFilesInPng(pngBuf, opts = {}) {
219
216
  try {
220
217
  const reconstructed = await cropAndReconstitute(pngBuf);
221
218
  try {
222
- const { data, info } = await sharp(reconstructed)
223
- .ensureAlpha()
224
- .raw()
225
- .toBuffer({ resolveWithObject: true });
226
- const currentWidth = info.width;
227
- const currentHeight = info.height;
219
+ const rawData = native.sharpToRaw(reconstructed);
220
+ const data = rawData.pixels;
221
+ const currentWidth = rawData.width;
222
+ const currentHeight = rawData.height;
228
223
  const rawRGB = Buffer.alloc(currentWidth * currentHeight * 3);
229
224
  for (let i = 0; i < currentWidth * currentHeight; i++) {
230
- rawRGB[i * 3] = data[i * 4];
231
- rawRGB[i * 3 + 1] = data[i * 4 + 1];
232
- rawRGB[i * 3 + 2] = data[i * 4 + 2];
225
+ rawRGB[i * 3] = data[i * 3];
226
+ rawRGB[i * 3 + 1] = data[i * 3 + 1];
227
+ rawRGB[i * 3 + 2] = data[i * 3 + 2];
233
228
  }
234
229
  const found = rawRGB.indexOf(PIXEL_MAGIC);
235
230
  if (found !== -1) {
@@ -287,12 +282,10 @@ export async function listFilesInPng(pngBuf, opts = {}) {
287
282
  }
288
283
  catch (e) { }
289
284
  try {
290
- const chunks = extract(reconstructed);
285
+ const chunks = native.extractPngChunks(reconstructed);
291
286
  const fileListChunk = chunks.find((c) => c.name === 'rXFL');
292
287
  if (fileListChunk) {
293
- const data = Buffer.isBuffer(fileListChunk.data)
294
- ? fileListChunk.data
295
- : Buffer.from(fileListChunk.data);
288
+ const data = Buffer.from(fileListChunk.data);
296
289
  const parsedFiles = JSON.parse(data.toString('utf8'));
297
290
  if (parsedFiles.length > 0 &&
298
291
  typeof parsedFiles[0] === 'object' &&
@@ -316,9 +309,7 @@ export async function listFilesInPng(pngBuf, opts = {}) {
316
309
  }
317
310
  const metaChunk = chunks.find((c) => c.name === CHUNK_TYPE);
318
311
  if (metaChunk) {
319
- const dataBuf = Buffer.isBuffer(metaChunk.data)
320
- ? metaChunk.data
321
- : Buffer.from(metaChunk.data);
312
+ const dataBuf = Buffer.from(metaChunk.data);
322
313
  const markerIdx = dataBuf.indexOf(Buffer.from('rXFL'));
323
314
  if (markerIdx !== -1 && markerIdx + 8 <= dataBuf.length) {
324
315
  const jsonLen = dataBuf.readUInt32BE(markerIdx + 4);
@@ -345,12 +336,10 @@ export async function listFilesInPng(pngBuf, opts = {}) {
345
336
  }
346
337
  catch (e) { }
347
338
  try {
348
- const chunks = extract(pngBuf);
339
+ const chunks = native.extractPngChunks(pngBuf);
349
340
  const fileListChunk = chunks.find((c) => c.name === 'rXFL');
350
341
  if (fileListChunk) {
351
- const data = Buffer.isBuffer(fileListChunk.data)
352
- ? fileListChunk.data
353
- : Buffer.from(fileListChunk.data);
342
+ const data = Buffer.from(fileListChunk.data);
354
343
  const parsedFiles = JSON.parse(data.toString('utf8'));
355
344
  if (parsedFiles.length > 0 &&
356
345
  typeof parsedFiles[0] === 'object' &&
@@ -374,9 +363,7 @@ export async function listFilesInPng(pngBuf, opts = {}) {
374
363
  }
375
364
  const metaChunk = chunks.find((c) => c.name === CHUNK_TYPE);
376
365
  if (metaChunk) {
377
- const dataBuf = Buffer.isBuffer(metaChunk.data)
378
- ? metaChunk.data
379
- : Buffer.from(metaChunk.data);
366
+ const dataBuf = Buffer.from(metaChunk.data);
380
367
  const markerIdx = dataBuf.indexOf(Buffer.from('rXFL'));
381
368
  if (markerIdx !== -1 && markerIdx + 8 <= dataBuf.length) {
382
369
  const jsonLen = dataBuf.readUInt32BE(markerIdx + 4);
@@ -442,7 +429,7 @@ export async function hasPassphraseInPng(pngBuf) {
442
429
  return flag === ENC_AES || flag === ENC_XOR;
443
430
  }
444
431
  try {
445
- const chunksRaw = extract(pngBuf);
432
+ const chunksRaw = native.extractPngChunks(pngBuf);
446
433
  const target = chunksRaw.find((c) => c.name === CHUNK_TYPE);
447
434
  if (target) {
448
435
  const data = Buffer.isBuffer(target.data)
@@ -460,12 +447,8 @@ export async function hasPassphraseInPng(pngBuf) {
460
447
  }
461
448
  catch (e) { }
462
449
  try {
463
- const sharpLib = await import('sharp');
464
- const { data } = await sharpLib
465
- .default(pngBuf)
466
- .raw()
467
- .toBuffer({ resolveWithObject: true });
468
- const rawRGB = Buffer.from(data);
450
+ const rawData = native.sharpToRaw(pngBuf);
451
+ const rawRGB = Buffer.from(rawData.pixels);
469
452
  const markerLen = MARKER_COLORS.length * 3;
470
453
  for (let i = 0; i <= rawRGB.length - markerLen; i += 3) {
471
454
  let ok = true;
@@ -0,0 +1 @@
1
+ export declare const native: any;
@@ -0,0 +1,7 @@
1
+ import { createRequire } from 'module';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = dirname(__filename);
6
+ const require = createRequire(import.meta.url);
7
+ export const native = require(join(__dirname, '../../libroxify_native.node'));
@@ -1,3 +1 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
1
  export declare function optimizePngBuffer(pngBuf: Buffer, fast?: boolean): Promise<Buffer>;
@@ -2,8 +2,6 @@ import { spawn, spawnSync } from 'child_process';
2
2
  import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
3
3
  import { tmpdir } from 'os';
4
4
  import { join } from 'path';
5
- import encode from 'png-chunks-encode';
6
- import extract from 'png-chunks-extract';
7
5
  import * as zlib from 'zlib';
8
6
  import { PNG_HEADER, PNG_HEADER_HEX } from './constants.js';
9
7
  export async function optimizePngBuffer(pngBuf, fast = false) {
@@ -11,6 +9,9 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
11
9
  if (pngBuf.length > MAX_OPTIMIZE_SIZE) {
12
10
  return pngBuf;
13
11
  }
12
+ if (fast) {
13
+ return pngBuf;
14
+ }
14
15
  const runCommandAsync = (cmd, args, timeout = 120000) => {
15
16
  return new Promise((resolve) => {
16
17
  try {
@@ -67,13 +68,12 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
67
68
  }
68
69
  catch (e) { }
69
70
  try {
70
- const chunksRaw = extract(pngBuf);
71
+ const nativeExtract = require('../../libroxify_native.node');
72
+ const chunksRaw = nativeExtract.extractPngChunks(pngBuf);
71
73
  const ihdr = chunksRaw.find((c) => c.name === 'IHDR');
72
74
  if (!ihdr)
73
75
  return pngBuf;
74
- const ihdrData = Buffer.isBuffer(ihdr.data)
75
- ? ihdr.data
76
- : Buffer.from(ihdr.data);
76
+ const ihdrData = Buffer.from(ihdr.data);
77
77
  const width = ihdrData.readUInt32BE(0);
78
78
  const height = ihdrData.readUInt32BE(4);
79
79
  const bitDepth = ihdrData[8];
@@ -81,9 +81,7 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
81
81
  if (bitDepth !== 8 || colorType !== 2)
82
82
  return pngBuf;
83
83
  const idatChunks = chunksRaw.filter((c) => c.name === 'IDAT');
84
- const idatData = Buffer.concat(idatChunks.map((c) => Buffer.isBuffer(c.data)
85
- ? c.data
86
- : Buffer.from(c.data)));
84
+ const idatData = Buffer.concat(idatChunks.map((c) => Buffer.from(c.data)));
87
85
  let raw;
88
86
  try {
89
87
  raw = zlib.inflateSync(idatData);
@@ -204,7 +202,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
204
202
  ? buf
205
203
  : Buffer.concat([PNG_HEADER, buf]);
206
204
  }
207
- const out = ensurePng(Buffer.from(encode(newChunks)));
205
+ const nativeEnc = require('../../libroxify_native.node');
206
+ const out = ensurePng(Buffer.from(nativeEnc.encodePngChunks(newChunks)));
208
207
  let bestBuf = out.length < pngBuf.length ? out : pngBuf;
209
208
  const strategies = [
210
209
  zlib.constants.Z_DEFAULT_STRATEGY,
@@ -227,7 +226,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
227
226
  const idx = altChunks.findIndex((c) => c.name === 'IDAT');
228
227
  if (idx !== -1)
229
228
  altChunks[idx] = { name: 'IDAT', data: comp };
230
- const candidate = ensurePng(Buffer.from(encode(altChunks)));
229
+ const nativeOptim = require('../../libroxify_native.node');
230
+ const candidate = ensurePng(Buffer.from(nativeOptim.encodePngChunks(altChunks)));
231
231
  if (candidate.length < bestBuf.length)
232
232
  bestBuf = candidate;
233
233
  }
@@ -245,7 +245,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
245
245
  const idx = altChunks.findIndex((c) => c.name === 'IDAT');
246
246
  if (idx !== -1)
247
247
  altChunks[idx] = { name: 'IDAT', data: Buffer.from(comp) };
248
- const candidate = ensurePng(Buffer.from(encode(altChunks)));
248
+ const native = require('../../libroxify_native.node');
249
+ const candidate = ensurePng(Buffer.from(native.encodePngChunks(altChunks)));
249
250
  if (candidate.length < bestBuf.length)
250
251
  bestBuf = candidate;
251
252
  }
@@ -303,7 +304,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
303
304
  const idx = altChunks.findIndex((c) => c.name === 'IDAT');
304
305
  if (idx !== -1)
305
306
  altChunks[idx] = { name: 'IDAT', data: comp };
306
- const candidate = ensurePng(Buffer.from(encode(altChunks)));
307
+ const native = require('../../libroxify_native.node');
308
+ const candidate = ensurePng(Buffer.from(native.encodePngChunks(altChunks)));
307
309
  if (candidate.length < bestBuf.length)
308
310
  bestBuf = candidate;
309
311
  }
@@ -383,7 +385,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
383
385
  const idx = altChunks.findIndex((c) => c.name === 'IDAT');
384
386
  if (idx !== -1)
385
387
  altChunks[idx] = { name: 'IDAT', data: comp };
386
- const candidate = ensurePng(Buffer.from(encode(altChunks)));
388
+ const nativeOptim2 = require('../../libroxify_native.node');
389
+ const candidate = ensurePng(Buffer.from(nativeOptim2.encodePngChunks(altChunks)));
387
390
  if (candidate.length < bestBuf.length)
388
391
  bestBuf = candidate;
389
392
  }
@@ -589,7 +592,8 @@ export async function optimizePngBuffer(pngBuf, fast = false) {
589
592
  data: zlib.deflateSync(idxFilteredAllVar, { level: 9 }),
590
593
  });
591
594
  palChunksVar.push({ name: 'IEND', data: Buffer.alloc(0) });
592
- const palOutVar = ensurePng(Buffer.from(encode(palChunksVar)));
595
+ const native = require('../../libroxify_native.node');
596
+ const palOutVar = ensurePng(Buffer.from(native.encodePngChunks(palChunksVar)));
593
597
  if (palOutVar.length < bestBuf.length)
594
598
  bestBuf = palOutVar;
595
599
  }
@@ -1,3 +1 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
1
  export declare function cropAndReconstitute(input: Buffer, debugDir?: string): Promise<Buffer>;
@@ -1,266 +1,3 @@
1
- import { join } from 'path';
2
- import sharp from 'sharp';
3
1
  export async function cropAndReconstitute(input, debugDir) {
4
- async function loadRaw(imgInput) {
5
- const { data, info } = await sharp(imgInput)
6
- .ensureAlpha()
7
- .raw()
8
- .toBuffer({ resolveWithObject: true });
9
- return { data, info };
10
- }
11
- function idxFor(x, y, width) {
12
- return (y * width + x) * 4;
13
- }
14
- function eqRGB(a, b) {
15
- return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
16
- }
17
- const { info } = await loadRaw(input);
18
- const doubledBuffer = await sharp(input)
19
- .resize({
20
- width: info.width * 2,
21
- height: info.height * 2,
22
- kernel: 'nearest',
23
- })
24
- .png()
25
- .toBuffer();
26
- if (debugDir) {
27
- await sharp(doubledBuffer).toFile(join(debugDir, 'doubled.png'));
28
- }
29
- const { data: doubledData, info: doubledInfo } = await loadRaw(doubledBuffer);
30
- const w = doubledInfo.width, h = doubledInfo.height;
31
- const at = (x, y) => {
32
- const i = idxFor(x, y, w);
33
- return [
34
- doubledData[i],
35
- doubledData[i + 1],
36
- doubledData[i + 2],
37
- doubledData[i + 3],
38
- ];
39
- };
40
- const findPattern = (startX, startY, dirX, dirY, pattern) => {
41
- for (let y = startY; y >= 0 && y < h; y += dirY) {
42
- for (let x = startX; x >= 0 && x < w; x += dirX) {
43
- const p = at(x, y);
44
- if (p[0] !== 255 || p[1] !== 0 || p[2] !== 0)
45
- continue;
46
- let nx = x + dirX;
47
- while (nx >= 0 && nx < w && eqRGB(at(nx, y), p))
48
- nx += dirX;
49
- if (nx < 0 || nx >= w)
50
- continue;
51
- const a = at(nx, y);
52
- let nx2 = nx + dirX;
53
- while (nx2 >= 0 && nx2 < w && eqRGB(at(nx2, y), a))
54
- nx2 += dirX;
55
- if (nx2 < 0 || nx2 >= w)
56
- continue;
57
- const b = at(nx2, y);
58
- if (a[0] === pattern[0][0] &&
59
- a[1] === pattern[0][1] &&
60
- a[2] === pattern[0][2] &&
61
- b[0] === pattern[1][0] &&
62
- b[1] === pattern[1][1] &&
63
- b[2] === pattern[1][2]) {
64
- return { x, y };
65
- }
66
- }
67
- }
68
- return null;
69
- };
70
- const startPoint = findPattern(0, 0, 1, 1, [
71
- [0, 255, 0],
72
- [0, 0, 255],
73
- ]);
74
- const endPoint = findPattern(w - 1, h - 1, -1, -1, [
75
- [0, 255, 0],
76
- [0, 0, 255],
77
- ]);
78
- if (!startPoint || !endPoint)
79
- throw new Error('Patterns not found');
80
- const sx1 = Math.min(startPoint.x, endPoint.x), sy1 = Math.min(startPoint.y, endPoint.y);
81
- const sx2 = Math.max(startPoint.x, endPoint.x), sy2 = Math.max(startPoint.y, endPoint.y);
82
- const cropW = sx2 - sx1 + 1, cropH = sy2 - sy1 + 1;
83
- if (cropW <= 0 || cropH <= 0)
84
- throw new Error('Invalid crop dimensions');
85
- const cropped = await sharp(doubledBuffer)
86
- .extract({ left: sx1, top: sy1, width: cropW, height: cropH })
87
- .png()
88
- .toBuffer();
89
- const { data: cdata, info: cinfo } = await loadRaw(cropped);
90
- const cw = cinfo.width, ch = cinfo.height;
91
- const newWidth = cw, newHeight = ch + 1;
92
- const out = Buffer.alloc(newWidth * newHeight * 4, 0);
93
- for (let i = 0; i < out.length; i += 4)
94
- out[i + 3] = 255;
95
- for (let y = 0; y < ch; y++) {
96
- for (let x = 0; x < cw; x++) {
97
- const srcI = (y * cw + x) * 4;
98
- const dstI = (y * newWidth + x) * 4;
99
- out[dstI] = cdata[srcI];
100
- out[dstI + 1] = cdata[srcI + 1];
101
- out[dstI + 2] = cdata[srcI + 2];
102
- out[dstI + 3] = cdata[srcI + 3];
103
- }
104
- }
105
- for (let x = 0; x < newWidth; x++) {
106
- const i = ((ch - 1) * newWidth + x) * 4;
107
- out[i] = out[i + 1] = out[i + 2] = 0;
108
- out[i + 3] = 255;
109
- const j = (ch * newWidth + x) * 4;
110
- out[j] = out[j + 1] = out[j + 2] = 0;
111
- out[j + 3] = 255;
112
- }
113
- if (newWidth >= 3) {
114
- const bgrStart = newWidth - 3;
115
- const bgr = [
116
- [0, 0, 255],
117
- [0, 255, 0],
118
- [255, 0, 0],
119
- ];
120
- for (let k = 0; k < 3; k++) {
121
- const i = (ch * newWidth + bgrStart + k) * 4;
122
- out[i] = bgr[k][0];
123
- out[i + 1] = bgr[k][1];
124
- out[i + 2] = bgr[k][2];
125
- out[i + 3] = 255;
126
- }
127
- }
128
- const getPixel = (x, y) => {
129
- const i = (y * newWidth + x) * 4;
130
- return [out[i], out[i + 1], out[i + 2], out[i + 3]];
131
- };
132
- const compressedLines = [];
133
- for (let y = 0; y < newHeight; y++) {
134
- const line = [];
135
- for (let x = 0; x < newWidth; x++)
136
- line.push(getPixel(x, y));
137
- const isAllBlack = line.every((p) => p[0] === 0 && p[1] === 0 && p[2] === 0 && p[3] === 255);
138
- if (!isAllBlack &&
139
- (compressedLines.length === 0 ||
140
- !line.every((p, i) => p.every((v, j) => v === compressedLines[compressedLines.length - 1][i][j])))) {
141
- compressedLines.push(line);
142
- }
143
- }
144
- if (compressedLines.length === 0) {
145
- return sharp({
146
- create: {
147
- width: 1,
148
- height: 1,
149
- channels: 4,
150
- background: { r: 0, g: 0, b: 0, alpha: 1 },
151
- },
152
- })
153
- .png()
154
- .toBuffer();
155
- }
156
- let finalWidth = newWidth, finalHeight = compressedLines.length;
157
- let finalOut = Buffer.alloc(finalWidth * finalHeight * 4, 0);
158
- for (let i = 0; i < finalOut.length; i += 4)
159
- finalOut[i + 3] = 255;
160
- for (let y = 0; y < finalHeight; y++) {
161
- for (let x = 0; x < finalWidth; x++) {
162
- const i = (y * finalWidth + x) * 4;
163
- finalOut[i] = compressedLines[y][x][0];
164
- finalOut[i + 1] = compressedLines[y][x][1];
165
- finalOut[i + 2] = compressedLines[y][x][2];
166
- finalOut[i + 3] = compressedLines[y][x][3] || 255;
167
- }
168
- }
169
- if (finalHeight >= 1 && finalWidth >= 3) {
170
- const lastY = finalHeight - 1;
171
- for (let k = 0; k < 3; k++) {
172
- const i = (lastY * finalWidth + finalWidth - 3 + k) * 4;
173
- finalOut[i] = finalOut[i + 1] = finalOut[i + 2] = 0;
174
- finalOut[i + 3] = 255;
175
- }
176
- }
177
- if (finalWidth >= 2) {
178
- const kept = [];
179
- for (let x = 0; x < finalWidth; x++) {
180
- if (kept.length === 0) {
181
- kept.push(x);
182
- continue;
183
- }
184
- const prevX = kept[kept.length - 1];
185
- let same = true;
186
- for (let y = 0; y < finalHeight; y++) {
187
- const ia = (y * finalWidth + prevX) * 4, ib = (y * finalWidth + x) * 4;
188
- if (finalOut[ia] !== finalOut[ib] ||
189
- finalOut[ia + 1] !== finalOut[ib + 1] ||
190
- finalOut[ia + 2] !== finalOut[ib + 2] ||
191
- finalOut[ia + 3] !== finalOut[ib + 3]) {
192
- same = false;
193
- break;
194
- }
195
- }
196
- if (!same)
197
- kept.push(x);
198
- }
199
- if (kept.length !== finalWidth) {
200
- const newFinalWidth = kept.length;
201
- const newOut = Buffer.alloc(newFinalWidth * finalHeight * 4, 0);
202
- for (let i = 0; i < newOut.length; i += 4)
203
- newOut[i + 3] = 255;
204
- for (let nx = 0; nx < kept.length; nx++) {
205
- const sx = kept[nx];
206
- for (let y = 0; y < finalHeight; y++) {
207
- const srcI = (y * finalWidth + sx) * 4, dstI = (y * newFinalWidth + nx) * 4;
208
- newOut[dstI] = finalOut[srcI];
209
- newOut[dstI + 1] = finalOut[srcI + 1];
210
- newOut[dstI + 2] = finalOut[srcI + 2];
211
- newOut[dstI + 3] = finalOut[srcI + 3];
212
- }
213
- }
214
- finalOut = newOut;
215
- finalWidth = newFinalWidth;
216
- }
217
- }
218
- if (finalHeight >= 2 && finalWidth >= 3) {
219
- const secondLastY = finalHeight - 2;
220
- const bgrSeq = [
221
- [0, 0, 255],
222
- [0, 255, 0],
223
- [255, 0, 0],
224
- ];
225
- let hasBGR = true;
226
- for (let k = 0; k < 3; k++) {
227
- const i = (secondLastY * finalWidth + finalWidth - 3 + k) * 4;
228
- if (finalOut[i] !== bgrSeq[k][0] ||
229
- finalOut[i + 1] !== bgrSeq[k][1] ||
230
- finalOut[i + 2] !== bgrSeq[k][2]) {
231
- hasBGR = false;
232
- break;
233
- }
234
- }
235
- if (hasBGR) {
236
- for (let k = 0; k < 3; k++) {
237
- const i = (secondLastY * finalWidth + finalWidth - 3 + k) * 4;
238
- finalOut[i] = finalOut[i + 1] = finalOut[i + 2] = 0;
239
- finalOut[i + 3] = 255;
240
- }
241
- }
242
- }
243
- if (finalHeight >= 1 && finalWidth >= 1) {
244
- const lastYFinal = finalHeight - 1;
245
- const bgrSeq = [
246
- [0, 0, 255],
247
- [0, 255, 0],
248
- [255, 0, 0],
249
- ];
250
- for (let k = 0; k < 3; k++) {
251
- const sx = finalWidth - 3 + k;
252
- if (sx >= 0) {
253
- const i = (lastYFinal * finalWidth + sx) * 4;
254
- finalOut[i] = bgrSeq[k][0];
255
- finalOut[i + 1] = bgrSeq[k][1];
256
- finalOut[i + 2] = bgrSeq[k][2];
257
- finalOut[i + 3] = 255;
258
- }
259
- }
260
- }
261
- return sharp(finalOut, {
262
- raw: { width: finalWidth, height: finalHeight, channels: 4 },
263
- })
264
- .png()
265
- .toBuffer();
2
+ return input;
266
3
  }
@@ -62,13 +62,7 @@ export async function encodeWithRustCLI(inputPath, outputPath, compressionLevel
62
62
  throw new Error('Rust CLI binary not found. Run: cargo build --release');
63
63
  }
64
64
  return new Promise((resolve, reject) => {
65
- const args = [
66
- 'encode',
67
- inputPath,
68
- outputPath,
69
- '--level',
70
- String(compressionLevel),
71
- ];
65
+ const args = ['encode', '--level', String(compressionLevel)];
72
66
  if (name) {
73
67
  args.push('--name', name);
74
68
  }
@@ -76,6 +70,7 @@ export async function encodeWithRustCLI(inputPath, outputPath, compressionLevel
76
70
  args.push('--passphrase', passphrase);
77
71
  args.push('--encrypt', encryptType);
78
72
  }
73
+ args.push(inputPath, outputPath);
79
74
  const proc = spawn(cliPath, args);
80
75
  let stderr = '';
81
76
  proc.stderr.on('data', (data) => {
@@ -1,5 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
1
  import { PackedFile } from '../pack.js';
4
2
  export interface EncodeOptions {
5
3
  compression?: 'zstd';
@@ -1,5 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
1
  export declare function compressStream(stream: AsyncGenerator<Buffer>, level?: number, onProgress?: (loaded: number, total: number) => void): Promise<{
4
2
  chunks: Buffer[];
5
3
  totalLength: number;