@@ -16,11 +16,15 @@ const int MODE_MONOCHROME = 1;
16
16
const int MODE_256 = 2 ;
17
17
const int MODE_ASCII_ART = 3 ;
18
18
const int MODE_ASCII_FULL = 4 ;
19
- int COLOR_MODE = 0 ;
19
+ const int MODE_DYNAMIC_RESOLUTION = 4 ;
20
+ int COLOR_MODE = MODE_DYNAMIC_RESOLUTION;
20
21
21
22
const char ASCII_ART_GRADIENT[] = " .,-=+*/OQ&%@#NM" ;
22
23
const char ASCII_FULL_GRADIENT[] = " `.-'\" ,:~_;!|^><+r*?=\\ L/v()ic7x1z{tJ}lsT[]FnuCYjofy2ae3I5VSkwZ4mXPGhEqpAK6$bd9HODRgMUW%8N0&B#Q@" ;
23
24
25
+ const string BLOCK_HEIGHT_GRADIENT[] = {" ▇" , " ▆" , " ▅" , " ▄" , " ▃" , " ▂" , " ▁" };
26
+ const string BLOCK_WIDTH_GRADIENT[] = {" ▉" , " ▊" , " ▋" , " ▌" , " ▍" , " ▎" , " ▏" };
27
+
24
28
sf::Music audioBuffer;
25
29
26
30
void onExit (int s) {
@@ -54,6 +58,24 @@ inline int similarityBetweenPixels(Vec3b vec1, Vec3b vec2) {
54
58
return abs (vec1[0 ] - vec2[0 ]) + abs (vec1[1 ] - vec2[1 ]) + abs (vec1[2 ] - vec2[2 ]);
55
59
}
56
60
61
+ inline float similarityBetweenPixelsf (Vec3b vec1, Vec3b vec2) {
62
+ return (float ) (abs (vec1[0 ] - vec2[0 ]) + abs (vec1[1 ] - vec2[1 ]) + abs (vec1[2 ] - vec2[2 ]));
63
+ }
64
+
65
+ inline Vec3b averagePixels (Vec3b vec1, Vec3b vec2) {
66
+ return Vec3b (vec1[0 ] + vec2[0 ], vec1[1 ] + vec2[1 ], vec1[2 ] + vec2[2 ]) / 2.0 ;
67
+ }
68
+ inline Vec3b averagePixels (Vec3b vec1, Vec3b vec2, Vec3b vec3) {
69
+ return Vec3b (vec1[0 ] + vec2[0 ] + vec3[0 ], vec1[1 ] + vec2[1 ] + vec3[1 ], vec1[2 ] + vec2[2 ] + vec3[2 ]) / 3.0 ;
70
+ }
71
+
72
+ inline Vec3b averagePixelsi (Vec3b vec1, Vec3b vec2) {
73
+ return Vec3b ((int ) (vec1[0 ] + vec2[0 ]) / 2 , (int ) (vec1[1 ] + vec2[1 ]) / 2 , (int ) (vec1[2 ] + vec2[2 ]) / 2 );
74
+ }
75
+ inline Vec3b averagePixelsi (Vec3b vec1, Vec3b vec2, Vec3b vec3) {
76
+ return Vec3b ((int ) (vec1[0 ] + vec2[0 ] + vec3[0 ]) / 3 , (int ) (vec1[1 ] + vec2[1 ] + vec3[1 ]) / 3 , (int ) (vec1[2 ] + vec2[2 ] + vec3[2 ]) / 3 );
77
+ }
78
+
57
79
int main (int argc, char *argv[]) {
58
80
// Setup the onExit signal to properly close the program
59
81
struct sigaction sigIntHandler;
@@ -103,6 +125,7 @@ int main(int argc, char *argv[]) {
103
125
cout << " --volume -v [percent] Set the volume in range 0% to 100%" << endl << endl;
104
126
cout << " Color Modes: " << endl;
105
127
cout << " color c Uses full RGB" << endl;
128
+ cout << " dynamic d Uses full color RGB, and tries to increase resolution using unicode characters; lowest compatibility, but nicest visuals" << endl;
106
129
cout << " 256-compatability 256 Uses a slightly more compatible 256 color palette, but looks much worse" << endl;
107
130
cout << " monochrome m Uses a set of basic, monochrome unicode characters; very compatible" << endl;
108
131
cout << " ascii-art a Makes the output look like ascii art; extremely high compatibilty" << endl;
@@ -137,6 +160,8 @@ int main(int argc, char *argv[]) {
137
160
COLOR_MODE = MODE_ASCII_ART;
138
161
} else if (argv[argIndex + 1 ][0 ] == (" f" )[0 ]) {
139
162
COLOR_MODE = MODE_ASCII_FULL;
163
+ } else if (argv[argIndex + 1 ][0 ] == (" d" )[0 ]) {
164
+ COLOR_MODE = MODE_DYNAMIC_RESOLUTION;
140
165
}
141
166
142
167
argIndex++; // Make sure to increment one extra to skip the mode
@@ -163,8 +188,7 @@ int main(int argc, char *argv[]) {
163
188
164
189
string videoPath = argv[1 ];
165
190
166
- if (!capture.open (videoPath))
167
- {
191
+ if (!capture.open (videoPath)) {
168
192
cout << " Video not found, is unreadable, or in wrong format!" <<endl;
169
193
return 1 ;
170
194
}
@@ -319,7 +343,7 @@ int main(int argc, char *argv[]) {
319
343
);
320
344
321
345
int index = coordsToScreenBufferIndex (i, j, terminalSize.ws_row );
322
- if (screenBufferInited) {
346
+ if (screenBufferInited && COLOR_MODE != MODE_DYNAMIC_RESOLUTION ) {
323
347
if (i > 8 && abs (screenBuffer[index + 0 ] - pixelBottom[0 ]) + abs (screenBuffer[index + 1 ] - pixelBottom[1 ]) + abs (screenBuffer[index + 2 ] - pixelBottom[2 ]) < 2 ) {
324
348
continue ;
325
349
}
@@ -332,7 +356,134 @@ int main(int argc, char *argv[]) {
332
356
cout << " \033 [" << (j - lastJ) - 1 << " C" ;
333
357
}
334
358
335
- if (COLOR_MODE == MODE_COLOR) {
359
+ if (COLOR_MODE == MODE_DYNAMIC_RESOLUTION) {
360
+ // Obtain a second pixel
361
+ Vec3b pixelTop = RGB.at <Vec3b>(
362
+ (int ) (i * yScale),
363
+ (int ) (j * xScale)
364
+ );
365
+
366
+ Vec3b pixelTopR = RGB.at <Vec3b>(
367
+ (int ) (i * yScale),
368
+ (int ) (j * xScale) + ((int ) xScale/2 )
369
+ );
370
+
371
+ Vec3b pixelBottomR = RGB.at <Vec3b>(
372
+ (int ) (i * yScale) + ((int ) yScale/2 ),
373
+ (int ) (j * xScale) + ((int ) xScale/2 )
374
+ );
375
+
376
+ // If color reduction is enabled, process that
377
+ if (COLOR_REDUCE > 0 ) {
378
+ float dither = (float ) ((i + j) % 2 ) / 2.1 ;
379
+ pixelTop[0 ] = roundf (pixelTop[0 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
380
+ pixelTop[1 ] = roundf (pixelTop[1 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
381
+ pixelTop[2 ] = roundf (pixelTop[2 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
382
+ pixelBottom[0 ] = roundf (pixelBottom[0 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
383
+ pixelBottom[1 ] = roundf (pixelBottom[1 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
384
+ pixelBottom[2 ] = roundf (pixelBottom[2 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
385
+ pixelTopR[0 ] = roundf (pixelTopR[0 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
386
+ pixelTopR[1 ] = roundf (pixelTopR[1 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
387
+ pixelTopR[2 ] = roundf (pixelTopR[2 ] / COLOR_REDUCE + dither) * COLOR_REDUCE;
388
+ pixelBottomR[0 ] = roundf (pixelBottomR[0 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
389
+ pixelBottomR[1 ] = roundf (pixelBottomR[1 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
390
+ pixelBottomR[2 ] = roundf (pixelBottomR[2 ] / COLOR_REDUCE - dither) * COLOR_REDUCE;
391
+ }
392
+
393
+ float verticalSplit = similarityBetweenPixelsf (averagePixels (pixelTop, pixelTopR), averagePixels (pixelBottom, pixelBottomR));
394
+ float horizontalSplit = similarityBetweenPixelsf (averagePixels (pixelTop, pixelBottom), averagePixels (pixelTopR, pixelBottomR));
395
+ float diagonalSplit = similarityBetweenPixelsf (averagePixels (pixelTop, pixelBottomR), averagePixels (pixelTopR, pixelBottom));
396
+ float topLeft = similarityBetweenPixelsf (pixelTop, averagePixels (pixelTopR, pixelBottom, pixelBottomR)) * 0.035 ;
397
+ float topRight = similarityBetweenPixelsf (pixelTopR, averagePixels (pixelTop, pixelBottom, pixelBottomR)) * 0.035 ;
398
+ float bottomLeft = similarityBetweenPixelsf (pixelBottom, averagePixels (pixelTopR, pixelTop, pixelBottomR)) * 0.035 ;
399
+ float bottomRight = similarityBetweenPixelsf (pixelBottomR, averagePixels (pixelTop, pixelTopR, pixelBottom)) * 0.035 ;
400
+
401
+ if (
402
+ verticalSplit > horizontalSplit && verticalSplit > diagonalSplit &&
403
+ verticalSplit > topRight && verticalSplit > topLeft &&
404
+ verticalSplit > bottomLeft && verticalSplit > bottomRight
405
+ ) {
406
+ float differences[7 ];
407
+ for (int k = 1 ; k < 8 ; k++) {
408
+ Vec3b pixel = RGB.at <Vec3b>(
409
+ (int ) (i * yScale) + ((int ) (((float ) k) * yScale/8 )),
410
+ (int ) (j * xScale)
411
+ );
412
+
413
+ differences[k - 1 ] = similarityBetweenPixelsf (pixel, pixelTop);
414
+ }
415
+
416
+ int highestIndex;
417
+ float highestValue = -1 ;
418
+ for (int k = 1 ; k < 7 ; k++) {
419
+ float delta = abs (differences[k - 1 ] - differences[k]);
420
+
421
+ if (delta > highestValue) {
422
+ highestValue = delta;
423
+ highestIndex = k;
424
+ }
425
+ }
426
+
427
+ cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m\033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m" << BLOCK_HEIGHT_GRADIENT[highestIndex];
428
+ } else if (
429
+ horizontalSplit > diagonalSplit &&
430
+ horizontalSplit > topRight && horizontalSplit > topLeft &&
431
+ horizontalSplit > bottomLeft && horizontalSplit > bottomRight
432
+ ) {
433
+ Vec3b left = averagePixelsi (pixelTop, pixelBottom);
434
+ Vec3b right = averagePixelsi (pixelTopR, pixelBottomR);
435
+ // cout << "\033[38;2;" << ((int) left[2]) << ";" << ((int) left[1]) << ";" << ((int) left[0]) << "m\033[48;2;" << ((int) right[2]) << ";" << ((int) right[1]) << ";" << ((int) right[0]) << "m▌";
436
+
437
+ float differences[7 ];
438
+ for (int k = 1 ; k < 8 ; k++) {
439
+ Vec3b pixel = RGB.at <Vec3b>(
440
+ (int ) (i * yScale),
441
+ (int ) (j * xScale) + ((int ) (((float ) k) * yScale/16 ))
442
+ );
443
+
444
+ differences[k - 1 ] = similarityBetweenPixelsf (pixel, left);
445
+ }
446
+
447
+ int highestIndex;
448
+ float highestValue = -1 ;
449
+ for (int k = 1 ; k < 7 ; k++) {
450
+ float delta = abs (differences[k - 1 ] - differences[k]);
451
+
452
+ if (delta > highestValue) {
453
+ highestValue = delta;
454
+ highestIndex = k;
455
+ }
456
+ }
457
+
458
+ cout << " \033 [48;2;" << ((int ) right[2 ]) << " ;" << ((int ) right[1 ]) << " ;" << ((int ) right[0 ]) << " m\033 [38;2;" << ((int ) left[2 ]) << " ;" << ((int ) left[1 ]) << " ;" << ((int ) left[0 ]) << " m" << BLOCK_WIDTH_GRADIENT[highestIndex];
459
+ } else if (
460
+ diagonalSplit > topRight && diagonalSplit > topLeft &&
461
+ diagonalSplit > bottomLeft && diagonalSplit > bottomRight
462
+ ) {
463
+ Vec3b B = averagePixelsi (pixelTop, pixelBottomR);
464
+ Vec3b A = averagePixelsi (pixelTopR, pixelBottom);
465
+ cout << " \033 [38;2;" << ((int ) A[2 ]) << " ;" << ((int ) A[1 ]) << " ;" << ((int ) A[0 ]) << " m\033 [48;2;" << ((int ) B[2 ]) << " ;" << ((int ) B[1 ]) << " ;" << ((int ) B[0 ]) << " m▞" ;
466
+ } else if (
467
+ topRight > topLeft && topRight > bottomLeft && topRight > bottomRight
468
+ ) {
469
+ Vec3b A = averagePixelsi (pixelTop, pixelBottom, pixelBottomR);
470
+ cout << " \033 [48;2;" << ((int ) A[2 ]) << " ;" << ((int ) A[1 ]) << " ;" << ((int ) A[0 ]) << " m\033 [38;2;" << ((int ) pixelTopR[2 ]) << " ;" << ((int ) pixelTopR[1 ]) << " ;" << ((int ) pixelTopR[0 ]) << " m▝" ;
471
+ } else if (
472
+ topLeft > bottomLeft && topLeft > bottomRight
473
+ ) {
474
+ Vec3b A = averagePixelsi (pixelTopR, pixelBottom, pixelBottomR);
475
+ cout << " \033 [48;2;" << ((int ) A[2 ]) << " ;" << ((int ) A[1 ]) << " ;" << ((int ) A[0 ]) << " m\033 [38;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m▘" ;
476
+ } else if (
477
+ bottomLeft > bottomRight
478
+ ) {
479
+ Vec3b A = averagePixelsi (pixelTopR, pixelTop, pixelBottomR);
480
+ cout << " \033 [48;2;" << ((int ) A[2 ]) << " ;" << ((int ) A[1 ]) << " ;" << ((int ) A[0 ]) << " m\033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m▖" ;
481
+ } else {
482
+ Vec3b A = averagePixelsi (pixelTopR, pixelTop, pixelBottom);
483
+ cout << " \033 [48;2;" << ((int ) A[2 ]) << " ;" << ((int ) A[1 ]) << " ;" << ((int ) A[0 ]) << " m\033 [38;2;" << ((int ) pixelBottomR[2 ]) << " ;" << ((int ) pixelBottomR[1 ]) << " ;" << ((int ) pixelBottomR[0 ]) << " m▗" ;
484
+ }
485
+
486
+ } else if (COLOR_MODE == MODE_COLOR) {
336
487
// Obtain a second pixel
337
488
Vec3b pixelTop = RGB.at <Vec3b>(
338
489
(int ) (i * yScale),
@@ -356,9 +507,9 @@ int main(int argc, char *argv[]) {
356
507
cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m " ;
357
508
} else {
358
509
if (useUnicode) {
359
- cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m" << " \033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m▄" ;
510
+ cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m\033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m▄" ;
360
511
} else {
361
- cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m" << " \033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m_" ;
512
+ cout << " \033 [48;2;" << ((int ) pixelTop[2 ]) << " ;" << ((int ) pixelTop[1 ]) << " ;" << ((int ) pixelTop[0 ]) << " m\033 [38;2;" << ((int ) pixelBottom[2 ]) << " ;" << ((int ) pixelBottom[1 ]) << " ;" << ((int ) pixelBottom[0 ]) << " m_" ;
362
513
}
363
514
}
364
515
} else if (COLOR_MODE == MODE_MONOCHROME) {
0 commit comments