# 
 | 
# 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:]) 
 |