forked from tech4gold/transmogrifier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transmogrify
executable file
·121 lines (106 loc) · 5.62 KB
/
transmogrify
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env node
'use strict';
var file,
fs = require('fs'),
PNG = require('png-js'),
argv = require('minimist')(process.argv.slice(2)),
usage = 'Usage: \ttransmogrify <filename> [-f] [-h]\nHelp: \ttransmogrify draws a png to your console.\nOptions:\n\t-f --fit\tFit the image to the console size.\n\t-h --help\tRenders this message.',
kdi = '5e426cf473f8e5ef3c5249a6a9b3b5ec3b3d614e712b7382a786aa94b897fdeaedf065141f3868295341772c324a7a848aa1a780b0a5d46c9bb3e3fc9ee0fee8ea16ed010503f3130c1e1b603ff46340482e536a6b7671432d4f0e676e79757ca289f7c4cbd0cc85818bb1cd0dd3d48f91bebfd6d8e2de0798c19fbce0e60f10e911eb1c161deeef58f0593a03f26519371a15061e20215a603e3f08f46869224c29480a2f3053466a66725276777825502c2d31563357496d4b6f55797a7b837d84a888acf6f7a609c5cbadd1aed27f858780f88bb0b7c7cdc9cfafd3aad5959096b49abe9cc0dcd7bad90be2e4dffafb92989dc19ec3b6bcbde1c2e5ffe70010e8e90411eaeb021cec16171dedee34ef015835f005593b3a5f03f1f2f36512191337141a0c1518063d1e1f201b21365a5b60383e393f3c0861f4626863692322404c24294248280a2e2f2a304e534746646a41666b724d5270765477717826254350272c452d2b314f5632330e574449676d4a4b6e6f73557479517a757b5e837c7d7e84a2a8828889acf5f68af7a0a6c409a1c5c6cbcaadd0d1a7aeccd25c7fa4855d8781808cf8868b8db0b1b7a3c7c8cda5c90dcfa9afced3abaad4d58e958f906c9691b4949ab9be9b9cbfc0b2dcd6d7b3bad8d9b80bdde2e3e4dedff9fa07fb9392fc98979dbbc1999e9fc3b5b6dabcdbbde0e1fdc2e6e5feff0fe7'.match(/.{1,2}/g).map(function(n) { return parseInt(n,16) }),
colors = '000000800000008000808000000080800080008080c0c0c0808080ff000000ff00ffff000000ffff00ff00ffffffffff00000000005f0000870000af0000d70000ff005f00005f5f005f87005faf005fd7005fff00870000875f0087870087af0087d70087ff00af0000af5f00af8700afaf00afd700afff00d70000d75f00d78700d7af00d7d700d7ff00ff0000ff5f00ff8700ffaf00ffd700ffff5f00005f005f5f00875f00af5f00d75f00ff5f5f005f5f5f5f5f875f5faf5f5fd75f5fff5f87005f875f5f87875f87af5f87d75f87ff5faf005faf5f5faf875fafaf5fafd75fafff5fd7005fd75f5fd7875fd7af5fd7d75fd7ff5fff005fff5f5fff875fffaf5fffd75fffff87000087005f8700878700af8700d78700ff875f00875f5f875f87875faf875fd7875fff87870087875f8787878787af8787d78787ff87af0087af5f87af8787afaf87afd787afff87d70087d75f87d78787d7af87d7d787d7ff87ff0087ff5f87ff8787ffaf87ffd787ffffaf0000af005faf0087af00afaf00d7af00ffaf5f00af5f5faf5f87af5fafaf5fd7af5fffaf8700af875faf8787af87afaf87d7af87ffafaf00afaf5fafaf87afafafafafd7afafffafd700afd75fafd787afd7afafd7d7afd7ffafff00afff5fafff87afffafafffd7afffffd70000d7005fd70087d700afd700d7d700ffd75f00d75f5fd75f87d75fafd75fd7d75fffd78700d7875fd78787d787afd787d7d787ffd7af00d7af5fd7af87d7afafd7afd7d7afffd7d700d7d75fd7d787d7d7afd7d7d7d7d7ffd7ff00d7ff5fd7ff87d7ffafd7ffd7d7ffffff0000ff005fff0087ff00afff00d7ff00ffff5f00ff5f5fff5f87ff5fafff5fd7ff5fffff8700ff875fff8787ff87afff87d7ff87ffffaf00ffaf5fffaf87ffafafffafd7ffafffffd700ffd75fffd787ffd7afffd7d7ffd7ffffff00ffff5fffff87ffffafffffd7ffffff0808081212121c1c1c2626263030303a3a3a4444444e4e4e5858586262626c6c6c7676768080808a8a8a9494949e9e9ea8a8a8b2b2b2bcbcbcc6c6c6d0d0d0dadadae4e4e4eeeeee'.match(/.{1,6}/g).map(function(n) { return parseInt(n,16) });
function h2r(hex) {
var r = hex >> 16,
g = hex >> 8 & 0xFF,
b = hex & 0xFF;
return [r, g, b];
}
function d(x, y) {
x = x.slice ? x : h2r(x);
y = y.slice ? y : h2r(y);
return Math.abs(x[0] - y[0]) + Math.abs(x[1] - y[1]) + Math.abs(x[2] - y[2]);
}
function nn(node, value, depth, closest) {
var color, ri, axis, branches, dist;
if (closest === null) {
closest = {idx: 0, dist: 0xFFFFFF};
}
color = h2r(colors[kdi[node]]);
ri = node * 2 + 2;
if (ri < kdi.length) {
axis = depth % 3;
branches = value[axis] < color[axis] ? [ri - 1, ri] : [ri, ri - 1];
nn(branches[0], value, depth + 1, closest);
if (Math.abs(value[axis] - color[axis]) < closest.dist) {
nn(branches[1], value, depth + 1, closest);
}
} else {
dist = d(color, value);
if (dist < closest.dist) {
closest.dist = dist;
closest.idx = node;
}
}
return kdi[closest.idx];
}
function fit(png, pixels) {
var px = pixels;
var cw = process.stdout.columns / 2 - 2;
var ch = process.stdout.rows - 2;
if(cw < png.width || ch < png.height) {
var scale = Math.min(cw / png.width, ch / png.height);
var r = [], g = [], b = [], counts = {};
var pw = Math.floor(png.width * scale);
var ph = Math.floor(png.height * scale);
for (i = 0; i < pixels.length; i += 4) {
var ri = i / 4;
var col = Math.floor(scale * (ri % png.width));
var row = Math.floor(scale * (ri / png.width));
var idx = row * pw + col;
if(!r[idx]) {
r[idx] = g[idx] = b[idx] = counts[idx] = 0;
}
r[idx] += pixels[i];
g[idx] += pixels[i + 1];
b[idx] += pixels[i + 2];
counts[idx] += 1;
}
px = [];
png.width = pw;
png.height = ph;
for(var i = 0; i < r.length; i++) {
px.push(r[i] / counts[i], g[i] / counts[i], b[i] / counts[i], i % pw == pw - 1 ? 0 : 255);
}
}
return px;
}
if(argv.h || argv.help || argv._.length < 1) {
console.log(usage);
process.exit();
}
file = process.argv[2];
fs.readFile(file, function (err, file) {
var png;
if (err) {
throw 'Whoops: ' + err;
}
png = new PNG(file);
png.decode(function (pixels) {
if(argv.f || argv.fit) {
pixels = fit(png, pixels);
}
var i, row = [], l = '\x1B[48;5;', r = 'm \x1B[49m';
for (i = 0; i < pixels.length; i += 4) {
if (row.length === png.width) {
console.log(row.join(''));
row = [];
}
if (!pixels[i + 3]) {
row.push(' ');
} else {
row.push(l + nn(0, [pixels[i], pixels[i + 1], pixels[i + 2]], 0, null) + r);
}
}
if (row.length === png.width) {
console.log(row.join(''));
}
});
});