ImageShow.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. import os
  16. import subprocess
  17. import sys
  18. import tempfile
  19. from PIL import Image
  20. if sys.version_info.major >= 3:
  21. from shlex import quote
  22. else:
  23. from pipes import quote
  24. _viewers = []
  25. def register(viewer, order=1):
  26. try:
  27. if issubclass(viewer, Viewer):
  28. viewer = viewer()
  29. except TypeError:
  30. pass # raised if viewer wasn't a class
  31. if order > 0:
  32. _viewers.append(viewer)
  33. elif order < 0:
  34. _viewers.insert(0, viewer)
  35. def show(image, title=None, **options):
  36. r"""
  37. Display a given image.
  38. :param image: An image object.
  39. :param title: Optional title. Not all viewers can display the title.
  40. :param \**options: Additional viewer options.
  41. :returns: True if a suitable viewer was found, false otherwise.
  42. """
  43. for viewer in _viewers:
  44. if viewer.show(image, title=title, **options):
  45. return 1
  46. return 0
  47. class Viewer(object):
  48. """Base class for viewers."""
  49. # main api
  50. def show(self, image, **options):
  51. # save temporary image to disk
  52. if not (
  53. image.mode in ("1", "RGBA") or (self.format == "PNG" and image.mode == "LA")
  54. ):
  55. base = Image.getmodebase(image.mode)
  56. if image.mode != base:
  57. image = image.convert(base)
  58. return self.show_image(image, **options)
  59. # hook methods
  60. format = None
  61. options = {}
  62. def get_format(self, image):
  63. """Return format name, or None to save as PGM/PPM"""
  64. return self.format
  65. def get_command(self, file, **options):
  66. raise NotImplementedError
  67. def save_image(self, image):
  68. """Save to temporary file, and return filename"""
  69. return image._dump(format=self.get_format(image), **self.options)
  70. def show_image(self, image, **options):
  71. """Display given image"""
  72. return self.show_file(self.save_image(image), **options)
  73. def show_file(self, file, **options):
  74. """Display given file"""
  75. os.system(self.get_command(file, **options))
  76. return 1
  77. # --------------------------------------------------------------------
  78. if sys.platform == "win32":
  79. class WindowsViewer(Viewer):
  80. format = "PNG"
  81. options = {"compress_level": 1}
  82. def get_command(self, file, **options):
  83. return (
  84. 'start "Pillow" /WAIT "%s" '
  85. "&& ping -n 2 127.0.0.1 >NUL "
  86. '&& del /f "%s"' % (file, file)
  87. )
  88. register(WindowsViewer)
  89. elif sys.platform == "darwin":
  90. class MacViewer(Viewer):
  91. format = "PNG"
  92. options = {"compress_level": 1}
  93. def get_command(self, file, **options):
  94. # on darwin open returns immediately resulting in the temp
  95. # file removal while app is opening
  96. command = "open -a Preview.app"
  97. command = "(%s %s; sleep 20; rm -f %s)&" % (
  98. command,
  99. quote(file),
  100. quote(file),
  101. )
  102. return command
  103. def show_file(self, file, **options):
  104. """Display given file"""
  105. fd, path = tempfile.mkstemp()
  106. with os.fdopen(fd, "w") as f:
  107. f.write(file)
  108. with open(path, "r") as f:
  109. subprocess.Popen(
  110. ["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"],
  111. shell=True,
  112. stdin=f,
  113. )
  114. os.remove(path)
  115. return 1
  116. register(MacViewer)
  117. else:
  118. # unixoids
  119. def which(executable):
  120. path = os.environ.get("PATH")
  121. if not path:
  122. return None
  123. for dirname in path.split(os.pathsep):
  124. filename = os.path.join(dirname, executable)
  125. if os.path.isfile(filename) and os.access(filename, os.X_OK):
  126. return filename
  127. return None
  128. class UnixViewer(Viewer):
  129. format = "PNG"
  130. options = {"compress_level": 1}
  131. def get_command(self, file, **options):
  132. command = self.get_command_ex(file, **options)[0]
  133. return "(%s %s; rm -f %s)&" % (command, quote(file), quote(file))
  134. def show_file(self, file, **options):
  135. """Display given file"""
  136. fd, path = tempfile.mkstemp()
  137. with os.fdopen(fd, "w") as f:
  138. f.write(file)
  139. with open(path, "r") as f:
  140. command = self.get_command_ex(file, **options)[0]
  141. subprocess.Popen(
  142. ["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f
  143. )
  144. os.remove(path)
  145. return 1
  146. # implementations
  147. class DisplayViewer(UnixViewer):
  148. def get_command_ex(self, file, **options):
  149. command = executable = "display"
  150. return command, executable
  151. if which("display"):
  152. register(DisplayViewer)
  153. class EogViewer(UnixViewer):
  154. def get_command_ex(self, file, **options):
  155. command = executable = "eog"
  156. return command, executable
  157. if which("eog"):
  158. register(EogViewer)
  159. class XVViewer(UnixViewer):
  160. def get_command_ex(self, file, title=None, **options):
  161. # note: xv is pretty outdated. most modern systems have
  162. # imagemagick's display command instead.
  163. command = executable = "xv"
  164. if title:
  165. command += " -name %s" % quote(title)
  166. return command, executable
  167. if which("xv"):
  168. register(XVViewer)
  169. if __name__ == "__main__":
  170. if len(sys.argv) < 2:
  171. print("Syntax: python ImageShow.py imagefile [title]")
  172. sys.exit()
  173. print(show(Image.open(sys.argv[1]), *sys.argv[2:]))