roxify 1.1.7 → 1.1.8
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/README.md +39 -122
- package/dist/index.d.ts +20 -0
- package/dist/index.js +20 -0
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -28,8 +28,8 @@ npm install roxify
|
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
npx rox encode <inputName>.ext (<outputName>.png)
|
|
31
|
-
|
|
32
31
|
npx rox decode <inputName>.png (<outputName>.ext)
|
|
32
|
+
npx rox list <inputName>.png
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
If no output name is provided:
|
|
@@ -37,154 +37,71 @@ If no output name is provided:
|
|
|
37
37
|
- Encoding: output defaults to `<inputName>.png`.
|
|
38
38
|
- Decoding: if the image contains the original filename it will be restored; otherwise the output will be `decoded.bin`.
|
|
39
39
|
|
|
40
|
-
**Commands:**
|
|
41
|
-
|
|
42
|
-
- `encode <input>... [output]` — Encode file(s)/directory to PNG
|
|
43
|
-
- `decode <input> [output]` — Decode PNG to file(s)
|
|
44
|
-
- `list <input>` — List files in archive without decoding
|
|
45
|
-
|
|
46
40
|
**Options:**
|
|
47
41
|
|
|
48
42
|
- `-p, --passphrase <pass>` — Encrypt with AES-256-GCM
|
|
49
|
-
- `-m, --mode <mode>` — Encoding mode: `screenshot` (default), `pixel`, `compact`, `chunk`
|
|
50
|
-
- `-q, --quality <0-22>` — Roxify compression level (default: 22)
|
|
51
|
-
- `--no-compress` — Disable compression
|
|
52
|
-
- `--files <list>` — Extract only specified files (comma-separated, for archives)
|
|
53
43
|
- `-v, --verbose` — Show detailed errors
|
|
54
44
|
|
|
55
45
|
Run `npx rox help` for full options.
|
|
56
46
|
|
|
57
47
|
## API Usage
|
|
58
48
|
|
|
49
|
+
### Basic Encoding and Decoding
|
|
50
|
+
|
|
59
51
|
```js
|
|
60
|
-
import {
|
|
52
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
53
|
+
import { encodeBinaryToPng } from 'roxify';
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
name: 'message.txt',
|
|
55
|
+
const fileName = 'input.bin';
|
|
56
|
+
const inputBuffer = readFileSync(fileName);
|
|
57
|
+
const pngBuffer = await encodeBinaryToPng(inputBuffer, {
|
|
58
|
+
name: fileName,
|
|
67
59
|
});
|
|
68
|
-
|
|
69
|
-
// Decode
|
|
70
|
-
const { buf, meta } = await decodePngToBinary(png);
|
|
71
|
-
console.log(buf.toString('utf8'));
|
|
72
|
-
console.log(meta?.name);
|
|
73
|
-
|
|
74
|
-
// List files in archive
|
|
75
|
-
const files = listFilesInPng(png);
|
|
76
|
-
console.log(files);
|
|
77
|
-
|
|
78
|
-
// Selective extraction
|
|
79
|
-
const result = await decodePngToBinary(png, { files: ['file1.txt'] });
|
|
80
|
-
if (result.files) {
|
|
81
|
-
// result.files contains only the selected files
|
|
82
|
-
}
|
|
60
|
+
writeFileSync('output.png', pngBuffer);
|
|
83
61
|
```
|
|
84
62
|
|
|
85
|
-
|
|
63
|
+
```js
|
|
64
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
65
|
+
import { decodePngToBinary } from 'roxify';
|
|
86
66
|
|
|
87
|
-
|
|
88
|
-
|
|
67
|
+
const pngFromDisk = readFileSync('output.png');
|
|
68
|
+
const { buf, meta } = await decodePngToBinary(pngFromDisk);
|
|
69
|
+
writeFileSync(meta?.name ?? 'decoded.txt', buf);
|
|
70
|
+
```
|
|
89
71
|
|
|
90
|
-
|
|
72
|
+
### With Passphrase
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (info.loaded && info.total) {
|
|
97
|
-
const percent = Math.round((info.loaded / info.total) * 100);
|
|
98
|
-
console.log(`Progress: ${percent}% (${info.loaded}/${info.total} bytes)`);
|
|
99
|
-
}
|
|
100
|
-
},
|
|
74
|
+
```js
|
|
75
|
+
const pngBuffer = await encodeBinaryToPng(inputBuffer, {
|
|
76
|
+
name: fileName,
|
|
77
|
+
passphrase: 'mysecret',
|
|
101
78
|
});
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Node.js (detailed chunk progress example)
|
|
79
|
+
```
|
|
105
80
|
|
|
106
81
|
```js
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const buf = readFileSync('test-data/testVideo.mp4');
|
|
111
|
-
const png = await encodeBinaryToPng(buf, {
|
|
112
|
-
showProgress: false,
|
|
113
|
-
onProgress(info) {
|
|
114
|
-
if (info.phase === 'compress_progress' && info.loaded && info.total) {
|
|
115
|
-
const percent = Math.round((info.loaded / info.total) * 100);
|
|
116
|
-
console.log(`[progress] ${info.phase} ${percent}% (${info.loaded}/${info.total} chunks)`);
|
|
117
|
-
} else {
|
|
118
|
-
console.log(`[progress] ${info.phase} ${info.loaded || ''}/${info.total || ''}`);
|
|
119
|
-
}
|
|
120
|
-
},
|
|
82
|
+
const { buf, meta } = await decodePngToBinary(pngFromDisk, {
|
|
83
|
+
passphrase: 'mysecret',
|
|
121
84
|
});
|
|
85
|
+
```
|
|
122
86
|
|
|
123
|
-
|
|
124
|
-
````
|
|
87
|
+
### With Progress Logging
|
|
125
88
|
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
},
|
|
89
|
+
```js
|
|
90
|
+
const pngBuffer = await encodeBinaryToPng(inputBuffer, {
|
|
91
|
+
name: fileName,
|
|
92
|
+
onProgress: (info) => {
|
|
93
|
+
console.log(`Phase: ${info.phase}, Loaded: ${info.loaded}/${info.total}`);
|
|
94
|
+
},
|
|
131
95
|
});
|
|
132
|
-
|
|
133
|
-
````
|
|
134
|
-
|
|
135
|
-
**API:**
|
|
136
|
-
|
|
137
|
-
- `encodeBinaryToPng(input: Buffer, opts?: EncodeOptions): Promise<Buffer>`
|
|
138
|
-
- `decodePngToBinary(pngBuf: Buffer, opts?: DecodeOptions): Promise<DecodeResult>`
|
|
139
|
-
- `listFilesInPng(pngBuf: Buffer): string[] | null`
|
|
140
|
-
|
|
141
|
-
**EncodeOptions:**
|
|
142
|
-
|
|
143
|
-
- `mode` — `'screenshot'` | `'pixel'` | `'compact'` | `'chunk'` (default: `'screenshot'`)
|
|
144
|
-
- `name` — Original filename (embedded as metadata)
|
|
145
|
-
- `passphrase` — Encryption passphrase (uses AES-256-GCM)
|
|
146
|
-
- `compression` — `'Roxify'` | `'none'` (default: `'Roxify'`)
|
|
147
|
-
- `brQuality` — Roxify compression level 0-22 (default: 22)
|
|
148
|
-
- `showProgress` — Display progress bar (default: `false`)
|
|
149
|
-
- `onProgress` — Callback for progress updates: `(info: { phase: string; loaded?: number; total?: number }) => void`
|
|
150
|
-
- `includeFileList` — Include file list for archives (default: `true` for directories)
|
|
151
|
-
|
|
152
|
-
**DecodeOptions:**
|
|
153
|
-
|
|
154
|
-
- `passphrase` — Decryption passphrase
|
|
155
|
-
- `files` — List of files to extract selectively (for archives)
|
|
156
|
-
- `showProgress` — Display progress bar (default: `false`)
|
|
157
|
-
- `onProgress` — Callback for progress updates: `(info: { phase: string; loaded?: number; total?: number }) => void`
|
|
158
|
-
|
|
159
|
-
**DecodeResult:**
|
|
160
|
-
|
|
161
|
-
- `buf?: Buffer` — Decoded data (if not selective extraction)
|
|
162
|
-
- `files?: PackedFile[]` — Extracted files (if selective extraction)
|
|
163
|
-
- `meta?: { name?: string }` — Metadata
|
|
164
|
-
|
|
165
|
-
## Example: Archive with Selective Extraction
|
|
96
|
+
```
|
|
166
97
|
|
|
167
98
|
```js
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const dirData = packPaths(['myfolder']); // From pack.js
|
|
173
|
-
const png = await encodeBinaryToPng(dirData.buf, {
|
|
174
|
-
includeFileList: true,
|
|
175
|
-
fileList: dirData.list,
|
|
99
|
+
const { buf, meta } = await decodePngToBinary(pngFromDisk, {
|
|
100
|
+
onProgress: (info) => {
|
|
101
|
+
console.log(`Phase: ${info.phase}, Loaded: ${info.loaded}/${info.total}`);
|
|
102
|
+
},
|
|
176
103
|
});
|
|
177
|
-
|
|
178
|
-
// List files without decoding
|
|
179
|
-
const files = listFilesInPng(png);
|
|
180
|
-
console.log('Files:', files);
|
|
181
|
-
|
|
182
|
-
// Extract only one file
|
|
183
|
-
const result = await decodePngToBinary(png, { files: ['myfolder/file.txt'] });
|
|
184
|
-
if (result.files) {
|
|
185
|
-
fs.writeFileSync('extracted.txt', result.files[0].buf);
|
|
186
|
-
}
|
|
187
|
-
````
|
|
104
|
+
```
|
|
188
105
|
|
|
189
106
|
## Requirements
|
|
190
107
|
|
package/dist/index.d.ts
CHANGED
|
@@ -157,6 +157,19 @@ export declare function cropAndReconstitute(input: Buffer, debugDir?: string): P
|
|
|
157
157
|
* @param input - Data to encode
|
|
158
158
|
* @param opts - Encoding options
|
|
159
159
|
* @public
|
|
160
|
+
* @example
|
|
161
|
+
* ```typescript
|
|
162
|
+
* import { readFileSync, writeFileSync } from 'fs';
|
|
163
|
+
* import { encodeBinaryToPng } from 'roxify';
|
|
164
|
+
*
|
|
165
|
+
* const fileName = 'input.bin'; //Path of your input file here
|
|
166
|
+
* const inputBuffer = readFileSync(fileName);
|
|
167
|
+
* const pngBuffer = await encodeBinaryToPng(inputBuffer, {
|
|
168
|
+
* name: fileName,
|
|
169
|
+
* });
|
|
170
|
+
* writeFileSync('output.png', pngBuffer);
|
|
171
|
+
|
|
172
|
+
* ```
|
|
160
173
|
*/
|
|
161
174
|
export declare function encodeBinaryToPng(input: Buffer, opts?: EncodeOptions): Promise<Buffer>;
|
|
162
175
|
/**
|
|
@@ -166,6 +179,13 @@ export declare function encodeBinaryToPng(input: Buffer, opts?: EncodeOptions):
|
|
|
166
179
|
* @param pngBuf - PNG data
|
|
167
180
|
* @param opts - Options (passphrase for encrypted inputs)
|
|
168
181
|
* @public
|
|
182
|
+
* @example
|
|
183
|
+
* import { readFileSync, writeFileSync } from 'fs';
|
|
184
|
+
* import { decodePngToBinary } from 'roxify';
|
|
185
|
+
*
|
|
186
|
+
* const pngFromDisk = readFileSync('output.png'); //Path of the encoded PNG here
|
|
187
|
+
* const { buf, meta } = await decodePngToBinary(pngFromDisk);
|
|
188
|
+
* writeFileSync(meta?.name ?? 'decoded.txt', buf);
|
|
169
189
|
*/
|
|
170
190
|
export declare function decodePngToBinary(pngBuf: Buffer, opts?: DecodeOptions): Promise<DecodeResult>;
|
|
171
191
|
export { packPaths, unpackBuffer } from './pack.js';
|
package/dist/index.js
CHANGED
|
@@ -537,6 +537,19 @@ export async function cropAndReconstitute(input, debugDir) {
|
|
|
537
537
|
* @param input - Data to encode
|
|
538
538
|
* @param opts - Encoding options
|
|
539
539
|
* @public
|
|
540
|
+
* @example
|
|
541
|
+
* ```typescript
|
|
542
|
+
* import { readFileSync, writeFileSync } from 'fs';
|
|
543
|
+
* import { encodeBinaryToPng } from 'roxify';
|
|
544
|
+
*
|
|
545
|
+
* const fileName = 'input.bin'; //Path of your input file here
|
|
546
|
+
* const inputBuffer = readFileSync(fileName);
|
|
547
|
+
* const pngBuffer = await encodeBinaryToPng(inputBuffer, {
|
|
548
|
+
* name: fileName,
|
|
549
|
+
* });
|
|
550
|
+
* writeFileSync('output.png', pngBuffer);
|
|
551
|
+
|
|
552
|
+
* ```
|
|
540
553
|
*/
|
|
541
554
|
export async function encodeBinaryToPng(input, opts = {}) {
|
|
542
555
|
let progressBar = null;
|
|
@@ -887,6 +900,13 @@ export async function encodeBinaryToPng(input, opts = {}) {
|
|
|
887
900
|
* @param pngBuf - PNG data
|
|
888
901
|
* @param opts - Options (passphrase for encrypted inputs)
|
|
889
902
|
* @public
|
|
903
|
+
* @example
|
|
904
|
+
* import { readFileSync, writeFileSync } from 'fs';
|
|
905
|
+
* import { decodePngToBinary } from 'roxify';
|
|
906
|
+
*
|
|
907
|
+
* const pngFromDisk = readFileSync('output.png'); //Path of the encoded PNG here
|
|
908
|
+
* const { buf, meta } = await decodePngToBinary(pngFromDisk);
|
|
909
|
+
* writeFileSync(meta?.name ?? 'decoded.txt', buf);
|
|
890
910
|
*/
|
|
891
911
|
export async function decodePngToBinary(pngBuf, opts = {}) {
|
|
892
912
|
let progressBar = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roxify",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Encode binary data into PNG images with Zstd compression and decode them back. Supports CLI and programmatic API (Node.js ESM).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,16 +21,19 @@
|
|
|
21
21
|
"keywords": [
|
|
22
22
|
"steganography",
|
|
23
23
|
"png",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"decompress",
|
|
24
|
+
"zstd",
|
|
25
|
+
"compression",
|
|
26
|
+
"encryption",
|
|
28
27
|
"encode",
|
|
29
28
|
"decode",
|
|
30
29
|
"cli",
|
|
31
30
|
"nodejs",
|
|
32
31
|
"esm",
|
|
33
|
-
"
|
|
32
|
+
"data-embedding",
|
|
33
|
+
"file-archive",
|
|
34
|
+
"lossless",
|
|
35
|
+
"aes-gcm",
|
|
36
|
+
"binary-data"
|
|
34
37
|
],
|
|
35
38
|
"author": "RoxCompressor",
|
|
36
39
|
"license": "UNLICENSED",
|