omnius 1.0.103 → 1.0.105
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/index.js +502 -137
- package/node_modules/image-to-ascii/index.cjs +65 -14
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/vendor/image-to-ascii/index.cjs +65 -14
|
@@ -19,6 +19,33 @@ function clamp(value, min, max) {
|
|
|
19
19
|
return Math.max(min, Math.min(max, n));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function clampByte(value, fallback) {
|
|
23
|
+
var n = Number(value);
|
|
24
|
+
if (!Number.isFinite(n)) return fallback;
|
|
25
|
+
return clamp(n, 0, 255);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeRgb(value, fallback) {
|
|
29
|
+
if (!isObject(value)) return fallback || null;
|
|
30
|
+
return {
|
|
31
|
+
r: clampByte(value.r, fallback ? fallback.r : 0),
|
|
32
|
+
g: clampByte(value.g, fallback ? fallback.g : 0),
|
|
33
|
+
b: clampByte(value.b, fallback ? fallback.b : 0)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function rgbToFfmpegColor(rgb) {
|
|
38
|
+
if (!rgb) return "black";
|
|
39
|
+
function hex(value) {
|
|
40
|
+
return clampByte(value, 0).toString(16).padStart(2, "0");
|
|
41
|
+
}
|
|
42
|
+
return "0x" + hex(rgb.r) + hex(rgb.g) + hex(rgb.b);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function luminance(r, g, b) {
|
|
46
|
+
return clampByte(Math.round((0.2126 * r) + (0.7152 * g) + (0.0722 * b)), 0);
|
|
47
|
+
}
|
|
48
|
+
|
|
22
49
|
function percentOrNumber(value, basis, fallback) {
|
|
23
50
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
24
51
|
if (typeof value === "string") {
|
|
@@ -53,9 +80,14 @@ function normalizeOptions(options) {
|
|
|
53
80
|
if (Array.isArray(pixels)) pixels = pixels.join("");
|
|
54
81
|
if (typeof pixels !== "string" || pixels.length < 2) pixels = DEFAULT_PIXELS;
|
|
55
82
|
if (options.reverse === true) pixels = pixels.split("").reverse().join("");
|
|
83
|
+
var pxBackground = null;
|
|
84
|
+
if (options.white_bg === true) pxBackground = { r: 255, g: 255, b: 255 };
|
|
85
|
+
if (isObject(options.px_background)) pxBackground = normalizeRgb(options.px_background, pxBackground);
|
|
56
86
|
return {
|
|
57
87
|
pixels: pixels,
|
|
58
88
|
colored: options.colored === true,
|
|
89
|
+
colorBackground: options.bg === true,
|
|
90
|
+
pxBackground: pxBackground,
|
|
59
91
|
concat: options.concat !== false,
|
|
60
92
|
stringify: options.stringify !== false,
|
|
61
93
|
timeoutMs: clamp(options.timeoutMs || options.timeout || 5000, 500, 60000),
|
|
@@ -117,24 +149,38 @@ function sourceToFile(source, callback) {
|
|
|
117
149
|
callback(null, source, false);
|
|
118
150
|
}
|
|
119
151
|
|
|
120
|
-
function buildFilter(width, height, preserveAspectRatio) {
|
|
152
|
+
function buildFilter(width, height, preserveAspectRatio, pxBackground) {
|
|
121
153
|
if (preserveAspectRatio) {
|
|
154
|
+
var padColor = rgbToFfmpegColor(pxBackground);
|
|
122
155
|
return [
|
|
123
156
|
"scale=" + width + ":" + height + ":force_original_aspect_ratio=decrease",
|
|
124
|
-
"pad=" + width + ":" + height + ":(ow-iw)/2:(oh-ih)/2:color=
|
|
125
|
-
"format=
|
|
157
|
+
"pad=" + width + ":" + height + ":(ow-iw)/2:(oh-ih)/2:color=" + padColor,
|
|
158
|
+
"format=rgba"
|
|
126
159
|
].join(",");
|
|
127
160
|
}
|
|
128
|
-
return "scale=" + width + ":" + height + ",format=
|
|
161
|
+
return "scale=" + width + ":" + height + ",format=rgba";
|
|
129
162
|
}
|
|
130
163
|
|
|
131
|
-
function matrixFromRaw(raw, width, height) {
|
|
164
|
+
function matrixFromRaw(raw, width, height, pxBackground) {
|
|
132
165
|
var matrix = [];
|
|
133
166
|
for (var y = 0; y < height; y++) {
|
|
134
167
|
var row = [];
|
|
135
168
|
for (var x = 0; x < width; x++) {
|
|
136
|
-
var
|
|
137
|
-
|
|
169
|
+
var offset = ((y * width) + x) * 4;
|
|
170
|
+
var r = raw[offset] || 0;
|
|
171
|
+
var g = raw[offset + 1] || 0;
|
|
172
|
+
var b = raw[offset + 2] || 0;
|
|
173
|
+
var a = raw[offset + 3];
|
|
174
|
+
if (a == null) a = 255;
|
|
175
|
+
if (pxBackground && a < 255) {
|
|
176
|
+
var alpha = a / 255;
|
|
177
|
+
r = Math.round((r * alpha) + (pxBackground.r * (1 - alpha)));
|
|
178
|
+
g = Math.round((g * alpha) + (pxBackground.g * (1 - alpha)));
|
|
179
|
+
b = Math.round((b * alpha) + (pxBackground.b * (1 - alpha)));
|
|
180
|
+
a = 255;
|
|
181
|
+
}
|
|
182
|
+
var value = luminance(r, g, b);
|
|
183
|
+
row.push({ r: r, g: g, b: b, a: a, value: value });
|
|
138
184
|
}
|
|
139
185
|
matrix.push(row);
|
|
140
186
|
}
|
|
@@ -148,11 +194,16 @@ function stringifyMatrix(matrix, options) {
|
|
|
148
194
|
for (var y = 0; y < matrix.length; y++) {
|
|
149
195
|
var line = "";
|
|
150
196
|
for (var x = 0; x < matrix[y].length; x++) {
|
|
151
|
-
var
|
|
197
|
+
var pixel = matrix[y][x] || {};
|
|
198
|
+
var value = pixel.value || 0;
|
|
152
199
|
var idx = Math.round((value / 255) * maxIdx);
|
|
153
200
|
var ch = pixels[idx] || " ";
|
|
154
201
|
if (options.colored) {
|
|
155
|
-
|
|
202
|
+
var r = pixel.r == null ? value : pixel.r;
|
|
203
|
+
var g = pixel.g == null ? value : pixel.g;
|
|
204
|
+
var b = pixel.b == null ? value : pixel.b;
|
|
205
|
+
var mode = options.colorBackground ? "48" : "38";
|
|
206
|
+
line += "\x1b[" + mode + ";2;" + r + ";" + g + ";" + b + "m" + ch + "\x1b[0m";
|
|
156
207
|
} else {
|
|
157
208
|
line += ch;
|
|
158
209
|
}
|
|
@@ -172,19 +223,19 @@ function renderFile(filePath, options, callback) {
|
|
|
172
223
|
"-i",
|
|
173
224
|
filePath,
|
|
174
225
|
"-vf",
|
|
175
|
-
buildFilter(width, height, options.preserveAspectRatio),
|
|
226
|
+
buildFilter(width, height, options.preserveAspectRatio, options.pxBackground),
|
|
176
227
|
"-frames:v",
|
|
177
228
|
"1",
|
|
178
229
|
"-f",
|
|
179
230
|
"rawvideo",
|
|
180
231
|
"-pix_fmt",
|
|
181
|
-
"
|
|
232
|
+
"rgba",
|
|
182
233
|
"-"
|
|
183
234
|
];
|
|
184
235
|
|
|
185
236
|
childProcess.execFile("ffmpeg", args, {
|
|
186
237
|
encoding: "buffer",
|
|
187
|
-
maxBuffer: width * height + 4096,
|
|
238
|
+
maxBuffer: (width * height * 4) + 4096,
|
|
188
239
|
timeout: options.timeoutMs
|
|
189
240
|
}, function (err, stdout, stderr) {
|
|
190
241
|
if (err) {
|
|
@@ -192,11 +243,11 @@ function renderFile(filePath, options, callback) {
|
|
|
192
243
|
callback(new Error("image-to-ascii failed via ffmpeg: " + detail));
|
|
193
244
|
return;
|
|
194
245
|
}
|
|
195
|
-
if (!stdout || stdout.length < width * height) {
|
|
246
|
+
if (!stdout || stdout.length < width * height * 4) {
|
|
196
247
|
callback(new Error("image-to-ascii decoded too few pixels for " + width + "x" + height));
|
|
197
248
|
return;
|
|
198
249
|
}
|
|
199
|
-
var matrix = matrixFromRaw(stdout, width, height);
|
|
250
|
+
var matrix = matrixFromRaw(stdout, width, height, options.pxBackground);
|
|
200
251
|
if (!options.stringify) {
|
|
201
252
|
callback(null, matrix);
|
|
202
253
|
return;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.105",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.105",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED
|
@@ -19,6 +19,33 @@ function clamp(value, min, max) {
|
|
|
19
19
|
return Math.max(min, Math.min(max, n));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function clampByte(value, fallback) {
|
|
23
|
+
var n = Number(value);
|
|
24
|
+
if (!Number.isFinite(n)) return fallback;
|
|
25
|
+
return clamp(n, 0, 255);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeRgb(value, fallback) {
|
|
29
|
+
if (!isObject(value)) return fallback || null;
|
|
30
|
+
return {
|
|
31
|
+
r: clampByte(value.r, fallback ? fallback.r : 0),
|
|
32
|
+
g: clampByte(value.g, fallback ? fallback.g : 0),
|
|
33
|
+
b: clampByte(value.b, fallback ? fallback.b : 0)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function rgbToFfmpegColor(rgb) {
|
|
38
|
+
if (!rgb) return "black";
|
|
39
|
+
function hex(value) {
|
|
40
|
+
return clampByte(value, 0).toString(16).padStart(2, "0");
|
|
41
|
+
}
|
|
42
|
+
return "0x" + hex(rgb.r) + hex(rgb.g) + hex(rgb.b);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function luminance(r, g, b) {
|
|
46
|
+
return clampByte(Math.round((0.2126 * r) + (0.7152 * g) + (0.0722 * b)), 0);
|
|
47
|
+
}
|
|
48
|
+
|
|
22
49
|
function percentOrNumber(value, basis, fallback) {
|
|
23
50
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
24
51
|
if (typeof value === "string") {
|
|
@@ -53,9 +80,14 @@ function normalizeOptions(options) {
|
|
|
53
80
|
if (Array.isArray(pixels)) pixels = pixels.join("");
|
|
54
81
|
if (typeof pixels !== "string" || pixels.length < 2) pixels = DEFAULT_PIXELS;
|
|
55
82
|
if (options.reverse === true) pixels = pixels.split("").reverse().join("");
|
|
83
|
+
var pxBackground = null;
|
|
84
|
+
if (options.white_bg === true) pxBackground = { r: 255, g: 255, b: 255 };
|
|
85
|
+
if (isObject(options.px_background)) pxBackground = normalizeRgb(options.px_background, pxBackground);
|
|
56
86
|
return {
|
|
57
87
|
pixels: pixels,
|
|
58
88
|
colored: options.colored === true,
|
|
89
|
+
colorBackground: options.bg === true,
|
|
90
|
+
pxBackground: pxBackground,
|
|
59
91
|
concat: options.concat !== false,
|
|
60
92
|
stringify: options.stringify !== false,
|
|
61
93
|
timeoutMs: clamp(options.timeoutMs || options.timeout || 5000, 500, 60000),
|
|
@@ -117,24 +149,38 @@ function sourceToFile(source, callback) {
|
|
|
117
149
|
callback(null, source, false);
|
|
118
150
|
}
|
|
119
151
|
|
|
120
|
-
function buildFilter(width, height, preserveAspectRatio) {
|
|
152
|
+
function buildFilter(width, height, preserveAspectRatio, pxBackground) {
|
|
121
153
|
if (preserveAspectRatio) {
|
|
154
|
+
var padColor = rgbToFfmpegColor(pxBackground);
|
|
122
155
|
return [
|
|
123
156
|
"scale=" + width + ":" + height + ":force_original_aspect_ratio=decrease",
|
|
124
|
-
"pad=" + width + ":" + height + ":(ow-iw)/2:(oh-ih)/2:color=
|
|
125
|
-
"format=
|
|
157
|
+
"pad=" + width + ":" + height + ":(ow-iw)/2:(oh-ih)/2:color=" + padColor,
|
|
158
|
+
"format=rgba"
|
|
126
159
|
].join(",");
|
|
127
160
|
}
|
|
128
|
-
return "scale=" + width + ":" + height + ",format=
|
|
161
|
+
return "scale=" + width + ":" + height + ",format=rgba";
|
|
129
162
|
}
|
|
130
163
|
|
|
131
|
-
function matrixFromRaw(raw, width, height) {
|
|
164
|
+
function matrixFromRaw(raw, width, height, pxBackground) {
|
|
132
165
|
var matrix = [];
|
|
133
166
|
for (var y = 0; y < height; y++) {
|
|
134
167
|
var row = [];
|
|
135
168
|
for (var x = 0; x < width; x++) {
|
|
136
|
-
var
|
|
137
|
-
|
|
169
|
+
var offset = ((y * width) + x) * 4;
|
|
170
|
+
var r = raw[offset] || 0;
|
|
171
|
+
var g = raw[offset + 1] || 0;
|
|
172
|
+
var b = raw[offset + 2] || 0;
|
|
173
|
+
var a = raw[offset + 3];
|
|
174
|
+
if (a == null) a = 255;
|
|
175
|
+
if (pxBackground && a < 255) {
|
|
176
|
+
var alpha = a / 255;
|
|
177
|
+
r = Math.round((r * alpha) + (pxBackground.r * (1 - alpha)));
|
|
178
|
+
g = Math.round((g * alpha) + (pxBackground.g * (1 - alpha)));
|
|
179
|
+
b = Math.round((b * alpha) + (pxBackground.b * (1 - alpha)));
|
|
180
|
+
a = 255;
|
|
181
|
+
}
|
|
182
|
+
var value = luminance(r, g, b);
|
|
183
|
+
row.push({ r: r, g: g, b: b, a: a, value: value });
|
|
138
184
|
}
|
|
139
185
|
matrix.push(row);
|
|
140
186
|
}
|
|
@@ -148,11 +194,16 @@ function stringifyMatrix(matrix, options) {
|
|
|
148
194
|
for (var y = 0; y < matrix.length; y++) {
|
|
149
195
|
var line = "";
|
|
150
196
|
for (var x = 0; x < matrix[y].length; x++) {
|
|
151
|
-
var
|
|
197
|
+
var pixel = matrix[y][x] || {};
|
|
198
|
+
var value = pixel.value || 0;
|
|
152
199
|
var idx = Math.round((value / 255) * maxIdx);
|
|
153
200
|
var ch = pixels[idx] || " ";
|
|
154
201
|
if (options.colored) {
|
|
155
|
-
|
|
202
|
+
var r = pixel.r == null ? value : pixel.r;
|
|
203
|
+
var g = pixel.g == null ? value : pixel.g;
|
|
204
|
+
var b = pixel.b == null ? value : pixel.b;
|
|
205
|
+
var mode = options.colorBackground ? "48" : "38";
|
|
206
|
+
line += "\x1b[" + mode + ";2;" + r + ";" + g + ";" + b + "m" + ch + "\x1b[0m";
|
|
156
207
|
} else {
|
|
157
208
|
line += ch;
|
|
158
209
|
}
|
|
@@ -172,19 +223,19 @@ function renderFile(filePath, options, callback) {
|
|
|
172
223
|
"-i",
|
|
173
224
|
filePath,
|
|
174
225
|
"-vf",
|
|
175
|
-
buildFilter(width, height, options.preserveAspectRatio),
|
|
226
|
+
buildFilter(width, height, options.preserveAspectRatio, options.pxBackground),
|
|
176
227
|
"-frames:v",
|
|
177
228
|
"1",
|
|
178
229
|
"-f",
|
|
179
230
|
"rawvideo",
|
|
180
231
|
"-pix_fmt",
|
|
181
|
-
"
|
|
232
|
+
"rgba",
|
|
182
233
|
"-"
|
|
183
234
|
];
|
|
184
235
|
|
|
185
236
|
childProcess.execFile("ffmpeg", args, {
|
|
186
237
|
encoding: "buffer",
|
|
187
|
-
maxBuffer: width * height + 4096,
|
|
238
|
+
maxBuffer: (width * height * 4) + 4096,
|
|
188
239
|
timeout: options.timeoutMs
|
|
189
240
|
}, function (err, stdout, stderr) {
|
|
190
241
|
if (err) {
|
|
@@ -192,11 +243,11 @@ function renderFile(filePath, options, callback) {
|
|
|
192
243
|
callback(new Error("image-to-ascii failed via ffmpeg: " + detail));
|
|
193
244
|
return;
|
|
194
245
|
}
|
|
195
|
-
if (!stdout || stdout.length < width * height) {
|
|
246
|
+
if (!stdout || stdout.length < width * height * 4) {
|
|
196
247
|
callback(new Error("image-to-ascii decoded too few pixels for " + width + "x" + height));
|
|
197
248
|
return;
|
|
198
249
|
}
|
|
199
|
-
var matrix = matrixFromRaw(stdout, width, height);
|
|
250
|
+
var matrix = matrixFromRaw(stdout, width, height, options.pxBackground);
|
|
200
251
|
if (!options.stringify) {
|
|
201
252
|
callback(null, matrix);
|
|
202
253
|
return;
|