Pillow/src/PIL/ImageShow.py

221 lines
5.8 KiB
Python
Raw Normal View History

2010-07-31 06:52:47 +04:00
#
# The Python Imaging Library.
# $Id$
#
# im.show() drivers
#
# History:
# 2008-04-06 fl Created
#
# Copyright (c) Secret Labs AB 2008.
#
# See the README file for information on usage and redistribution.
#
from __future__ import print_function
2014-08-26 17:47:10 +04:00
import os
import subprocess
import sys
import tempfile
2019-09-26 15:12:28 +03:00
from shlex import quote
2010-07-31 06:52:47 +04:00
from PIL import Image
2010-07-31 06:52:47 +04:00
_viewers = []
2014-08-26 17:47:10 +04:00
2010-07-31 06:52:47 +04:00
def register(viewer, order=1):
try:
if issubclass(viewer, Viewer):
viewer = viewer()
except TypeError:
2014-08-26 17:47:10 +04:00
pass # raised if viewer wasn't a class
2010-07-31 06:52:47 +04:00
if order > 0:
_viewers.append(viewer)
elif order < 0:
_viewers.insert(0, viewer)
2014-08-26 17:47:10 +04:00
2010-07-31 06:52:47 +04:00
def show(image, title=None, **options):
r"""
2016-05-24 10:36:14 +03:00
Display a given image.
:param image: An image object.
:param title: Optional title. Not all viewers can display the title.
:param \**options: Additional viewer options.
:returns: True if a suitable viewer was found, false otherwise.
2016-05-24 10:36:14 +03:00
"""
2010-07-31 06:52:47 +04:00
for viewer in _viewers:
if viewer.show(image, title=title, **options):
return 1
return 0
2014-08-26 17:47:10 +04:00
2015-05-26 17:07:21 +03:00
class Viewer(object):
2016-05-24 10:36:14 +03:00
"""Base class for viewers."""
2010-07-31 06:52:47 +04:00
# main api
def show(self, image, **options):
# save temporary image to disk
if not (
image.mode in ("1", "RGBA") or (self.format == "PNG" and image.mode == "LA")
):
2010-07-31 06:52:47 +04:00
base = Image.getmodebase(image.mode)
if image.mode != base:
image = image.convert(base)
2010-07-31 06:52:47 +04:00
return self.show_image(image, **options)
2010-07-31 06:52:47 +04:00
# hook methods
format = None
2017-05-13 16:08:08 +03:00
options = {}
2010-07-31 06:52:47 +04:00
def get_format(self, image):
2016-05-24 10:36:14 +03:00
"""Return format name, or None to save as PGM/PPM"""
2010-07-31 06:52:47 +04:00
return self.format
def get_command(self, file, **options):
raise NotImplementedError
def save_image(self, image):
2016-05-24 10:36:14 +03:00
"""Save to temporary file, and return filename"""
2017-05-13 16:08:08 +03:00
return image._dump(format=self.get_format(image), **self.options)
2010-07-31 06:52:47 +04:00
def show_image(self, image, **options):
2016-05-24 10:36:14 +03:00
"""Display given image"""
2010-07-31 06:52:47 +04:00
return self.show_file(self.save_image(image), **options)
def show_file(self, file, **options):
2016-05-24 10:36:14 +03:00
"""Display given file"""
2010-07-31 06:52:47 +04:00
os.system(self.get_command(file, **options))
return 1
2019-03-21 16:28:20 +03:00
2010-07-31 06:52:47 +04:00
# --------------------------------------------------------------------
2017-11-22 13:13:13 +03:00
2010-07-31 06:52:47 +04:00
if sys.platform == "win32":
class WindowsViewer(Viewer):
2019-08-16 12:43:28 +03:00
format = "PNG"
options = {"compress_level": 1}
2014-08-26 17:47:10 +04:00
2010-07-31 06:52:47 +04:00
def get_command(self, file, **options):
2019-03-21 16:28:20 +03:00
return (
'start "Pillow" /WAIT "%s" '
"&& ping -n 2 127.0.0.1 >NUL "
'&& del /f "%s"' % (file, file)
)
2010-07-31 06:52:47 +04:00
register(WindowsViewer)
elif sys.platform == "darwin":
class MacViewer(Viewer):
format = "PNG"
2019-03-21 16:28:20 +03:00
options = {"compress_level": 1}
2014-08-26 17:47:10 +04:00
2010-07-31 06:52:47 +04:00
def get_command(self, file, **options):
# on darwin open returns immediately resulting in the temp
# file removal while app is opening
command = "open -a Preview.app"
2019-03-21 16:28:20 +03:00
command = "(%s %s; sleep 20; rm -f %s)&" % (
command,
quote(file),
quote(file),
)
2010-07-31 06:52:47 +04:00
return command
def show_file(self, file, **options):
"""Display given file"""
2018-12-31 00:27:07 +03:00
fd, path = tempfile.mkstemp()
2019-03-21 16:28:20 +03:00
with os.fdopen(fd, "w") as f:
2018-12-31 00:27:07 +03:00
f.write(file)
with open(path, "r") as f:
2019-03-21 16:28:20 +03:00
subprocess.Popen(
["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"],
2019-03-21 16:28:20 +03:00
shell=True,
stdin=f,
)
os.remove(path)
return 1
2010-07-31 06:52:47 +04:00
register(MacViewer)
else:
# unixoids
def which(executable):
path = os.environ.get("PATH")
if not path:
return None
for dirname in path.split(os.pathsep):
filename = os.path.join(dirname, executable)
if os.path.isfile(filename) and os.access(filename, os.X_OK):
2010-07-31 06:52:47 +04:00
return filename
return None
class UnixViewer(Viewer):
format = "PNG"
2019-03-21 16:28:20 +03:00
options = {"compress_level": 1}
2018-11-03 05:13:04 +03:00
def get_command(self, file, **options):
command = self.get_command_ex(file, **options)[0]
return "(%s %s; rm -f %s)&" % (command, quote(file), quote(file))
2010-07-31 06:52:47 +04:00
def show_file(self, file, **options):
"""Display given file"""
2018-12-31 00:27:07 +03:00
fd, path = tempfile.mkstemp()
2019-03-21 16:28:20 +03:00
with os.fdopen(fd, "w") as f:
2018-12-31 00:27:07 +03:00
f.write(file)
with open(path, "r") as f:
command = self.get_command_ex(file, **options)[0]
2019-03-21 16:28:20 +03:00
subprocess.Popen(
2019-08-15 13:41:48 +03:00
["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f
2019-03-21 16:28:20 +03:00
)
os.remove(path)
return 1
2010-07-31 06:52:47 +04:00
# implementations
class DisplayViewer(UnixViewer):
def get_command_ex(self, file, **options):
command = executable = "display"
2010-07-31 06:52:47 +04:00
return command, executable
2017-11-22 13:13:13 +03:00
if which("display"):
register(DisplayViewer)
class EogViewer(UnixViewer):
def get_command_ex(self, file, **options):
command = executable = "eog"
return command, executable
2017-11-22 13:13:13 +03:00
if which("eog"):
register(EogViewer)
2010-07-31 06:52:47 +04:00
class XVViewer(UnixViewer):
def get_command_ex(self, file, title=None, **options):
# note: xv is pretty outdated. most modern systems have
# imagemagick's display command instead.
command = executable = "xv"
if title:
command += " -name %s" % quote(title)
2010-07-31 06:52:47 +04:00
return command, executable
if which("xv"):
register(XVViewer)
if __name__ == "__main__":
2018-01-06 13:51:45 +03:00
if len(sys.argv) < 2:
print("Syntax: python ImageShow.py imagefile [title]")
sys.exit()
print(show(Image.open(sys.argv[1]), *sys.argv[2:]))