Skip to content

Instantly share code, notes, and snippets.

@eugeneware
Forked from garfieldnate/imgcat.py
Created September 27, 2018 04:12
Show Gist options
  • Save eugeneware/0e632122a7e5088679194aa2739843fe to your computer and use it in GitHub Desktop.
Save eugeneware/0e632122a7e5088679194aa2739843fe to your computer and use it in GitHub Desktop.
Python 2/3 version of imgcat tool, which displays images inline in iTerm2
from __future__ import print_function
import base64
import os
import select
import sys
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
# only accepts ESC backslash for ST.
def print_osc(terminal):
if terminal.startswith('screen'):
print_partial("\033Ptmux;\033\033]")
else:
print_partial("\033]")
# More of the tmux workaround described above.
def print_st(terminal):
if terminal.startswith('screen'):
print_partial("\a\033\\")
else:
print_partial("\a")
# print_image filename inline base64contents print_filename
# filename: Filename to convey to client
# inline: 0 or 1
# base64contents: Base64-encoded contents
# print_filename: If non-empty, print the filename
# before outputting the image
def print_image(image_file_name=None, data=None):
terminal = os.environ.get('TERM')
print_osc(terminal)
print_partial('1337;File=')
args = []
if image_file_name:
b64_file_name = base64.b64encode(image_file_name.encode('ascii')).decode('ascii')
args.append('name=' + b64_file_name)
with open(image_file_name, "rb") as image_file:
b64_data = base64.b64encode(image_file.read()).decode('ascii')
elif data:
b64_data = base64.b64encode(data).decode('ascii')
else:
raise ValueError("Expected image_file_name or data")
args.append('size=' + str(len(b64_data)))
args.append("inline=1")
print_partial(';'.join(args))
print_partial(":")
print_partial(b64_data)
print_st(terminal)
def show_help():
print("Usage: imgcat filename ...")
print(" or: cat filename | python imgcat.py -")
exit()
def print_partial(msg):
print(msg, end='')
def _read_binary_stdin():
# see https://stackoverflow.com/a/38939320/474819 for other platform notes
PY3 = sys.version_info >= (3,0)
if PY3:
source = sys.stdin.buffer
else:
# Python 2 on Windows opens sys.stdin in text mode, and
# binary data that read from it becomes corrupted on \r\n
if sys.platform == "win32":
# set sys.stdin to binary mode
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
source = sys.stdin
return source.read()
def main():
filename = None
data = None
if len(sys.argv) != 2:
show_help()
if sys.argv[1] != '-':
filename=sys.argv[1]
print_image(image_file_name=filename)
else:
data = _read_binary_stdin()
print_image(data=data)
if not filename and not data:
show_help()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment