improve ImageShow docs

This commit is contained in:
nulano 2020-06-14 12:00:23 +02:00
parent 41a75210b5
commit 4a9afc79bf
4 changed files with 140 additions and 90 deletions

View File

@ -62,14 +62,6 @@ can be found here.
:undoc-members:
:show-inheritance:
:mod:`ImageShow` Module
-----------------------
.. automodule:: PIL.ImageShow
:members:
:undoc-members:
:show-inheritance:
:mod:`ImageTransform` Module
----------------------------

View File

@ -0,0 +1,27 @@
.. py:module:: PIL.ImageShow
.. py:currentmodule:: PIL.ImageShow
:py:mod:`ImageShow` Module
==========================
The :py:mod:`ImageShow` Module is used to display images.
All default viewers convert the image to be shown to PNG format.
.. autofunction:: PIL.ImageShow.show
.. autoclass:: WindowsViewer
.. autoclass:: MacViewer
.. class:: UnixViewer
The following viewers may be registered on Unix-based systems, if the given command is found:
.. autoclass:: PIL.ImageShow.DisplayViewer
.. autoclass:: PIL.ImageShow.EogViewer
.. autoclass:: PIL.ImageShow.XVViewer
.. autofunction:: PIL.ImageShow.register
.. autoclass:: PIL.ImageShow.Viewer
:member-order: bysource
:members:
:undoc-members:

View File

@ -22,6 +22,7 @@ Reference
ImagePath
ImageQt
ImageSequence
ImageShow
ImageStat
ImageTk
ImageWin

View File

@ -24,6 +24,14 @@ _viewers = []
def register(viewer, order=1):
"""
The :py:func:`register` function is used to register additional viewers.
:param viewer: The viewer to be registered.
:param order:
A negative integer to prepend this viewer to the list,
or a positive integer to append it.
"""
try:
if issubclass(viewer, Viewer):
viewer = viewer()
@ -40,9 +48,9 @@ def show(image, title=None, **options):
Display a given image.
:param image: An image object.
:param title: Optional title. Not all viewers can display the title.
: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.
:returns: ``True`` if a suitable viewer was found, ``False`` otherwise.
"""
for viewer in _viewers:
if viewer.show(image, title=title, **options):
@ -56,6 +64,10 @@ class Viewer:
# main api
def show(self, image, **options):
"""
The main function for displaying an image.
Converts the given image to the target format and displays it.
"""
# save temporary image to disk
if not (
@ -70,25 +82,31 @@ class Viewer:
# hook methods
format = None
"""The format to convert the image into."""
options = {}
"""Additional options used to convert the image."""
def get_format(self, image):
"""Return format name, or None to save as PGM/PPM"""
"""Return format name, or ``None`` to save as PGM/PPM."""
return self.format
def get_command(self, file, **options):
"""
Returns the command used to display the file.
Not implemented in the base class.
"""
raise NotImplementedError
def save_image(self, image):
"""Save to temporary file, and return filename"""
"""Save to temporary file and return filename."""
return image._dump(format=self.get_format(image), **self.options)
def show_image(self, image, **options):
"""Display given image"""
"""Display the given image."""
return self.show_file(self.save_image(image), **options)
def show_file(self, file, **options):
"""Display given file"""
"""Display the given file."""
os.system(self.get_command(file, **options))
return 1
@ -96,104 +114,116 @@ class Viewer:
# --------------------------------------------------------------------
class WindowsViewer(Viewer):
"""The default viewer on Windows is the default system application for PNG files."""
format = "PNG"
options = {"compress_level": 1}
def get_command(self, file, **options):
return (
'start "Pillow" /WAIT "%s" '
"&& ping -n 2 127.0.0.1 >NUL "
'&& del /f "%s"' % (file, file)
)
if sys.platform == "win32":
class WindowsViewer(Viewer):
format = "PNG"
options = {"compress_level": 1}
def get_command(self, file, **options):
return (
'start "Pillow" /WAIT "%s" '
"&& ping -n 2 127.0.0.1 >NUL "
'&& del /f "%s"' % (file, file)
)
register(WindowsViewer)
elif sys.platform == "darwin":
class MacViewer(Viewer):
format = "PNG"
options = {"compress_level": 1}
class MacViewer(Viewer):
"""The default viewer on MacOS using ``Preview.app``."""
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"
command = "({} {}; sleep 20; rm -f {})&".format(
command, quote(file), quote(file)
format = "PNG"
options = {"compress_level": 1}
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"
command = "({} {}; sleep 20; rm -f {})&".format(
command, quote(file), quote(file)
)
return command
def show_file(self, file, **options):
"""Display given file"""
fd, path = tempfile.mkstemp()
with os.fdopen(fd, "w") as f:
f.write(file)
with open(path, "r") as f:
subprocess.Popen(
["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"],
shell=True,
stdin=f,
)
return command
os.remove(path)
return 1
def show_file(self, file, **options):
"""Display given file"""
fd, path = tempfile.mkstemp()
with os.fdopen(fd, "w") as f:
f.write(file)
with open(path, "r") as f:
subprocess.Popen(
["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"],
shell=True,
stdin=f,
)
os.remove(path)
return 1
if sys.platform == "darwin":
register(MacViewer)
else:
# unixoids
class UnixViewer(Viewer):
format = "PNG"
options = {"compress_level": 1}
class UnixViewer(Viewer):
format = "PNG"
options = {"compress_level": 1}
def get_command(self, file, **options):
command = self.get_command_ex(file, **options)[0]
return "({} {}; rm -f {})&".format(command, quote(file), quote(file))
def get_command(self, file, **options):
def show_file(self, file, **options):
"""Display given file"""
fd, path = tempfile.mkstemp()
with os.fdopen(fd, "w") as f:
f.write(file)
with open(path, "r") as f:
command = self.get_command_ex(file, **options)[0]
return "({} {}; rm -f {})&".format(command, quote(file), quote(file))
subprocess.Popen(
["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f
)
os.remove(path)
return 1
def show_file(self, file, **options):
"""Display given file"""
fd, path = tempfile.mkstemp()
with os.fdopen(fd, "w") as f:
f.write(file)
with open(path, "r") as f:
command = self.get_command_ex(file, **options)[0]
subprocess.Popen(
["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f
)
os.remove(path)
return 1
# implementations
class DisplayViewer(UnixViewer):
"""The ImageMagick ``display`` command."""
class DisplayViewer(UnixViewer):
def get_command_ex(self, file, **options):
command = executable = "display"
return command, executable
def get_command_ex(self, file, **options):
command = executable = "display"
return command, executable
class EogViewer(UnixViewer):
"""The GNOME Image Viewer ``eog`` command."""
def get_command_ex(self, file, **options):
command = executable = "eog"
return command, executable
class XVViewer(UnixViewer):
"""
The X Viewer ``xv`` command.
This viewer supports the ``title`` parameter.
"""
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)
return command, executable
if sys.platform not in ("win32", "darwin"): # unixoids
if shutil.which("display"):
register(DisplayViewer)
class EogViewer(UnixViewer):
def get_command_ex(self, file, **options):
command = executable = "eog"
return command, executable
if shutil.which("eog"):
register(EogViewer)
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)
return command, executable
if shutil.which("xv"):
register(XVViewer)