summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/ext/img_display.py79
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)