You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.1 KiB

4 years ago
  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # im.show() drivers
  6. #
  7. # History:
  8. # 2008-04-06 fl Created
  9. #
  10. # Copyright (c) Secret Labs AB 2008.
  11. #
  12. # See the README file for information on usage and redistribution.
  13. #
  14. from __future__ import print_function
  15. from PIL import Image
  16. import os
  17. import sys
  18. if sys.version_info.major >= 3:
  19. from shlex import quote
  20. else:
  21. from pipes import quote
  22. _viewers = []
  23. def register(viewer, order=1):
  24. try:
  25. if issubclass(viewer, Viewer):
  26. viewer = viewer()
  27. except TypeError:
  28. pass # raised if viewer wasn't a class
  29. if order > 0:
  30. _viewers.append(viewer)
  31. elif order < 0:
  32. _viewers.insert(0, viewer)
  33. def show(image, title=None, **options):
  34. r"""
  35. Display a given image.
  36. :param image: An image object.
  37. :param title: Optional title. Not all viewers can display the title.
  38. :param \**options: Additional viewer options.
  39. :returns: True if a suitable viewer was found, false otherwise.
  40. """
  41. for viewer in _viewers:
  42. if viewer.show(image, title=title, **options):
  43. return 1
  44. return 0
  45. class Viewer(object):
  46. """Base class for viewers."""
  47. # main api
  48. def show(self, image, **options):
  49. # save temporary image to disk
  50. if image.mode[:4] == "I;16":
  51. # @PIL88 @PIL101
  52. # "I;16" isn't an 'official' mode, but we still want to
  53. # provide a simple way to show 16-bit images.
  54. base = "L"
  55. # FIXME: auto-contrast if max() > 255?
  56. else:
  57. base = Image.getmodebase(image.mode)
  58. if base != image.mode and image.mode != "1" and image.mode != "RGBA":
  59. image = image.convert(base)
  60. return self.show_image(image, **options)
  61. # hook methods
  62. format = None
  63. options = {}
  64. def get_format(self, image):
  65. """Return format name, or None to save as PGM/PPM"""
  66. return self.format
  67. def get_command(self, file, **options):
  68. raise NotImplementedError
  69. def save_image(self, image):
  70. """Save to temporary file, and return filename"""
  71. return image._dump(format=self.get_format(image), **self.options)
  72. def show_image(self, image, **options):
  73. """Display given image"""
  74. return self.show_file(self.save_image(image), **options)
  75. def show_file(self, file, **options):
  76. """Display given file"""
  77. os.system(self.get_command(file, **options))
  78. return 1
  79. # --------------------------------------------------------------------
  80. if sys.platform == "win32":
  81. class WindowsViewer(Viewer):
  82. format = "BMP"
  83. def get_command(self, file, **options):
  84. return ('start "Pillow" /WAIT "%s" '
  85. '&& ping -n 2 127.0.0.1 >NUL '
  86. '&& del /f "%s"' % (file, file))
  87. register(WindowsViewer)
  88. elif sys.platform == "darwin":
  89. class MacViewer(Viewer):
  90. format = "PNG"
  91. options = {'compress_level': 1}
  92. def get_command(self, file, **options):
  93. # on darwin open returns immediately resulting in the temp
  94. # file removal while app is opening
  95. command = "open -a /Applications/Preview.app"
  96. command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file),
  97. quote(file))
  98. return command
  99. register(MacViewer)
  100. else:
  101. # unixoids
  102. def which(executable):
  103. path = os.environ.get("PATH")
  104. if not path:
  105. return None
  106. for dirname in path.split(os.pathsep):
  107. filename = os.path.join(dirname, executable)
  108. if os.path.isfile(filename) and os.access(filename, os.X_OK):
  109. return filename
  110. return None
  111. class UnixViewer(Viewer):
  112. format = "PNG"
  113. options = {'compress_level': 1}
  114. def show_file(self, file, **options):
  115. command, executable = self.get_command_ex(file, **options)
  116. command = "(%s %s; rm -f %s)&" % (command, quote(file),
  117. quote(file))
  118. os.system(command)
  119. return 1
  120. # implementations
  121. class DisplayViewer(UnixViewer):
  122. def get_command_ex(self, file, **options):
  123. command = executable = "display"
  124. return command, executable
  125. if which("display"):
  126. register(DisplayViewer)
  127. class EogViewer(UnixViewer):
  128. def get_command_ex(self, file, **options):
  129. command = executable = "eog"
  130. return command, executable
  131. if which("eog"):
  132. register(EogViewer)
  133. class XVViewer(UnixViewer):
  134. def get_command_ex(self, file, title=None, **options):
  135. # note: xv is pretty outdated. most modern systems have
  136. # imagemagick's display command instead.
  137. command = executable = "xv"
  138. if title:
  139. command += " -name %s" % quote(title)
  140. return command, executable
  141. if which("xv"):
  142. register(XVViewer)
  143. if __name__ == "__main__":
  144. if len(sys.argv) < 2:
  145. print("Syntax: python ImageShow.py imagefile [title]")
  146. sys.exit()
  147. print(show(Image.open(sys.argv[1]), *sys.argv[2:]))