-
-
Save jbboehr/7ffe9c4a582b0ba1131c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
from PIL import Image | |
xterm256colors = [ # http://pln.jonas.me/xterm-colors | |
(0, (0x00, 0x00, 0x00)), # SYSTEM | |
(1, (0x80, 0x00, 0x00)), # SYSTEM | |
(2, (0x00, 0x80, 0x00)), # SYSTEM | |
(3, (0x80, 0x80, 0x00)), # SYSTEM | |
(4, (0x00, 0x00, 0x80)), # SYSTEM | |
(5, (0x80, 0x00, 0x80)), # SYSTEM | |
(6, (0x00, 0x80, 0x80)), # SYSTEM | |
(7, (0xc0, 0xc0, 0xc0)), # SYSTEM | |
(8, (0x80, 0x80, 0x80)), # SYSTEM | |
(9, (0xff, 0x00, 0x00)), # SYSTEM | |
(10, (0x00, 0xff, 0x00)), # SYSTEM | |
(11, (0xff, 0xff, 0x00)), # SYSTEM | |
(12, (0x00, 0x00, 0xff)), # SYSTEM | |
(13, (0xff, 0x00, 0xff)), # SYSTEM | |
(14, (0x00, 0xff, 0xff)), # SYSTEM | |
(15, (0xff, 0xff, 0xff)), # SYSTEM | |
(16, (0x00, 0x00, 0x00)), # Grey0 | |
(17, (0x00, 0x00, 0x5f)), # NavyBlue | |
(18, (0x00, 0x00, 0x87)), # DarkBlue | |
(19, (0x00, 0x00, 0xaf)), # Blue3 | |
(20, (0x00, 0x00, 0xd7)), # Blue3 | |
(21, (0x00, 0x00, 0xff)), # Blue1 | |
(22, (0x00, 0x5f, 0x00)), # DarkGreen | |
(23, (0x00, 0x5f, 0x5f)), # DeepSkyBlue4 | |
(24, (0x00, 0x5f, 0x87)), # DeepSkyBlue4 | |
(25, (0x00, 0x5f, 0xaf)), # DeepSkyBlue4 | |
(26, (0x00, 0x5f, 0xd7)), # DodgerBlue3 | |
(27, (0x00, 0x5f, 0xff)), # DodgerBlue2 | |
(28, (0x00, 0x87, 0x00)), # Green4 | |
(29, (0x00, 0x87, 0x5f)), # SpringGreen4 | |
(30, (0x00, 0x87, 0x87)), # Turquoise4 | |
(31, (0x00, 0x87, 0xaf)), # DeepSkyBlue3 | |
(32, (0x00, 0x87, 0xd7)), # DeepSkyBlue3 | |
(33, (0x00, 0x87, 0xff)), # DodgerBlue1 | |
(34, (0x00, 0xaf, 0x00)), # Green3 | |
(35, (0x00, 0xaf, 0x5f)), # SpringGreen3 | |
(36, (0x00, 0xaf, 0x87)), # DarkCyan | |
(37, (0x00, 0xaf, 0xaf)), # LightSeaGreen | |
(38, (0x00, 0xaf, 0xd7)), # DeepSkyBlue2 | |
(39, (0x00, 0xaf, 0xff)), # DeepSkyBlue1 | |
(40, (0x00, 0xd7, 0x00)), # Green3 | |
(41, (0x00, 0xd7, 0x5f)), # SpringGreen3 | |
(42, (0x00, 0xd7, 0x87)), # SpringGreen2 | |
(43, (0x00, 0xd7, 0xaf)), # Cyan3 | |
(44, (0x00, 0xd7, 0xd7)), # DarkTurquoise | |
(45, (0x00, 0xd7, 0xff)), # Turquoise2 | |
(46, (0x00, 0xff, 0x00)), # Green1 | |
(47, (0x00, 0xff, 0x5f)), # SpringGreen2 | |
(48, (0x00, 0xff, 0x87)), # SpringGreen1 | |
(49, (0x00, 0xff, 0xaf)), # MediumSpringGreen | |
(50, (0x00, 0xff, 0xd7)), # Cyan2 | |
(51, (0x00, 0xff, 0xff)), # Cyan1 | |
(52, (0x5f, 0x00, 0x00)), # DarkRed | |
(53, (0x5f, 0x00, 0x5f)), # DeepPink4 | |
(54, (0x5f, 0x00, 0x87)), # Purple4 | |
(55, (0x5f, 0x00, 0xaf)), # Purple4 | |
(56, (0x5f, 0x00, 0xd7)), # Purple3 | |
(57, (0x5f, 0x00, 0xff)), # BlueViolet | |
(58, (0x5f, 0x5f, 0x00)), # Orange4 | |
(59, (0x5f, 0x5f, 0x5f)), # Grey37 | |
(60, (0x5f, 0x5f, 0x87)), # MediumPurple4 | |
(61, (0x5f, 0x5f, 0xaf)), # SlateBlue3 | |
(62, (0x5f, 0x5f, 0xd7)), # SlateBlue3 | |
(63, (0x5f, 0x5f, 0xff)), # RoyalBlue1 | |
(64, (0x5f, 0x87, 0x00)), # Chartreuse4 | |
(65, (0x5f, 0x87, 0x5f)), # DarkSeaGreen4 | |
(66, (0x5f, 0x87, 0x87)), # PaleTurquoise4 | |
(67, (0x5f, 0x87, 0xaf)), # SteelBlue | |
(68, (0x5f, 0x87, 0xd7)), # SteelBlue3 | |
(69, (0x5f, 0x87, 0xff)), # CornflowerBlue | |
(70, (0x5f, 0xaf, 0x00)), # Chartreuse3 | |
(71, (0x5f, 0xaf, 0x5f)), # DarkSeaGreen4 | |
(72, (0x5f, 0xaf, 0x87)), # CadetBlue | |
(73, (0x5f, 0xaf, 0xaf)), # CadetBlue | |
(74, (0x5f, 0xaf, 0xd7)), # SkyBlue3 | |
(75, (0x5f, 0xaf, 0xff)), # SteelBlue1 | |
(76, (0x5f, 0xd7, 0x00)), # Chartreuse3 | |
(77, (0x5f, 0xd7, 0x5f)), # PaleGreen3 | |
(78, (0x5f, 0xd7, 0x87)), # SeaGreen3 | |
(79, (0x5f, 0xd7, 0xaf)), # Aquamarine3 | |
(80, (0x5f, 0xd7, 0xd7)), # MediumTurquoise | |
(81, (0x5f, 0xd7, 0xff)), # SteelBlue1 | |
(82, (0x5f, 0xff, 0x00)), # Chartreuse2 | |
(83, (0x5f, 0xff, 0x5f)), # SeaGreen2 | |
(84, (0x5f, 0xff, 0x87)), # SeaGreen1 | |
(85, (0x5f, 0xff, 0xaf)), # SeaGreen1 | |
(86, (0x5f, 0xff, 0xd7)), # Aquamarine1 | |
(87, (0x5f, 0xff, 0xff)), # DarkSlateGray2 | |
(88, (0x87, 0x00, 0x00)), # DarkRed | |
(89, (0x87, 0x00, 0x5f)), # DeepPink4 | |
(90, (0x87, 0x00, 0x87)), # DarkMagenta | |
(91, (0x87, 0x00, 0xaf)), # DarkMagenta | |
(92, (0x87, 0x00, 0xd7)), # DarkViolet | |
(93, (0x87, 0x00, 0xff)), # Purple | |
(94, (0x87, 0x5f, 0x00)), # Orange4 | |
(95, (0x87, 0x5f, 0x5f)), # LightPink4 | |
(96, (0x87, 0x5f, 0x87)), # Plum4 | |
(97, (0x87, 0x5f, 0xaf)), # MediumPurple3 | |
(98, (0x87, 0x5f, 0xd7)), # MediumPurple3 | |
(99, (0x87, 0x5f, 0xff)), # SlateBlue1 | |
(100, (0x87, 0x87, 0x00)), # Yellow4 | |
(101, (0x87, 0x87, 0x5f)), # Wheat4 | |
(102, (0x87, 0x87, 0x87)), # Grey53 | |
(103, (0x87, 0x87, 0xaf)), # LightSlateGrey | |
(104, (0x87, 0x87, 0xd7)), # MediumPurple | |
(105, (0x87, 0x87, 0xff)), # LightSlateBlue | |
(106, (0x87, 0xaf, 0x00)), # Yellow4 | |
(107, (0x87, 0xaf, 0x5f)), # DarkOliveGreen3 | |
(108, (0x87, 0xaf, 0x87)), # DarkSeaGreen | |
(109, (0x87, 0xaf, 0xaf)), # LightSkyBlue3 | |
(110, (0x87, 0xaf, 0xd7)), # LightSkyBlue3 | |
(111, (0x87, 0xaf, 0xff)), # SkyBlue2 | |
(112, (0x87, 0xd7, 0x00)), # Chartreuse2 | |
(113, (0x87, 0xd7, 0x5f)), # DarkOliveGreen3 | |
(114, (0x87, 0xd7, 0x87)), # PaleGreen3 | |
(115, (0x87, 0xd7, 0xaf)), # DarkSeaGreen3 | |
(116, (0x87, 0xd7, 0xd7)), # DarkSlateGray3 | |
(117, (0x87, 0xd7, 0xff)), # SkyBlue1 | |
(118, (0x87, 0xff, 0x00)), # Chartreuse1 | |
(119, (0x87, 0xff, 0x5f)), # LightGreen | |
(120, (0x87, 0xff, 0x87)), # LightGreen | |
(121, (0x87, 0xff, 0xaf)), # PaleGreen1 | |
(122, (0x87, 0xff, 0xd7)), # Aquamarine1 | |
(123, (0x87, 0xff, 0xff)), # DarkSlateGray1 | |
(124, (0xaf, 0x00, 0x00)), # Red3 | |
(125, (0xaf, 0x00, 0x5f)), # DeepPink4 | |
(126, (0xaf, 0x00, 0x87)), # MediumVioletRed | |
(127, (0xaf, 0x00, 0xaf)), # Magenta3 | |
(128, (0xaf, 0x00, 0xd7)), # DarkViolet | |
(129, (0xaf, 0x00, 0xff)), # Purple | |
(130, (0xaf, 0x5f, 0x00)), # DarkOrange3 | |
(131, (0xaf, 0x5f, 0x5f)), # IndianRed | |
(132, (0xaf, 0x5f, 0x87)), # HotPink3 | |
(133, (0xaf, 0x5f, 0xaf)), # MediumOrchid3 | |
(134, (0xaf, 0x5f, 0xd7)), # MediumOrchid | |
(135, (0xaf, 0x5f, 0xff)), # MediumPurple2 | |
(136, (0xaf, 0x87, 0x00)), # DarkGoldenrod | |
(137, (0xaf, 0x87, 0x5f)), # LightSalmon3 | |
(138, (0xaf, 0x87, 0x87)), # RosyBrown | |
(139, (0xaf, 0x87, 0xaf)), # Grey63 | |
(140, (0xaf, 0x87, 0xd7)), # MediumPurple2 | |
(141, (0xaf, 0x87, 0xff)), # MediumPurple1 | |
(142, (0xaf, 0xaf, 0x00)), # Gold3 | |
(143, (0xaf, 0xaf, 0x5f)), # DarkKhaki | |
(144, (0xaf, 0xaf, 0x87)), # NavajoWhite3 | |
(145, (0xaf, 0xaf, 0xaf)), # Grey69 | |
(146, (0xaf, 0xaf, 0xd7)), # LightSteelBlue3 | |
(147, (0xaf, 0xaf, 0xff)), # LightSteelBlue | |
(148, (0xaf, 0xd7, 0x00)), # Yellow3 | |
(149, (0xaf, 0xd7, 0x5f)), # DarkOliveGreen3 | |
(150, (0xaf, 0xd7, 0x87)), # DarkSeaGreen3 | |
(151, (0xaf, 0xd7, 0xaf)), # DarkSeaGreen2 | |
(152, (0xaf, 0xd7, 0xd7)), # LightCyan3 | |
(153, (0xaf, 0xd7, 0xff)), # LightSkyBlue1 | |
(154, (0xaf, 0xff, 0x00)), # GreenYellow | |
(155, (0xaf, 0xff, 0x5f)), # DarkOliveGreen2 | |
(156, (0xaf, 0xff, 0x87)), # PaleGreen1 | |
(157, (0xaf, 0xff, 0xaf)), # DarkSeaGreen2 | |
(158, (0xaf, 0xff, 0xd7)), # DarkSeaGreen1 | |
(159, (0xaf, 0xff, 0xff)), # PaleTurquoise1 | |
(160, (0xd7, 0x00, 0x00)), # Red3 | |
(161, (0xd7, 0x00, 0x5f)), # DeepPink3 | |
(162, (0xd7, 0x00, 0x87)), # DeepPink3 | |
(163, (0xd7, 0x00, 0xaf)), # Magenta3 | |
(164, (0xd7, 0x00, 0xd7)), # Magenta3 | |
(165, (0xd7, 0x00, 0xff)), # Magenta2 | |
(166, (0xd7, 0x5f, 0x00)), # DarkOrange3 | |
(167, (0xd7, 0x5f, 0x5f)), # IndianRed | |
(168, (0xd7, 0x5f, 0x87)), # HotPink3 | |
(169, (0xd7, 0x5f, 0xaf)), # HotPink2 | |
(170, (0xd7, 0x5f, 0xd7)), # Orchid | |
(171, (0xd7, 0x5f, 0xff)), # MediumOrchid1 | |
(172, (0xd7, 0x87, 0x00)), # Orange3 | |
(173, (0xd7, 0x87, 0x5f)), # LightSalmon3 | |
(174, (0xd7, 0x87, 0x87)), # LightPink3 | |
(175, (0xd7, 0x87, 0xaf)), # Pink3 | |
(176, (0xd7, 0x87, 0xd7)), # Plum3 | |
(177, (0xd7, 0x87, 0xff)), # Violet | |
(178, (0xd7, 0xaf, 0x00)), # Gold3 | |
(179, (0xd7, 0xaf, 0x5f)), # LightGoldenrod3 | |
(180, (0xd7, 0xaf, 0x87)), # Tan | |
(181, (0xd7, 0xaf, 0xaf)), # MistyRose3 | |
(182, (0xd7, 0xaf, 0xd7)), # Thistle3 | |
(183, (0xd7, 0xaf, 0xff)), # Plum2 | |
(184, (0xd7, 0xd7, 0x00)), # Yellow3 | |
(185, (0xd7, 0xd7, 0x5f)), # Khaki3 | |
(186, (0xd7, 0xd7, 0x87)), # LightGoldenrod2 | |
(187, (0xd7, 0xd7, 0xaf)), # LightYellow3 | |
(188, (0xd7, 0xd7, 0xd7)), # Grey84 | |
(189, (0xd7, 0xd7, 0xff)), # LightSteelBlue1 | |
(190, (0xd7, 0xff, 0x00)), # Yellow2 | |
(191, (0xd7, 0xff, 0x5f)), # DarkOliveGreen1 | |
(192, (0xd7, 0xff, 0x87)), # DarkOliveGreen1 | |
(193, (0xd7, 0xff, 0xaf)), # DarkSeaGreen1 | |
(194, (0xd7, 0xff, 0xd7)), # Honeydew2 | |
(195, (0xd7, 0xff, 0xff)), # LightCyan1 | |
(196, (0xff, 0x00, 0x00)), # Red1 | |
(197, (0xff, 0x00, 0x5f)), # DeepPink2 | |
(198, (0xff, 0x00, 0x87)), # DeepPink1 | |
(199, (0xff, 0x00, 0xaf)), # DeepPink1 | |
(200, (0xff, 0x00, 0xd7)), # Magenta2 | |
(201, (0xff, 0x00, 0xff)), # Magenta1 | |
(202, (0xff, 0x5f, 0x00)), # OrangeRed1 | |
(203, (0xff, 0x5f, 0x5f)), # IndianRed1 | |
(204, (0xff, 0x5f, 0x87)), # IndianRed1 | |
(205, (0xff, 0x5f, 0xaf)), # HotPink | |
(206, (0xff, 0x5f, 0xd7)), # HotPink | |
(207, (0xff, 0x5f, 0xff)), # MediumOrchid1 | |
(208, (0xff, 0x87, 0x00)), # DarkOrange | |
(209, (0xff, 0x87, 0x5f)), # Salmon1 | |
(210, (0xff, 0x87, 0x87)), # LightCoral | |
(211, (0xff, 0x87, 0xaf)), # PaleVioletRed1 | |
(212, (0xff, 0x87, 0xd7)), # Orchid2 | |
(213, (0xff, 0x87, 0xff)), # Orchid1 | |
(214, (0xff, 0xaf, 0x00)), # Orange1 | |
(215, (0xff, 0xaf, 0x5f)), # SandyBrown | |
(216, (0xff, 0xaf, 0x87)), # LightSalmon1 | |
(217, (0xff, 0xaf, 0xaf)), # LightPink1 | |
(218, (0xff, 0xaf, 0xd7)), # Pink1 | |
(219, (0xff, 0xaf, 0xff)), # Plum1 | |
(220, (0xff, 0xd7, 0x00)), # Gold1 | |
(221, (0xff, 0xd7, 0x5f)), # LightGoldenrod2 | |
(222, (0xff, 0xd7, 0x87)), # LightGoldenrod2 | |
(223, (0xff, 0xd7, 0xaf)), # NavajoWhite1 | |
(224, (0xff, 0xd7, 0xd7)), # MistyRose1 | |
(225, (0xff, 0xd7, 0xff)), # Thistle1 | |
(226, (0xff, 0xff, 0x00)), # Yellow1 | |
(227, (0xff, 0xff, 0x5f)), # LightGoldenrod1 | |
(228, (0xff, 0xff, 0x87)), # Khaki1 | |
(229, (0xff, 0xff, 0xaf)), # Wheat1 | |
(230, (0xff, 0xff, 0xd7)), # Cornsilk1 | |
(231, (0xff, 0xff, 0xff)), # Grey100 | |
(232, (0x08, 0x08, 0x08)), # Grey3 | |
(233, (0x12, 0x12, 0x12)), # Grey7 | |
(234, (0x1c, 0x1c, 0x1c)), # Grey11 | |
(235, (0x26, 0x26, 0x26)), # Grey15 | |
(236, (0x30, 0x30, 0x30)), # Grey19 | |
(237, (0x3a, 0x3a, 0x3a)), # Grey23 | |
(238, (0x44, 0x44, 0x44)), # Grey27 | |
(239, (0x4e, 0x4e, 0x4e)), # Grey30 | |
(240, (0x58, 0x58, 0x58)), # Grey35 | |
(241, (0x62, 0x62, 0x62)), # Grey39 | |
(242, (0x6c, 0x6c, 0x6c)), # Grey42 | |
(243, (0x76, 0x76, 0x76)), # Grey46 | |
(244, (0x80, 0x80, 0x80)), # Grey50 | |
(245, (0x8a, 0x8a, 0x8a)), # Grey54 | |
(246, (0x94, 0x94, 0x94)), # Grey58 | |
(247, (0x9e, 0x9e, 0x9e)), # Grey62 | |
(248, (0xa8, 0xa8, 0xa8)), # Grey66 | |
(249, (0xb2, 0xb2, 0xb2)), # Grey70 | |
(250, (0xbc, 0xbc, 0xbc)), # Grey74 | |
(251, (0xc6, 0xc6, 0xc6)), # Grey78 | |
(252, (0xd0, 0xd0, 0xd0)), # Grey82 | |
(253, (0xda, 0xda, 0xda)), # Grey85 | |
(254, (0xe4, 0xe4, 0xe4)), # Grey89 | |
(255, (0xee, 0xee, 0xee)), # Grey93 | |
] | |
def colordiff(ca, cb): | |
return ( | |
abs(ca[0] - cb[0]) + | |
abs(ca[1] - cb[1]) + | |
abs(ca[2] - cb[2]) | |
) | |
def find_colorcode(c): | |
winning_colordiff = 999 | |
winning_colorcode = -1 | |
for cc in xterm256colors: | |
cdiff = colordiff(c, cc[1]) | |
if cdiff < winning_colordiff: | |
winning_colordiff = cdiff | |
winning_colorcode = cc[0] | |
return winning_colorcode | |
if len(sys.argv) <= 2: | |
print("Usage: %s <image file> <text file>" % sys.argv[0]) | |
print("Converts images into color sequences (xterm-256color)") | |
exit(1) | |
img = Image.open(sys.argv[1]) | |
if img.size[0] * img.size[1] > 120 * 36: | |
print("Warning: Big image, did you forget to scale it down?") | |
img = img.convert("RGB") | |
imgd = img.load() | |
tf = open(sys.argv[2], "wb") | |
for y in range(img.size[1]): | |
lastcc = -1 | |
for x in range(img.size[0]): | |
cc = find_colorcode(imgd[x, y]) | |
if cc == lastcc: | |
tf.write(b" ") # Just add more spaces instead of repeating the ANSI sequence | |
else: | |
tf.write(b"\x1b[48;5;" + str(cc).encode("ascii") + b"m ") # 2 spaces per pixel because chars are non-square | |
lastcc = cc | |
tf.write(b"\x1b[0m\n") | |
tf.flush() | |
tf.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment