omnius 1.0.9 → 1.0.11
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 +2 -2
- package/dist/index.js +26 -10
- package/dist/postinstall-daemon.cjs +15 -0
- package/dist/preinstall.cjs +25 -1
- package/node_modules/image-to-ascii/bin/image-to-ascii.cjs +18 -0
- package/node_modules/image-to-ascii/index.cjs +257 -0
- package/node_modules/image-to-ascii/index.d.ts +48 -0
- package/node_modules/image-to-ascii/package.json +22 -0
- package/npm-shrinkwrap.json +18 -557
- package/package.json +7 -3
- package/vendor/image-to-ascii/bin/image-to-ascii.cjs +18 -0
- package/vendor/image-to-ascii/index.cjs +257 -0
- package/vendor/image-to-ascii/index.d.ts +48 -0
- package/vendor/image-to-ascii/package.json +22 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var childProcess = require("node:child_process");
|
|
4
|
+
var crypto = require("node:crypto");
|
|
5
|
+
var fs = require("node:fs");
|
|
6
|
+
var os = require("node:os");
|
|
7
|
+
var path = require("node:path");
|
|
8
|
+
|
|
9
|
+
var DEFAULT_PIXELS = " .,:;i1tfLCG08@";
|
|
10
|
+
|
|
11
|
+
function isObject(value) {
|
|
12
|
+
return value !== null && typeof value === "object" && !Buffer.isBuffer(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function clamp(value, min, max) {
|
|
16
|
+
var n = Number(value);
|
|
17
|
+
if (!Number.isFinite(n)) return min;
|
|
18
|
+
n = Math.floor(n);
|
|
19
|
+
return Math.max(min, Math.min(max, n));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function percentOrNumber(value, basis, fallback) {
|
|
23
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
24
|
+
if (typeof value === "string") {
|
|
25
|
+
var trimmed = value.trim();
|
|
26
|
+
if (trimmed.endsWith("%")) {
|
|
27
|
+
var pct = Number(trimmed.slice(0, -1));
|
|
28
|
+
if (Number.isFinite(pct)) return Math.max(1, Math.floor((basis * pct) / 100));
|
|
29
|
+
}
|
|
30
|
+
var parsed = Number(trimmed);
|
|
31
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
32
|
+
}
|
|
33
|
+
return fallback;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveSize(options) {
|
|
37
|
+
var size = isObject(options.size) ? options.size : {};
|
|
38
|
+
var sizeOptions = isObject(options.size_options) ? options.size_options : {};
|
|
39
|
+
var screen = isObject(sizeOptions.screen_size) ? sizeOptions.screen_size : {};
|
|
40
|
+
var screenWidth = clamp(screen.width || process.stdout.columns || 80, 20, 240);
|
|
41
|
+
var screenHeight = clamp(screen.height || process.stdout.rows || 32, 8, 120);
|
|
42
|
+
var width = percentOrNumber(size.width, screenWidth, Math.min(80, screenWidth));
|
|
43
|
+
var height = percentOrNumber(size.height, screenHeight, Math.max(8, Math.round(width * 0.42)));
|
|
44
|
+
return {
|
|
45
|
+
width: clamp(width, 8, 240),
|
|
46
|
+
height: clamp(height, 4, 120)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeOptions(options) {
|
|
51
|
+
if (!isObject(options)) options = {};
|
|
52
|
+
var pixels = options.pixels;
|
|
53
|
+
if (Array.isArray(pixels)) pixels = pixels.join("");
|
|
54
|
+
if (typeof pixels !== "string" || pixels.length < 2) pixels = DEFAULT_PIXELS;
|
|
55
|
+
if (options.reverse === true) pixels = pixels.split("").reverse().join("");
|
|
56
|
+
return {
|
|
57
|
+
pixels: pixels,
|
|
58
|
+
colored: options.colored === true,
|
|
59
|
+
concat: options.concat !== false,
|
|
60
|
+
stringify: options.stringify !== false,
|
|
61
|
+
timeoutMs: clamp(options.timeoutMs || options.timeout || 5000, 500, 60000),
|
|
62
|
+
preserveAspectRatio: !options.size_options || options.size_options.preserve_aspect_ratio !== false,
|
|
63
|
+
size: resolveSize(options),
|
|
64
|
+
stringifyFn: typeof options.stringify_fn === "function" ? options.stringify_fn : null
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function tempFilePath(ext) {
|
|
69
|
+
var suffix = ext || ".img";
|
|
70
|
+
if (!suffix.startsWith(".")) suffix = "." + suffix;
|
|
71
|
+
return path.join(os.tmpdir(), "omnius-image-to-ascii-" + crypto.randomUUID() + suffix);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function extensionFromUrl(url) {
|
|
75
|
+
try {
|
|
76
|
+
var parsed = new URL(url);
|
|
77
|
+
var ext = path.extname(parsed.pathname || "");
|
|
78
|
+
return ext || ".img";
|
|
79
|
+
} catch (e) {
|
|
80
|
+
return ".img";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function sourceToFile(source, callback) {
|
|
85
|
+
if (Buffer.isBuffer(source)) {
|
|
86
|
+
var bufPath = tempFilePath(".img");
|
|
87
|
+
fs.writeFile(bufPath, source, function (err) {
|
|
88
|
+
callback(err, bufPath, true);
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (typeof source !== "string" || source.trim().length === 0) {
|
|
94
|
+
callback(new Error("image-to-ascii source must be a file path, URL, or Buffer"));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (/^https?:\/\//i.test(source)) {
|
|
99
|
+
if (typeof fetch !== "function") {
|
|
100
|
+
callback(new Error("image-to-ascii URL input requires Node fetch support"));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
fetch(source).then(function (res) {
|
|
104
|
+
if (!res.ok) throw new Error("image-to-ascii failed to fetch image: HTTP " + res.status);
|
|
105
|
+
return res.arrayBuffer();
|
|
106
|
+
}).then(function (arrayBuffer) {
|
|
107
|
+
var urlPath = tempFilePath(extensionFromUrl(source));
|
|
108
|
+
fs.writeFile(urlPath, Buffer.from(arrayBuffer), function (err) {
|
|
109
|
+
callback(err, urlPath, true);
|
|
110
|
+
});
|
|
111
|
+
}).catch(function (err) {
|
|
112
|
+
callback(err);
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
callback(null, source, false);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function buildFilter(width, height, preserveAspectRatio) {
|
|
121
|
+
if (preserveAspectRatio) {
|
|
122
|
+
return [
|
|
123
|
+
"scale=" + width + ":" + height + ":force_original_aspect_ratio=decrease",
|
|
124
|
+
"pad=" + width + ":" + height + ":(ow-iw)/2:(oh-ih)/2:color=black",
|
|
125
|
+
"format=gray"
|
|
126
|
+
].join(",");
|
|
127
|
+
}
|
|
128
|
+
return "scale=" + width + ":" + height + ",format=gray";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function matrixFromRaw(raw, width, height) {
|
|
132
|
+
var matrix = [];
|
|
133
|
+
for (var y = 0; y < height; y++) {
|
|
134
|
+
var row = [];
|
|
135
|
+
for (var x = 0; x < width; x++) {
|
|
136
|
+
var value = raw[y * width + x] || 0;
|
|
137
|
+
row.push({ r: value, g: value, b: value, a: 255, value: value });
|
|
138
|
+
}
|
|
139
|
+
matrix.push(row);
|
|
140
|
+
}
|
|
141
|
+
return matrix;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function stringifyMatrix(matrix, options) {
|
|
145
|
+
var lines = [];
|
|
146
|
+
var pixels = options.pixels;
|
|
147
|
+
var maxIdx = pixels.length - 1;
|
|
148
|
+
for (var y = 0; y < matrix.length; y++) {
|
|
149
|
+
var line = "";
|
|
150
|
+
for (var x = 0; x < matrix[y].length; x++) {
|
|
151
|
+
var value = matrix[y][x].value || 0;
|
|
152
|
+
var idx = Math.round((value / 255) * maxIdx);
|
|
153
|
+
var ch = pixels[idx] || " ";
|
|
154
|
+
if (options.colored) {
|
|
155
|
+
line += "\x1b[38;2;" + value + ";" + value + ";" + value + "m" + ch + "\x1b[0m";
|
|
156
|
+
} else {
|
|
157
|
+
line += ch;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
lines.push(line.replace(/\s+$/g, ""));
|
|
161
|
+
}
|
|
162
|
+
return options.concat ? lines.join("\n") : lines;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function renderFile(filePath, options, callback) {
|
|
166
|
+
var width = options.size.width;
|
|
167
|
+
var height = options.size.height;
|
|
168
|
+
var args = [
|
|
169
|
+
"-hide_banner",
|
|
170
|
+
"-loglevel",
|
|
171
|
+
"error",
|
|
172
|
+
"-i",
|
|
173
|
+
filePath,
|
|
174
|
+
"-vf",
|
|
175
|
+
buildFilter(width, height, options.preserveAspectRatio),
|
|
176
|
+
"-frames:v",
|
|
177
|
+
"1",
|
|
178
|
+
"-f",
|
|
179
|
+
"rawvideo",
|
|
180
|
+
"-pix_fmt",
|
|
181
|
+
"gray",
|
|
182
|
+
"-"
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
childProcess.execFile("ffmpeg", args, {
|
|
186
|
+
encoding: "buffer",
|
|
187
|
+
maxBuffer: width * height + 4096,
|
|
188
|
+
timeout: options.timeoutMs
|
|
189
|
+
}, function (err, stdout, stderr) {
|
|
190
|
+
if (err) {
|
|
191
|
+
var detail = stderr && stderr.length ? String(stderr).trim() : err.message;
|
|
192
|
+
callback(new Error("image-to-ascii failed via ffmpeg: " + detail));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (!stdout || stdout.length < width * height) {
|
|
196
|
+
callback(new Error("image-to-ascii decoded too few pixels for " + width + "x" + height));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
var matrix = matrixFromRaw(stdout, width, height);
|
|
200
|
+
if (!options.stringify) {
|
|
201
|
+
callback(null, matrix);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (options.stringifyFn) {
|
|
205
|
+
try {
|
|
206
|
+
callback(null, options.stringifyFn(matrix, options));
|
|
207
|
+
} catch (stringifyErr) {
|
|
208
|
+
callback(stringifyErr);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
callback(null, stringifyMatrix(matrix, options));
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function imageToAscii(source, options, callback) {
|
|
217
|
+
if (typeof options === "function") {
|
|
218
|
+
callback = options;
|
|
219
|
+
options = {};
|
|
220
|
+
}
|
|
221
|
+
if (typeof callback !== "function") {
|
|
222
|
+
return new Promise(function (resolve, reject) {
|
|
223
|
+
imageToAscii(source, options || {}, function (err, converted) {
|
|
224
|
+
if (err) reject(err);
|
|
225
|
+
else resolve(converted);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var normalized = normalizeOptions(options || {});
|
|
231
|
+
sourceToFile(source, function (sourceErr, filePath, cleanup) {
|
|
232
|
+
if (sourceErr) {
|
|
233
|
+
callback(sourceErr);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
renderFile(filePath, normalized, function (renderErr, converted) {
|
|
237
|
+
if (cleanup) {
|
|
238
|
+
fs.unlink(filePath, function () {});
|
|
239
|
+
}
|
|
240
|
+
callback(renderErr, converted);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
imageToAscii.defaults = {
|
|
246
|
+
size_options: {
|
|
247
|
+
px_size: { width: 1 }
|
|
248
|
+
},
|
|
249
|
+
stringify: true,
|
|
250
|
+
concat: true,
|
|
251
|
+
size: {
|
|
252
|
+
height: "100%"
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
module.exports = imageToAscii;
|
|
257
|
+
module.exports.default = imageToAscii;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
declare namespace imageToAscii {
|
|
2
|
+
interface Size {
|
|
3
|
+
width?: number | string;
|
|
4
|
+
height?: number | string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface SizeOptions {
|
|
8
|
+
screen_size?: {
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
12
|
+
preserve_aspect_ratio?: boolean;
|
|
13
|
+
fit_screen?: boolean;
|
|
14
|
+
px_size?: {
|
|
15
|
+
width?: number;
|
|
16
|
+
height?: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Options {
|
|
21
|
+
pxWidth?: number;
|
|
22
|
+
size?: Size;
|
|
23
|
+
size_options?: SizeOptions;
|
|
24
|
+
stringify?: boolean;
|
|
25
|
+
concat?: boolean;
|
|
26
|
+
pixels?: string | string[];
|
|
27
|
+
reverse?: boolean;
|
|
28
|
+
colored?: boolean;
|
|
29
|
+
bg?: boolean;
|
|
30
|
+
fg?: boolean;
|
|
31
|
+
white_bg?: boolean;
|
|
32
|
+
px_background?: { r: number; g: number; b: number };
|
|
33
|
+
image_type?: string;
|
|
34
|
+
timeout?: number;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
stringify_fn?: (pixels: unknown, options: Options) => unknown;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type Callback = (err: Error | null, converted?: unknown) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare function imageToAscii(
|
|
43
|
+
source: string | Buffer,
|
|
44
|
+
options: imageToAscii.Options | imageToAscii.Callback,
|
|
45
|
+
callback?: imageToAscii.Callback,
|
|
46
|
+
): void | Promise<unknown>;
|
|
47
|
+
|
|
48
|
+
export = imageToAscii;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "image-to-ascii",
|
|
3
|
+
"version": "3.3.0-omnius.1",
|
|
4
|
+
"description": "Omnius bundled image-to-ascii compatibility renderer without the legacy lwip native dependency chain.",
|
|
5
|
+
"main": "index.cjs",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"image-to-ascii": "bin/image-to-ascii.cjs"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./index.d.ts",
|
|
13
|
+
"require": "./index.cjs",
|
|
14
|
+
"default": "./index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22.0.0"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {}
|
|
22
|
+
}
|