| # | 
| # 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. | 
| # | 
|   | 
| import Image | 
| import os, sys | 
|   | 
| _viewers = [] | 
|   | 
| def register(viewer, order=1): | 
|     try: | 
|         if issubclass(viewer, Viewer): | 
|             viewer = viewer() | 
|     except TypeError: | 
|         pass # raised if viewer wasn't a class | 
|     if order > 0: | 
|         _viewers.append(viewer) | 
|     elif order < 0: | 
|         _viewers.insert(0, viewer) | 
|   | 
| ## | 
| # Displays a given image. | 
| # | 
| # @param image An image object. | 
| # @param title Optional title.  Not all viewers can display the title. | 
| # @param **options Additional viewer options. | 
| # @return True if a suitable viewer was found, false otherwise. | 
|   | 
| def show(image, title=None, **options): | 
|     for viewer in _viewers: | 
|         if viewer.show(image, title=title, **options): | 
|             return 1 | 
|     return 0 | 
|   | 
| ## | 
| # Base class for viewers. | 
|   | 
| class Viewer: | 
|   | 
|     # main api | 
|   | 
|     def show(self, image, **options): | 
|   | 
|         # save temporary image to disk | 
|         if image.mode[:4] == "I;16": | 
|             # @PIL88 @PIL101 | 
|             # "I;16" isn't an 'official' mode, but we still want to | 
|             # provide a simple way to show 16-bit images. | 
|             base = "L" | 
|             # FIXME: auto-contrast if max() > 255? | 
|         else: | 
|             base = Image.getmodebase(image.mode) | 
|         if base != image.mode and image.mode != "1": | 
|             image = image.convert(base) | 
|   | 
|         self.show_image(image, **options) | 
|   | 
|     # hook methods | 
|   | 
|     format = None | 
|   | 
|     def get_format(self, image): | 
|         # return format name, or None to save as PGM/PPM | 
|         return self.format | 
|   | 
|     def get_command(self, file, **options): | 
|         raise NotImplementedError | 
|   | 
|     def save_image(self, image): | 
|         # save to temporary file, and return filename | 
|         return image._dump(format=self.get_format(image)) | 
|   | 
|     def show_image(self, image, **options): | 
|         # display given image | 
|         return self.show_file(self.save_image(image), **options) | 
|   | 
|     def show_file(self, file, **options): | 
|         # display given file | 
|         os.system(self.get_command(file, **options)) | 
|         return 1 | 
|   | 
| # -------------------------------------------------------------------- | 
|   | 
| if sys.platform == "win32": | 
|   | 
|     class WindowsViewer(Viewer): | 
|         format = "BMP" | 
|         def get_command(self, file, **options): | 
|             return "start /wait %s && del /f %s" % (file, file) | 
|   | 
|     register(WindowsViewer) | 
|   | 
| elif sys.platform == "darwin": | 
|   | 
|     class MacViewer(Viewer): | 
|         format = "BMP" | 
|         def get_command(self, file, **options): | 
|             # on darwin open returns immediately resulting in the temp | 
|             # file removal while app is opening | 
|             command = "open -a /Applications/Preview.app" | 
|             command = "(%s %s; sleep 20; rm -f %s)&" % (command, file, file) | 
|             return command | 
|   | 
|     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): | 
|                 # FIXME: make sure it's executable | 
|                 return filename | 
|         return None | 
|   | 
|     class UnixViewer(Viewer): | 
|         def show_file(self, file, **options): | 
|             command, executable = self.get_command_ex(file, **options) | 
|             command = "(%s %s; rm -f %s)&" % (command, file, file) | 
|             os.system(command) | 
|             return 1 | 
|   | 
|     # implementations | 
|   | 
|     class DisplayViewer(UnixViewer): | 
|         def get_command_ex(self, file, **options): | 
|             command = executable = "display" | 
|             return command, executable | 
|   | 
|     if which("display"): | 
|         register(DisplayViewer) | 
|   | 
|     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: | 
|                 # FIXME: do full escaping | 
|                 command = command + " -name \"%s\"" % title | 
|             return command, executable | 
|   | 
|     if which("xv"): | 
|         register(XVViewer) | 
|   | 
| if __name__ == "__main__": | 
|     # usage: python ImageShow.py imagefile [title] | 
|     print show(Image.open(sys.argv[1]), *sys.argv[2:]) |