diff options
-rw-r--r-- | ranger/ext/img_display.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/ranger/ext/img_display.py b/ranger/ext/img_display.py new file mode 100644 index 00000000..277d32ce --- /dev/null +++ b/ranger/ext/img_display.py @@ -0,0 +1,79 @@ +# This software is distributed under the terms of the GNU GPL version 3. + +""" +This module provides functions to draw images in the terminal using +w3mimgdisplay, an utilitary program from w3m (a text-based web browser). +w3mimgdisplay can display images either in virtual tty (using linux +framebuffer) or in a Xorg session. + +w3m need to be installed for this to work. +""" + +import termios, fcntl, struct, sys +from subprocess import Popen, PIPE + +W3MIMGDISPLAY_PATH = '/usr/lib/w3m/w3mimgdisplay' + +def _get_font_dimensions(): + """ + Get the height and width of a character displayed in the terminal in + pixels. + """ + s = struct.pack("HHHH", 0, 0, 0, 0) + fd_stdout = sys.stdout.fileno() + x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s) + rows, cols, xpixels, ypixels = struct.unpack("HHHH", x) + + return (xpixels // cols), (ypixels // rows) + + +def _w3mimgdisplay(commands): + """ + Invoke w3mimgdisplay and send commands on its standard input. + """ + process = Popen(W3MIMGDISPLAY_PATH, stdin=PIPE, stdout=PIPE, + universal_newlines=True) + + # wait for the external program to finish + output, _ = process.communicate(input=commands) + + return output + +def draw(path, start_x, start_y, max_width, max_height): + """ + Draw an image file in the terminal. + + start_x, start_y, max_height and max_width specify the drawing area. + They are expressed in number of characters. + """ + fontw, fonth = _get_font_dimensions() + + max_width_pixels = max_width * fontw + max_height_pixels = max_height * fonth + + # get image size + cmd = "5;{}".format(path) + output = _w3mimgdisplay(cmd).split() + + if len(output) != 2: + raise Exception('Failed to execute w3mimgdisplay') + + width = int(output[0]) + height = int(output[1]) + + # get the maximum image size preserving ratio + if width > max_width_pixels: + height = (height * max_width_pixels) // width + width = max_width_pixels + if height > max_height_pixels: + width = (width * max_height_pixels) // height + height = max_height_pixels + + # draw + cmd = "0;1;{x};{y};{w};{h};;;;;{filename}\n4;\n3;".format( + x = start_x * fontw, + y = start_y * fonth, + w = width, + h = height, + filename = path) + _w3mimgdisplay(cmd) |