nodejs-audio-visualizer 4.2.4 → 4.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/LICENSE +21 -21
- package/README.md +70 -70
- package/dist/audio.d.ts +12 -12
- package/dist/audio.js +120 -120
- package/dist/beats.d.ts +19 -19
- package/dist/beats.js +43 -43
- package/dist/bpmEncoder.d.ts +14 -14
- package/dist/bpmEncoder.js +97 -97
- package/dist/config.d.ts +54 -54
- package/dist/config.js +299 -299
- package/dist/dsp.d.ts +16 -16
- package/dist/dsp.js +76 -76
- package/dist/highlight.d.ts +32 -32
- package/dist/highlight.js +325 -325
- package/dist/image.d.ts +79 -79
- package/dist/image.js +458 -458
- package/dist/index.d.ts +67 -67
- package/dist/index.js +470 -466
- package/dist/index.js.map +1 -1
- package/dist/video.d.ts +67 -64
- package/dist/video.js +317 -293
- package/dist/video.js.map +1 -1
- package/dist/waitForEventLoop.d.ts +1 -1
- package/dist/waitForEventLoop.js +5 -5
- package/package.json +61 -61
- package/src/audio.ts +120 -120
- package/src/beats.ts +68 -68
- package/src/bpmEncoder.ts +97 -97
- package/src/config.ts +382 -382
- package/src/dsp.ts +95 -95
- package/src/highlight.ts +284 -284
- package/src/image.ts +602 -602
- package/src/index.ts +610 -606
- package/src/tests/audio.test.ts +96 -96
- package/src/tests/config.test.ts +406 -406
- package/src/tests/dsp.test.ts +24 -24
- package/src/tests/highlight.test.ts +178 -178
- package/src/tests/image.test.ts +222 -222
- package/src/tests/index.test.ts +63 -63
- package/src/tests/video.test.ts +71 -71
- package/src/typings.d.ts +6 -6
- package/src/video.ts +403 -375
- package/src/waitForEventLoop.ts +2 -2
package/dist/image.js
CHANGED
|
@@ -1,459 +1,459 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
-
};
|
|
52
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
-
var bmp_js_1 = require("bmp-js");
|
|
54
|
-
var jimp_1 = __importDefault(require("jimp"));
|
|
55
|
-
exports.mixValues = function (value1, value1Opacity, value2) {
|
|
56
|
-
return Math.round(value2 * (1 - value1Opacity) + value1 * value1Opacity);
|
|
57
|
-
};
|
|
58
|
-
exports.mixColors = function (_a) {
|
|
59
|
-
var color = _a.color, colorOpacity = _a.colorOpacity, backgroundColor = _a.backgroundColor;
|
|
60
|
-
return {
|
|
61
|
-
red: exports.mixValues(color.red, colorOpacity, backgroundColor.red),
|
|
62
|
-
green: exports.mixValues(color.green, colorOpacity, backgroundColor.green),
|
|
63
|
-
blue: exports.mixValues(color.blue, colorOpacity, backgroundColor.blue),
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
var getRectPixelColor = function (params) {
|
|
67
|
-
var imageDstBuffer = params.imageDstBuffer, pixelIndex = params.pixelIndex, color = params.color, opacity = params.opacity;
|
|
68
|
-
if (opacity === 1) {
|
|
69
|
-
return color;
|
|
70
|
-
}
|
|
71
|
-
var backgroundPixelColor = {
|
|
72
|
-
blue: imageDstBuffer.data[pixelIndex],
|
|
73
|
-
green: imageDstBuffer.data[pixelIndex + 1],
|
|
74
|
-
red: imageDstBuffer.data[pixelIndex + 2],
|
|
75
|
-
};
|
|
76
|
-
var resultColor = exports.mixColors({
|
|
77
|
-
color: color,
|
|
78
|
-
colorOpacity: opacity,
|
|
79
|
-
backgroundColor: backgroundPixelColor,
|
|
80
|
-
});
|
|
81
|
-
return resultColor;
|
|
82
|
-
};
|
|
83
|
-
exports.drawRect = function (_a) {
|
|
84
|
-
var imageDstBuffer = _a.imageDstBuffer, position = _a.position, size = _a.size, color = _a.color, opacity = _a.opacity;
|
|
85
|
-
for (var currY = position.y; currY < position.y + size.height; currY++) {
|
|
86
|
-
for (var currX = position.x; currX < position.x + size.width; currX++) {
|
|
87
|
-
var pixelIndex = imageDstBuffer.shiftPos + currY * imageDstBuffer.rowBytes + currX * 3;
|
|
88
|
-
var pixelColor = getRectPixelColor({
|
|
89
|
-
imageDstBuffer: imageDstBuffer,
|
|
90
|
-
pixelIndex: pixelIndex,
|
|
91
|
-
color: color,
|
|
92
|
-
opacity: opacity,
|
|
93
|
-
});
|
|
94
|
-
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
95
|
-
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
96
|
-
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
var buildQuadEdgeTable = function (points) {
|
|
101
|
-
var edges = [];
|
|
102
|
-
for (var i = 0; i < points.length; i++) {
|
|
103
|
-
var p1 = points[i];
|
|
104
|
-
var p2 = points[(i + 1) % points.length];
|
|
105
|
-
if (p1.y === p2.y)
|
|
106
|
-
continue; // Skip horizontal edges
|
|
107
|
-
var yMin = Math.min(p1.y, p2.y);
|
|
108
|
-
var yMax = Math.max(p1.y, p2.y);
|
|
109
|
-
var x = p1.y < p2.y ? p1.x : p2.x;
|
|
110
|
-
var dx = (p2.x - p1.x) / (p2.y - p1.y);
|
|
111
|
-
edges.push({ yMin: yMin, yMax: yMax, x: x, dx: dx });
|
|
112
|
-
}
|
|
113
|
-
return edges.sort(function (a, b) { return a.yMin - b.yMin; });
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
|
-
* Fills a quadrilateral (4-sided polygon) using scan-line algorithm
|
|
117
|
-
* Only the outer edges are anti-aliased
|
|
118
|
-
*/
|
|
119
|
-
exports.fillRect = function (_a) {
|
|
120
|
-
var imageDstBuffer = _a.imageDstBuffer, points = _a.points, color = _a.color, opacity = _a.opacity;
|
|
121
|
-
// Build edge table from all 4 vertices
|
|
122
|
-
var edgeTable = buildQuadEdgeTable(points);
|
|
123
|
-
if (edgeTable.length === 0)
|
|
124
|
-
return;
|
|
125
|
-
// Find the bounding box
|
|
126
|
-
var yMin = Math.min.apply(Math, points.map(function (p) { return p.y; }));
|
|
127
|
-
var yMax = Math.max.apply(Math, points.map(function (p) { return p.y; }));
|
|
128
|
-
// Active Edge Table for scan line algorithm
|
|
129
|
-
var activeEdges = [];
|
|
130
|
-
// Scan line algorithm: process each horizontal line
|
|
131
|
-
for (var y = Math.floor(yMin); y <= Math.ceil(yMax); y++) {
|
|
132
|
-
// Add edges that start at this scanline to AET
|
|
133
|
-
for (var _i = 0, edgeTable_1 = edgeTable; _i < edgeTable_1.length; _i++) {
|
|
134
|
-
var edge = edgeTable_1[_i];
|
|
135
|
-
if (Math.floor(edge.yMin) === y) {
|
|
136
|
-
activeEdges.push(__assign({}, edge));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// Remove edges that end at this scanline from AET
|
|
140
|
-
for (var i = activeEdges.length - 1; i >= 0; i--) {
|
|
141
|
-
if (Math.ceil(activeEdges[i].yMax) <= y) {
|
|
142
|
-
activeEdges.splice(i, 1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// Sort active edges by x coordinate
|
|
146
|
-
activeEdges.sort(function (a, b) { return a.x - b.x; });
|
|
147
|
-
// Fill pixels between pairs of intersections
|
|
148
|
-
for (var i = 0; i < activeEdges.length; i += 2) {
|
|
149
|
-
if (i + 1 < activeEdges.length) {
|
|
150
|
-
var xStart = activeEdges[i].x;
|
|
151
|
-
var xEnd = activeEdges[i + 1].x;
|
|
152
|
-
// Anti-aliased rendering with sub-pixel precision
|
|
153
|
-
var xStartFloor = Math.floor(xStart);
|
|
154
|
-
var xEndCeil = Math.ceil(xEnd);
|
|
155
|
-
for (var x = xStartFloor; x < xEndCeil; x++) {
|
|
156
|
-
var pixelIndex = imageDstBuffer.shiftPos + y * imageDstBuffer.rowBytes + x * 3;
|
|
157
|
-
// Calculate coverage for anti-aliasing
|
|
158
|
-
var coverage = 1.0;
|
|
159
|
-
if (x === xStartFloor) {
|
|
160
|
-
// Left edge pixel - calculate fractional coverage
|
|
161
|
-
coverage = Math.min(1.0, 1.0 - (xStart - xStartFloor));
|
|
162
|
-
}
|
|
163
|
-
else if (x === xEndCeil - 1) {
|
|
164
|
-
// Right edge pixel - calculate fractional coverage
|
|
165
|
-
coverage = Math.min(1.0, xEnd - Math.floor(xEnd));
|
|
166
|
-
}
|
|
167
|
-
// Apply coverage to opacity for smooth edges
|
|
168
|
-
var effectiveOpacity = opacity * coverage;
|
|
169
|
-
var pixelColor = getRectPixelColor({
|
|
170
|
-
imageDstBuffer: imageDstBuffer,
|
|
171
|
-
pixelIndex: pixelIndex,
|
|
172
|
-
color: color,
|
|
173
|
-
opacity: effectiveOpacity,
|
|
174
|
-
});
|
|
175
|
-
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
176
|
-
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
177
|
-
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// Update x coordinates for next scanline (x' = x + dx)
|
|
182
|
-
for (var _b = 0, activeEdges_1 = activeEdges; _b < activeEdges_1.length; _b++) {
|
|
183
|
-
var edge = activeEdges_1[_b];
|
|
184
|
-
edge.x += edge.dx;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
var getRectY = function (rotation, top, height, rectHeight) {
|
|
189
|
-
switch (rotation) {
|
|
190
|
-
case 'up':
|
|
191
|
-
return top + height - rectHeight;
|
|
192
|
-
case 'mirror':
|
|
193
|
-
return top + Math.trunc((height - rectHeight) / 2);
|
|
194
|
-
default:
|
|
195
|
-
return top;
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
var minRectHeight = 2;
|
|
199
|
-
var getRectHeight = function (height, spectrumValue) {
|
|
200
|
-
var rectHeight = Math.trunc(height * spectrumValue);
|
|
201
|
-
if (rectHeight < minRectHeight) {
|
|
202
|
-
return minRectHeight;
|
|
203
|
-
}
|
|
204
|
-
return rectHeight;
|
|
205
|
-
};
|
|
206
|
-
var drawSpectrum = function (_a) {
|
|
207
|
-
var imageDstBuffer = _a.imageDstBuffer, spectrum = _a.spectrum, size = _a.size, position = _a.position, rotation = _a.rotation, margin = _a.margin, color = _a.color, opacity = _a.opacity;
|
|
208
|
-
var busWidth = Math.trunc(size.width / spectrum.length);
|
|
209
|
-
var left = Math.trunc(position.x);
|
|
210
|
-
var top = Math.trunc(position.y);
|
|
211
|
-
var height = Math.trunc(size.height);
|
|
212
|
-
for (var spectrumX = 0; spectrumX < spectrum.length; spectrumX++) {
|
|
213
|
-
var spectrumValue = spectrum[spectrumX];
|
|
214
|
-
if ((spectrumValue > 1) || (spectrumValue < 0)) {
|
|
215
|
-
throw new Error('Spectrum values must be in range from 0 to 1');
|
|
216
|
-
}
|
|
217
|
-
var rectX = left + busWidth * spectrumX;
|
|
218
|
-
var rectHeight = getRectHeight(height, spectrumValue);
|
|
219
|
-
var rectY = getRectY(rotation, top, height, rectHeight);
|
|
220
|
-
exports.drawRect({
|
|
221
|
-
imageDstBuffer: imageDstBuffer,
|
|
222
|
-
position: { x: rectX + margin, y: rectY },
|
|
223
|
-
size: { width: busWidth - margin / 2, height: rectHeight },
|
|
224
|
-
color: color,
|
|
225
|
-
opacity: opacity,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
var calcCirclePoint = function (angleRadians, radius) {
|
|
230
|
-
var circleX = radius * Math.cos(angleRadians);
|
|
231
|
-
var circleY = radius * Math.sin(angleRadians);
|
|
232
|
-
return { x: circleX, y: circleY };
|
|
233
|
-
};
|
|
234
|
-
var lerp = function (start, end, t) {
|
|
235
|
-
return start + (end - start) * t;
|
|
236
|
-
};
|
|
237
|
-
var drawPolarSpectrum = function (_a) {
|
|
238
|
-
var imageDstBuffer = _a.imageDstBuffer, spectrum = _a.spectrum, centerX = _a.centerX, centerY = _a.centerY, innerRadius = _a.innerRadius, maxBarLength = _a.maxBarLength, barWidth = _a.barWidth, color = _a.color, opacity = _a.opacity;
|
|
239
|
-
var angleStep = (2 * Math.PI) / spectrum.length;
|
|
240
|
-
var innerLength = innerRadius * 2 * Math.PI;
|
|
241
|
-
var radiansPerPixel = 2 * Math.PI / innerLength;
|
|
242
|
-
var barWidthInRadians = radiansPerPixel * barWidth;
|
|
243
|
-
var spectrumAverage = spectrum.reduce(function (a, b) { return a + b; }, 0) / spectrum.length;
|
|
244
|
-
var scaleFactor = lerp(0.75, 1, spectrumAverage);
|
|
245
|
-
var scaledMaxOuterRadius = (innerRadius + maxBarLength) * scaleFactor;
|
|
246
|
-
var scaledInnerRadius = innerRadius * scaleFactor;
|
|
247
|
-
for (var i = 0; i < spectrum.length; i++) {
|
|
248
|
-
var currentSpectrumValue = spectrum[i] || 0;
|
|
249
|
-
var busRadius = lerp(scaledInnerRadius, scaledMaxOuterRadius, currentSpectrumValue);
|
|
250
|
-
var angle = i * angleStep;
|
|
251
|
-
var angleRadiansStart = angle;
|
|
252
|
-
var angleRadiansEnd = angle + barWidthInRadians;
|
|
253
|
-
var point1 = calcCirclePoint(angleRadiansStart, scaledInnerRadius);
|
|
254
|
-
var point2 = calcCirclePoint(angleRadiansStart, busRadius);
|
|
255
|
-
var point3 = calcCirclePoint(angleRadiansEnd, scaledInnerRadius);
|
|
256
|
-
var point4 = calcCirclePoint(angleRadiansEnd, busRadius);
|
|
257
|
-
exports.fillRect({
|
|
258
|
-
imageDstBuffer: imageDstBuffer,
|
|
259
|
-
points: [
|
|
260
|
-
{ x: centerX + Math.round(point1.x), y: centerY + Math.round(point1.y) },
|
|
261
|
-
{ x: centerX + Math.round(point2.x), y: centerY + Math.round(point2.y) },
|
|
262
|
-
{ x: centerX + Math.round(point4.x), y: centerY + Math.round(point4.y) },
|
|
263
|
-
{ x: centerX + Math.round(point3.x), y: centerY + Math.round(point3.y) },
|
|
264
|
-
],
|
|
265
|
-
color: color,
|
|
266
|
-
opacity: opacity,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
exports.createSpectrumVisualizerFrameGenerator = function () {
|
|
271
|
-
var prevSpectrum = null;
|
|
272
|
-
return function (_a) {
|
|
273
|
-
var backgroundImageBuffer = _a.backgroundImageBuffer, spectrum = _a.spectrum, size = _a.size, position = _a.position, rotation = _a.rotation, margin = _a.margin, color = _a.color, opacity = _a.opacity, spectrumEffect = _a.spectrumEffect;
|
|
274
|
-
var imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
275
|
-
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
276
|
-
var rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
277
|
-
if (spectrumEffect === 'volume') {
|
|
278
|
-
drawSpectrum({
|
|
279
|
-
imageDstBuffer: imageDstBuffer,
|
|
280
|
-
spectrum: spectrum,
|
|
281
|
-
size: size,
|
|
282
|
-
position: { x: position.x + 2, y: position.y + 2 },
|
|
283
|
-
rotation: rotation,
|
|
284
|
-
margin: margin,
|
|
285
|
-
color: rgbSpectrumColor,
|
|
286
|
-
opacity: opacity * 0.5,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
if (spectrumEffect === 'smooth' && prevSpectrum) {
|
|
290
|
-
drawSpectrum({
|
|
291
|
-
imageDstBuffer: imageDstBuffer,
|
|
292
|
-
spectrum: prevSpectrum,
|
|
293
|
-
size: size,
|
|
294
|
-
position: position,
|
|
295
|
-
rotation: rotation,
|
|
296
|
-
margin: margin,
|
|
297
|
-
color: rgbSpectrumColor,
|
|
298
|
-
opacity: opacity * 0.3,
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
drawSpectrum({
|
|
302
|
-
imageDstBuffer: imageDstBuffer,
|
|
303
|
-
spectrum: spectrum,
|
|
304
|
-
size: size,
|
|
305
|
-
position: position,
|
|
306
|
-
rotation: rotation,
|
|
307
|
-
margin: margin,
|
|
308
|
-
color: rgbSpectrumColor,
|
|
309
|
-
opacity: opacity,
|
|
310
|
-
});
|
|
311
|
-
prevSpectrum = spectrum;
|
|
312
|
-
return imageDstBuffer;
|
|
313
|
-
};
|
|
314
|
-
};
|
|
315
|
-
exports.createPolarVisualizerFrameGenerator = function () {
|
|
316
|
-
var prevSpectrum = null;
|
|
317
|
-
return function (_a) {
|
|
318
|
-
var backgroundImageBuffer = _a.backgroundImageBuffer, spectrum = _a.spectrum, centerX = _a.centerX, centerY = _a.centerY, innerRadius = _a.innerRadius, maxBarLength = _a.maxBarLength, barWidth = _a.barWidth, color = _a.color, opacity = _a.opacity, spectrumEffect = _a.spectrumEffect;
|
|
319
|
-
var imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
320
|
-
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
321
|
-
var rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
322
|
-
if (spectrumEffect === 'volume') {
|
|
323
|
-
drawPolarSpectrum({
|
|
324
|
-
imageDstBuffer: imageDstBuffer,
|
|
325
|
-
spectrum: spectrum,
|
|
326
|
-
centerX: centerX + 2,
|
|
327
|
-
centerY: centerY + 2,
|
|
328
|
-
innerRadius: innerRadius,
|
|
329
|
-
maxBarLength: maxBarLength,
|
|
330
|
-
barWidth: barWidth,
|
|
331
|
-
color: rgbSpectrumColor,
|
|
332
|
-
opacity: opacity * 0.5,
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
if (spectrumEffect === 'smooth' && prevSpectrum) {
|
|
336
|
-
drawPolarSpectrum({
|
|
337
|
-
imageDstBuffer: imageDstBuffer,
|
|
338
|
-
spectrum: prevSpectrum,
|
|
339
|
-
centerX: centerX,
|
|
340
|
-
centerY: centerY,
|
|
341
|
-
innerRadius: innerRadius,
|
|
342
|
-
maxBarLength: maxBarLength,
|
|
343
|
-
barWidth: barWidth,
|
|
344
|
-
color: rgbSpectrumColor,
|
|
345
|
-
opacity: opacity * 0.3,
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
drawPolarSpectrum({
|
|
349
|
-
imageDstBuffer: imageDstBuffer,
|
|
350
|
-
spectrum: spectrum,
|
|
351
|
-
centerX: centerX,
|
|
352
|
-
centerY: centerY,
|
|
353
|
-
innerRadius: innerRadius,
|
|
354
|
-
maxBarLength: maxBarLength,
|
|
355
|
-
barWidth: barWidth,
|
|
356
|
-
color: rgbSpectrumColor,
|
|
357
|
-
opacity: opacity,
|
|
358
|
-
});
|
|
359
|
-
prevSpectrum = spectrum;
|
|
360
|
-
return imageDstBuffer;
|
|
361
|
-
};
|
|
362
|
-
};
|
|
363
|
-
exports.convertToBmp = function (filePath, targetWidth, targetHeight) { return __awaiter(void 0, void 0, void 0, function () {
|
|
364
|
-
return __generator(this, function (_a) {
|
|
365
|
-
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(void 0, void 0, void 0, function () {
|
|
366
|
-
var image, sw, sh, isOrientationMismatch, targetAspect, cropW, cropH, cropX, cropY, _a;
|
|
367
|
-
return __generator(this, function (_b) {
|
|
368
|
-
switch (_b.label) {
|
|
369
|
-
case 0:
|
|
370
|
-
_b.trys.push([0, 2, , 3]);
|
|
371
|
-
return [4 /*yield*/, jimp_1.default.read(filePath)];
|
|
372
|
-
case 1:
|
|
373
|
-
image = _b.sent();
|
|
374
|
-
if (targetWidth && targetHeight) {
|
|
375
|
-
sw = image.getWidth();
|
|
376
|
-
sh = image.getHeight();
|
|
377
|
-
isOrientationMismatch = (sw > sh && targetWidth < targetHeight) ||
|
|
378
|
-
(sw < sh && targetWidth > targetHeight);
|
|
379
|
-
if (isOrientationMismatch) {
|
|
380
|
-
targetAspect = targetWidth / targetHeight;
|
|
381
|
-
cropW = void 0, cropH = void 0, cropX = void 0, cropY = void 0;
|
|
382
|
-
if (sw / sh > targetAspect) {
|
|
383
|
-
cropW = Math.round(sh * targetAspect);
|
|
384
|
-
cropH = sh;
|
|
385
|
-
cropX = Math.round((sw - cropW) / 2);
|
|
386
|
-
cropY = 0;
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
cropW = sw;
|
|
390
|
-
cropH = Math.round(sw / targetAspect);
|
|
391
|
-
cropX = 0;
|
|
392
|
-
cropY = Math.round((sh - cropH) / 2);
|
|
393
|
-
}
|
|
394
|
-
image.crop(cropX, cropY, cropW, cropH);
|
|
395
|
-
}
|
|
396
|
-
image.resize(targetWidth, targetHeight);
|
|
397
|
-
}
|
|
398
|
-
image.getBuffer("image/bmp", function (err, value) {
|
|
399
|
-
if (err) {
|
|
400
|
-
reject(err);
|
|
401
|
-
}
|
|
402
|
-
resolve(value);
|
|
403
|
-
});
|
|
404
|
-
return [3 /*break*/, 3];
|
|
405
|
-
case 2:
|
|
406
|
-
_a = _b.sent();
|
|
407
|
-
throw new Error("Cannot procces image file from path: " + filePath);
|
|
408
|
-
case 3: return [2 /*return*/];
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
}); })];
|
|
412
|
-
});
|
|
413
|
-
}); };
|
|
414
|
-
exports.parseImage = function (buffer) { return bmp_js_1.decode(buffer); };
|
|
415
|
-
exports.getImageColor = function (image) {
|
|
416
|
-
var blueSum = 0;
|
|
417
|
-
var greenSum = 0;
|
|
418
|
-
var redSum = 0;
|
|
419
|
-
for (var currY = 0; currY < image.height; currY++) {
|
|
420
|
-
for (var currX = 0; currX < image.width; currX++) {
|
|
421
|
-
var idx = (image.width * currY + currX) << 2;
|
|
422
|
-
blueSum += image.data[idx + 1];
|
|
423
|
-
greenSum += image.data[idx + 2];
|
|
424
|
-
redSum += image.data[idx + 3];
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
var pixelsCount = image.width * image.height;
|
|
428
|
-
return {
|
|
429
|
-
red: ~~(redSum / pixelsCount),
|
|
430
|
-
green: ~~(greenSum / pixelsCount),
|
|
431
|
-
blue: ~~(blueSum / pixelsCount)
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
exports.getVideoFrameColor = function (bgrBuffer, width, height) {
|
|
435
|
-
var blueSum = 0;
|
|
436
|
-
var greenSum = 0;
|
|
437
|
-
var redSum = 0;
|
|
438
|
-
var pixelsCount = width * height;
|
|
439
|
-
for (var i = 0; i < bgrBuffer.length; i += 3) {
|
|
440
|
-
blueSum += bgrBuffer[i];
|
|
441
|
-
greenSum += bgrBuffer[i + 1];
|
|
442
|
-
redSum += bgrBuffer[i + 2];
|
|
443
|
-
}
|
|
444
|
-
return {
|
|
445
|
-
red: ~~(redSum / pixelsCount),
|
|
446
|
-
green: ~~(greenSum / pixelsCount),
|
|
447
|
-
blue: ~~(blueSum / pixelsCount),
|
|
448
|
-
};
|
|
449
|
-
};
|
|
450
|
-
exports.invertColor = function (color) {
|
|
451
|
-
return ({ red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue });
|
|
452
|
-
};
|
|
453
|
-
var hexToRgb = function (hex) {
|
|
454
|
-
var red = parseInt(hex.substring(1, 3), 16);
|
|
455
|
-
var green = parseInt(hex.substring(3, 5), 16);
|
|
456
|
-
var blue = parseInt(hex.substring(5, 7), 16);
|
|
457
|
-
return { red: red, green: green, blue: blue };
|
|
458
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (_) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
var bmp_js_1 = require("bmp-js");
|
|
54
|
+
var jimp_1 = __importDefault(require("jimp"));
|
|
55
|
+
exports.mixValues = function (value1, value1Opacity, value2) {
|
|
56
|
+
return Math.round(value2 * (1 - value1Opacity) + value1 * value1Opacity);
|
|
57
|
+
};
|
|
58
|
+
exports.mixColors = function (_a) {
|
|
59
|
+
var color = _a.color, colorOpacity = _a.colorOpacity, backgroundColor = _a.backgroundColor;
|
|
60
|
+
return {
|
|
61
|
+
red: exports.mixValues(color.red, colorOpacity, backgroundColor.red),
|
|
62
|
+
green: exports.mixValues(color.green, colorOpacity, backgroundColor.green),
|
|
63
|
+
blue: exports.mixValues(color.blue, colorOpacity, backgroundColor.blue),
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
var getRectPixelColor = function (params) {
|
|
67
|
+
var imageDstBuffer = params.imageDstBuffer, pixelIndex = params.pixelIndex, color = params.color, opacity = params.opacity;
|
|
68
|
+
if (opacity === 1) {
|
|
69
|
+
return color;
|
|
70
|
+
}
|
|
71
|
+
var backgroundPixelColor = {
|
|
72
|
+
blue: imageDstBuffer.data[pixelIndex],
|
|
73
|
+
green: imageDstBuffer.data[pixelIndex + 1],
|
|
74
|
+
red: imageDstBuffer.data[pixelIndex + 2],
|
|
75
|
+
};
|
|
76
|
+
var resultColor = exports.mixColors({
|
|
77
|
+
color: color,
|
|
78
|
+
colorOpacity: opacity,
|
|
79
|
+
backgroundColor: backgroundPixelColor,
|
|
80
|
+
});
|
|
81
|
+
return resultColor;
|
|
82
|
+
};
|
|
83
|
+
exports.drawRect = function (_a) {
|
|
84
|
+
var imageDstBuffer = _a.imageDstBuffer, position = _a.position, size = _a.size, color = _a.color, opacity = _a.opacity;
|
|
85
|
+
for (var currY = position.y; currY < position.y + size.height; currY++) {
|
|
86
|
+
for (var currX = position.x; currX < position.x + size.width; currX++) {
|
|
87
|
+
var pixelIndex = imageDstBuffer.shiftPos + currY * imageDstBuffer.rowBytes + currX * 3;
|
|
88
|
+
var pixelColor = getRectPixelColor({
|
|
89
|
+
imageDstBuffer: imageDstBuffer,
|
|
90
|
+
pixelIndex: pixelIndex,
|
|
91
|
+
color: color,
|
|
92
|
+
opacity: opacity,
|
|
93
|
+
});
|
|
94
|
+
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
95
|
+
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
96
|
+
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var buildQuadEdgeTable = function (points) {
|
|
101
|
+
var edges = [];
|
|
102
|
+
for (var i = 0; i < points.length; i++) {
|
|
103
|
+
var p1 = points[i];
|
|
104
|
+
var p2 = points[(i + 1) % points.length];
|
|
105
|
+
if (p1.y === p2.y)
|
|
106
|
+
continue; // Skip horizontal edges
|
|
107
|
+
var yMin = Math.min(p1.y, p2.y);
|
|
108
|
+
var yMax = Math.max(p1.y, p2.y);
|
|
109
|
+
var x = p1.y < p2.y ? p1.x : p2.x;
|
|
110
|
+
var dx = (p2.x - p1.x) / (p2.y - p1.y);
|
|
111
|
+
edges.push({ yMin: yMin, yMax: yMax, x: x, dx: dx });
|
|
112
|
+
}
|
|
113
|
+
return edges.sort(function (a, b) { return a.yMin - b.yMin; });
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Fills a quadrilateral (4-sided polygon) using scan-line algorithm
|
|
117
|
+
* Only the outer edges are anti-aliased
|
|
118
|
+
*/
|
|
119
|
+
exports.fillRect = function (_a) {
|
|
120
|
+
var imageDstBuffer = _a.imageDstBuffer, points = _a.points, color = _a.color, opacity = _a.opacity;
|
|
121
|
+
// Build edge table from all 4 vertices
|
|
122
|
+
var edgeTable = buildQuadEdgeTable(points);
|
|
123
|
+
if (edgeTable.length === 0)
|
|
124
|
+
return;
|
|
125
|
+
// Find the bounding box
|
|
126
|
+
var yMin = Math.min.apply(Math, points.map(function (p) { return p.y; }));
|
|
127
|
+
var yMax = Math.max.apply(Math, points.map(function (p) { return p.y; }));
|
|
128
|
+
// Active Edge Table for scan line algorithm
|
|
129
|
+
var activeEdges = [];
|
|
130
|
+
// Scan line algorithm: process each horizontal line
|
|
131
|
+
for (var y = Math.floor(yMin); y <= Math.ceil(yMax); y++) {
|
|
132
|
+
// Add edges that start at this scanline to AET
|
|
133
|
+
for (var _i = 0, edgeTable_1 = edgeTable; _i < edgeTable_1.length; _i++) {
|
|
134
|
+
var edge = edgeTable_1[_i];
|
|
135
|
+
if (Math.floor(edge.yMin) === y) {
|
|
136
|
+
activeEdges.push(__assign({}, edge));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Remove edges that end at this scanline from AET
|
|
140
|
+
for (var i = activeEdges.length - 1; i >= 0; i--) {
|
|
141
|
+
if (Math.ceil(activeEdges[i].yMax) <= y) {
|
|
142
|
+
activeEdges.splice(i, 1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Sort active edges by x coordinate
|
|
146
|
+
activeEdges.sort(function (a, b) { return a.x - b.x; });
|
|
147
|
+
// Fill pixels between pairs of intersections
|
|
148
|
+
for (var i = 0; i < activeEdges.length; i += 2) {
|
|
149
|
+
if (i + 1 < activeEdges.length) {
|
|
150
|
+
var xStart = activeEdges[i].x;
|
|
151
|
+
var xEnd = activeEdges[i + 1].x;
|
|
152
|
+
// Anti-aliased rendering with sub-pixel precision
|
|
153
|
+
var xStartFloor = Math.floor(xStart);
|
|
154
|
+
var xEndCeil = Math.ceil(xEnd);
|
|
155
|
+
for (var x = xStartFloor; x < xEndCeil; x++) {
|
|
156
|
+
var pixelIndex = imageDstBuffer.shiftPos + y * imageDstBuffer.rowBytes + x * 3;
|
|
157
|
+
// Calculate coverage for anti-aliasing
|
|
158
|
+
var coverage = 1.0;
|
|
159
|
+
if (x === xStartFloor) {
|
|
160
|
+
// Left edge pixel - calculate fractional coverage
|
|
161
|
+
coverage = Math.min(1.0, 1.0 - (xStart - xStartFloor));
|
|
162
|
+
}
|
|
163
|
+
else if (x === xEndCeil - 1) {
|
|
164
|
+
// Right edge pixel - calculate fractional coverage
|
|
165
|
+
coverage = Math.min(1.0, xEnd - Math.floor(xEnd));
|
|
166
|
+
}
|
|
167
|
+
// Apply coverage to opacity for smooth edges
|
|
168
|
+
var effectiveOpacity = opacity * coverage;
|
|
169
|
+
var pixelColor = getRectPixelColor({
|
|
170
|
+
imageDstBuffer: imageDstBuffer,
|
|
171
|
+
pixelIndex: pixelIndex,
|
|
172
|
+
color: color,
|
|
173
|
+
opacity: effectiveOpacity,
|
|
174
|
+
});
|
|
175
|
+
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
176
|
+
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
177
|
+
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Update x coordinates for next scanline (x' = x + dx)
|
|
182
|
+
for (var _b = 0, activeEdges_1 = activeEdges; _b < activeEdges_1.length; _b++) {
|
|
183
|
+
var edge = activeEdges_1[_b];
|
|
184
|
+
edge.x += edge.dx;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
var getRectY = function (rotation, top, height, rectHeight) {
|
|
189
|
+
switch (rotation) {
|
|
190
|
+
case 'up':
|
|
191
|
+
return top + height - rectHeight;
|
|
192
|
+
case 'mirror':
|
|
193
|
+
return top + Math.trunc((height - rectHeight) / 2);
|
|
194
|
+
default:
|
|
195
|
+
return top;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var minRectHeight = 2;
|
|
199
|
+
var getRectHeight = function (height, spectrumValue) {
|
|
200
|
+
var rectHeight = Math.trunc(height * spectrumValue);
|
|
201
|
+
if (rectHeight < minRectHeight) {
|
|
202
|
+
return minRectHeight;
|
|
203
|
+
}
|
|
204
|
+
return rectHeight;
|
|
205
|
+
};
|
|
206
|
+
var drawSpectrum = function (_a) {
|
|
207
|
+
var imageDstBuffer = _a.imageDstBuffer, spectrum = _a.spectrum, size = _a.size, position = _a.position, rotation = _a.rotation, margin = _a.margin, color = _a.color, opacity = _a.opacity;
|
|
208
|
+
var busWidth = Math.trunc(size.width / spectrum.length);
|
|
209
|
+
var left = Math.trunc(position.x);
|
|
210
|
+
var top = Math.trunc(position.y);
|
|
211
|
+
var height = Math.trunc(size.height);
|
|
212
|
+
for (var spectrumX = 0; spectrumX < spectrum.length; spectrumX++) {
|
|
213
|
+
var spectrumValue = spectrum[spectrumX];
|
|
214
|
+
if ((spectrumValue > 1) || (spectrumValue < 0)) {
|
|
215
|
+
throw new Error('Spectrum values must be in range from 0 to 1');
|
|
216
|
+
}
|
|
217
|
+
var rectX = left + busWidth * spectrumX;
|
|
218
|
+
var rectHeight = getRectHeight(height, spectrumValue);
|
|
219
|
+
var rectY = getRectY(rotation, top, height, rectHeight);
|
|
220
|
+
exports.drawRect({
|
|
221
|
+
imageDstBuffer: imageDstBuffer,
|
|
222
|
+
position: { x: rectX + margin, y: rectY },
|
|
223
|
+
size: { width: busWidth - margin / 2, height: rectHeight },
|
|
224
|
+
color: color,
|
|
225
|
+
opacity: opacity,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
var calcCirclePoint = function (angleRadians, radius) {
|
|
230
|
+
var circleX = radius * Math.cos(angleRadians);
|
|
231
|
+
var circleY = radius * Math.sin(angleRadians);
|
|
232
|
+
return { x: circleX, y: circleY };
|
|
233
|
+
};
|
|
234
|
+
var lerp = function (start, end, t) {
|
|
235
|
+
return start + (end - start) * t;
|
|
236
|
+
};
|
|
237
|
+
var drawPolarSpectrum = function (_a) {
|
|
238
|
+
var imageDstBuffer = _a.imageDstBuffer, spectrum = _a.spectrum, centerX = _a.centerX, centerY = _a.centerY, innerRadius = _a.innerRadius, maxBarLength = _a.maxBarLength, barWidth = _a.barWidth, color = _a.color, opacity = _a.opacity;
|
|
239
|
+
var angleStep = (2 * Math.PI) / spectrum.length;
|
|
240
|
+
var innerLength = innerRadius * 2 * Math.PI;
|
|
241
|
+
var radiansPerPixel = 2 * Math.PI / innerLength;
|
|
242
|
+
var barWidthInRadians = radiansPerPixel * barWidth;
|
|
243
|
+
var spectrumAverage = spectrum.reduce(function (a, b) { return a + b; }, 0) / spectrum.length;
|
|
244
|
+
var scaleFactor = lerp(0.75, 1, spectrumAverage);
|
|
245
|
+
var scaledMaxOuterRadius = (innerRadius + maxBarLength) * scaleFactor;
|
|
246
|
+
var scaledInnerRadius = innerRadius * scaleFactor;
|
|
247
|
+
for (var i = 0; i < spectrum.length; i++) {
|
|
248
|
+
var currentSpectrumValue = spectrum[i] || 0;
|
|
249
|
+
var busRadius = lerp(scaledInnerRadius, scaledMaxOuterRadius, currentSpectrumValue);
|
|
250
|
+
var angle = i * angleStep;
|
|
251
|
+
var angleRadiansStart = angle;
|
|
252
|
+
var angleRadiansEnd = angle + barWidthInRadians;
|
|
253
|
+
var point1 = calcCirclePoint(angleRadiansStart, scaledInnerRadius);
|
|
254
|
+
var point2 = calcCirclePoint(angleRadiansStart, busRadius);
|
|
255
|
+
var point3 = calcCirclePoint(angleRadiansEnd, scaledInnerRadius);
|
|
256
|
+
var point4 = calcCirclePoint(angleRadiansEnd, busRadius);
|
|
257
|
+
exports.fillRect({
|
|
258
|
+
imageDstBuffer: imageDstBuffer,
|
|
259
|
+
points: [
|
|
260
|
+
{ x: centerX + Math.round(point1.x), y: centerY + Math.round(point1.y) },
|
|
261
|
+
{ x: centerX + Math.round(point2.x), y: centerY + Math.round(point2.y) },
|
|
262
|
+
{ x: centerX + Math.round(point4.x), y: centerY + Math.round(point4.y) },
|
|
263
|
+
{ x: centerX + Math.round(point3.x), y: centerY + Math.round(point3.y) },
|
|
264
|
+
],
|
|
265
|
+
color: color,
|
|
266
|
+
opacity: opacity,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
exports.createSpectrumVisualizerFrameGenerator = function () {
|
|
271
|
+
var prevSpectrum = null;
|
|
272
|
+
return function (_a) {
|
|
273
|
+
var backgroundImageBuffer = _a.backgroundImageBuffer, spectrum = _a.spectrum, size = _a.size, position = _a.position, rotation = _a.rotation, margin = _a.margin, color = _a.color, opacity = _a.opacity, spectrumEffect = _a.spectrumEffect;
|
|
274
|
+
var imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
275
|
+
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
276
|
+
var rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
277
|
+
if (spectrumEffect === 'volume') {
|
|
278
|
+
drawSpectrum({
|
|
279
|
+
imageDstBuffer: imageDstBuffer,
|
|
280
|
+
spectrum: spectrum,
|
|
281
|
+
size: size,
|
|
282
|
+
position: { x: position.x + 2, y: position.y + 2 },
|
|
283
|
+
rotation: rotation,
|
|
284
|
+
margin: margin,
|
|
285
|
+
color: rgbSpectrumColor,
|
|
286
|
+
opacity: opacity * 0.5,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (spectrumEffect === 'smooth' && prevSpectrum) {
|
|
290
|
+
drawSpectrum({
|
|
291
|
+
imageDstBuffer: imageDstBuffer,
|
|
292
|
+
spectrum: prevSpectrum,
|
|
293
|
+
size: size,
|
|
294
|
+
position: position,
|
|
295
|
+
rotation: rotation,
|
|
296
|
+
margin: margin,
|
|
297
|
+
color: rgbSpectrumColor,
|
|
298
|
+
opacity: opacity * 0.3,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
drawSpectrum({
|
|
302
|
+
imageDstBuffer: imageDstBuffer,
|
|
303
|
+
spectrum: spectrum,
|
|
304
|
+
size: size,
|
|
305
|
+
position: position,
|
|
306
|
+
rotation: rotation,
|
|
307
|
+
margin: margin,
|
|
308
|
+
color: rgbSpectrumColor,
|
|
309
|
+
opacity: opacity,
|
|
310
|
+
});
|
|
311
|
+
prevSpectrum = spectrum;
|
|
312
|
+
return imageDstBuffer;
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
exports.createPolarVisualizerFrameGenerator = function () {
|
|
316
|
+
var prevSpectrum = null;
|
|
317
|
+
return function (_a) {
|
|
318
|
+
var backgroundImageBuffer = _a.backgroundImageBuffer, spectrum = _a.spectrum, centerX = _a.centerX, centerY = _a.centerY, innerRadius = _a.innerRadius, maxBarLength = _a.maxBarLength, barWidth = _a.barWidth, color = _a.color, opacity = _a.opacity, spectrumEffect = _a.spectrumEffect;
|
|
319
|
+
var imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
320
|
+
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
321
|
+
var rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
322
|
+
if (spectrumEffect === 'volume') {
|
|
323
|
+
drawPolarSpectrum({
|
|
324
|
+
imageDstBuffer: imageDstBuffer,
|
|
325
|
+
spectrum: spectrum,
|
|
326
|
+
centerX: centerX + 2,
|
|
327
|
+
centerY: centerY + 2,
|
|
328
|
+
innerRadius: innerRadius,
|
|
329
|
+
maxBarLength: maxBarLength,
|
|
330
|
+
barWidth: barWidth,
|
|
331
|
+
color: rgbSpectrumColor,
|
|
332
|
+
opacity: opacity * 0.5,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
if (spectrumEffect === 'smooth' && prevSpectrum) {
|
|
336
|
+
drawPolarSpectrum({
|
|
337
|
+
imageDstBuffer: imageDstBuffer,
|
|
338
|
+
spectrum: prevSpectrum,
|
|
339
|
+
centerX: centerX,
|
|
340
|
+
centerY: centerY,
|
|
341
|
+
innerRadius: innerRadius,
|
|
342
|
+
maxBarLength: maxBarLength,
|
|
343
|
+
barWidth: barWidth,
|
|
344
|
+
color: rgbSpectrumColor,
|
|
345
|
+
opacity: opacity * 0.3,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
drawPolarSpectrum({
|
|
349
|
+
imageDstBuffer: imageDstBuffer,
|
|
350
|
+
spectrum: spectrum,
|
|
351
|
+
centerX: centerX,
|
|
352
|
+
centerY: centerY,
|
|
353
|
+
innerRadius: innerRadius,
|
|
354
|
+
maxBarLength: maxBarLength,
|
|
355
|
+
barWidth: barWidth,
|
|
356
|
+
color: rgbSpectrumColor,
|
|
357
|
+
opacity: opacity,
|
|
358
|
+
});
|
|
359
|
+
prevSpectrum = spectrum;
|
|
360
|
+
return imageDstBuffer;
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
exports.convertToBmp = function (filePath, targetWidth, targetHeight) { return __awaiter(void 0, void 0, void 0, function () {
|
|
364
|
+
return __generator(this, function (_a) {
|
|
365
|
+
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(void 0, void 0, void 0, function () {
|
|
366
|
+
var image, sw, sh, isOrientationMismatch, targetAspect, cropW, cropH, cropX, cropY, _a;
|
|
367
|
+
return __generator(this, function (_b) {
|
|
368
|
+
switch (_b.label) {
|
|
369
|
+
case 0:
|
|
370
|
+
_b.trys.push([0, 2, , 3]);
|
|
371
|
+
return [4 /*yield*/, jimp_1.default.read(filePath)];
|
|
372
|
+
case 1:
|
|
373
|
+
image = _b.sent();
|
|
374
|
+
if (targetWidth && targetHeight) {
|
|
375
|
+
sw = image.getWidth();
|
|
376
|
+
sh = image.getHeight();
|
|
377
|
+
isOrientationMismatch = (sw > sh && targetWidth < targetHeight) ||
|
|
378
|
+
(sw < sh && targetWidth > targetHeight);
|
|
379
|
+
if (isOrientationMismatch) {
|
|
380
|
+
targetAspect = targetWidth / targetHeight;
|
|
381
|
+
cropW = void 0, cropH = void 0, cropX = void 0, cropY = void 0;
|
|
382
|
+
if (sw / sh > targetAspect) {
|
|
383
|
+
cropW = Math.round(sh * targetAspect);
|
|
384
|
+
cropH = sh;
|
|
385
|
+
cropX = Math.round((sw - cropW) / 2);
|
|
386
|
+
cropY = 0;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
cropW = sw;
|
|
390
|
+
cropH = Math.round(sw / targetAspect);
|
|
391
|
+
cropX = 0;
|
|
392
|
+
cropY = Math.round((sh - cropH) / 2);
|
|
393
|
+
}
|
|
394
|
+
image.crop(cropX, cropY, cropW, cropH);
|
|
395
|
+
}
|
|
396
|
+
image.resize(targetWidth, targetHeight);
|
|
397
|
+
}
|
|
398
|
+
image.getBuffer("image/bmp", function (err, value) {
|
|
399
|
+
if (err) {
|
|
400
|
+
reject(err);
|
|
401
|
+
}
|
|
402
|
+
resolve(value);
|
|
403
|
+
});
|
|
404
|
+
return [3 /*break*/, 3];
|
|
405
|
+
case 2:
|
|
406
|
+
_a = _b.sent();
|
|
407
|
+
throw new Error("Cannot procces image file from path: " + filePath);
|
|
408
|
+
case 3: return [2 /*return*/];
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}); })];
|
|
412
|
+
});
|
|
413
|
+
}); };
|
|
414
|
+
exports.parseImage = function (buffer) { return bmp_js_1.decode(buffer); };
|
|
415
|
+
exports.getImageColor = function (image) {
|
|
416
|
+
var blueSum = 0;
|
|
417
|
+
var greenSum = 0;
|
|
418
|
+
var redSum = 0;
|
|
419
|
+
for (var currY = 0; currY < image.height; currY++) {
|
|
420
|
+
for (var currX = 0; currX < image.width; currX++) {
|
|
421
|
+
var idx = (image.width * currY + currX) << 2;
|
|
422
|
+
blueSum += image.data[idx + 1];
|
|
423
|
+
greenSum += image.data[idx + 2];
|
|
424
|
+
redSum += image.data[idx + 3];
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
var pixelsCount = image.width * image.height;
|
|
428
|
+
return {
|
|
429
|
+
red: ~~(redSum / pixelsCount),
|
|
430
|
+
green: ~~(greenSum / pixelsCount),
|
|
431
|
+
blue: ~~(blueSum / pixelsCount)
|
|
432
|
+
};
|
|
433
|
+
};
|
|
434
|
+
exports.getVideoFrameColor = function (bgrBuffer, width, height) {
|
|
435
|
+
var blueSum = 0;
|
|
436
|
+
var greenSum = 0;
|
|
437
|
+
var redSum = 0;
|
|
438
|
+
var pixelsCount = width * height;
|
|
439
|
+
for (var i = 0; i < bgrBuffer.length; i += 3) {
|
|
440
|
+
blueSum += bgrBuffer[i];
|
|
441
|
+
greenSum += bgrBuffer[i + 1];
|
|
442
|
+
redSum += bgrBuffer[i + 2];
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
red: ~~(redSum / pixelsCount),
|
|
446
|
+
green: ~~(greenSum / pixelsCount),
|
|
447
|
+
blue: ~~(blueSum / pixelsCount),
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
exports.invertColor = function (color) {
|
|
451
|
+
return ({ red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue });
|
|
452
|
+
};
|
|
453
|
+
var hexToRgb = function (hex) {
|
|
454
|
+
var red = parseInt(hex.substring(1, 3), 16);
|
|
455
|
+
var green = parseInt(hex.substring(3, 5), 16);
|
|
456
|
+
var blue = parseInt(hex.substring(5, 7), 16);
|
|
457
|
+
return { red: red, green: green, blue: blue };
|
|
458
|
+
};
|
|
459
459
|
//# sourceMappingURL=image.js.map
|