Python Imaging Library (PIL)中ImageShow.py模組淺析

來源:互聯網
上載者:User

       最近想用Python做一些映像的處理,鑒於是Python菜鳥,所以只能依賴於一些現成的映像庫(PIL或者Opencv),這樣有助於快速開發。當然了,Python在影像處理方面還是很不錯的。

       這裡我用的是PIL1.1.7;運行環境是Unbuntu10.10;Python
2.6.6.

       對於剛剛接觸 PIL,還是有點迷茫的。因此,我就從最簡單的Image.show()開始

先來看一段代碼 :

import Imageimport sysim = Image.open('lena.BMP')print im.format, im.sizeim.show()

從代碼功能上看,得到結果應輸出的是:映像的格式、圖形的大小以及顯示映像

但是實際上會出現一個問題,映像顯示不出來,到底出了什麼情況呢?繼續往下看吧

我首先想到的是im.show()函數出現了些問題(大家也肯定會這麼想,事實上也是這樣的)。

要想瞭解im.show(),最直接有效方法就是找到im.show()函數。

在我的os上,這個函數在/usr/local/lib/python2.6/dist-packages/PIL/ImageShow.py裡面(可以通過locate ImageShow.py找到路徑)

先來看看整個檔案裡面有哪些東西吧!

import Imageimport 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)    return "start /wait %s && PING 127.0.0.1 -n 5 > NUL && 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:])

第80行之前都是函數和類定義,可以先跳過,我從第80行開始看。

第80行:判斷程式是否運行在win32平台上,由於我的平台是linux,所以答案是否定的,所以if裡面的代碼就先不管了(如果有興趣可以仔細琢磨一下)

接著到第90行:判斷是否是darwin平台(查了一下,好像是MAC,不確定),也不是我們要的,繼續...

第103行:終於到了我要找的了,從這裡103行到開始到第144行,又都是函數和類的定義,先跳過,待會看

第145行開始,進入正題了:if  which("xv") 成立,執行 register(XVViewer)。看了這麼久,我們要的就這麼兩句,一句話,真是”蛋疼的很“。好的,繼續

which(”xv“)到底是個什麼樣的函數呢?簡單的說就是,你的命令列裡面是否有"xv"這個指令.若有,執行語句

register(XVViewer).功能是將映像複製到一個臨時檔案夾,再調用xv指令來顯示映像。

上面這兩句才是這整個模組的精華啊!

程式就先讀到這裡

好了,問題來了,在ubuntu10.10中,有沒有xv指令呢?試一下就是的,指令不存在!!!

現在終於知道為什麼映像顯示不出來了,ubuntu中沒有xv指令來顯示映像,而是用eog指令顯示圖形的

接下來就是修改代碼,不用xv,而是用eog;很簡單,將代碼中出現xv的地方,都換成eog就行了。搞定!!!

在說明一下,上面很多代碼都是在為了適應不同平台,而採取不同的調用指令,我現在在Ubuntu中(Linux),所以,其他平台的語句都可以刪去不要。因此整個模組可以改為一下的樣子:

#import Imageimport 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# --------------------------------------------------------------------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):#get the program of opening the image                # FIXME: make sure it's executable            return filename    return Noneclass 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 1class LinuxViewer(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 = "eog"        if title:                # FIXME: do full escaping            command = command + " -name \"%s\"" % title        return command, executableif which("eog"):print "aaa"register(LinuxViewer) 
 
續:上面是在ubuntu上實現的,接下來是在win7實現
       win7上出現的問題也是在圖片的調用指令上:
if sys.platform == "win32":    class WindowsViewer(Viewer):        format = "BMP"        def get_command(self, file, **options):                        return "start /wait %s && del /f %s" % (file,file)            #return "start /wait %s" % file    register(WindowsViewer)
這是原始碼中調用圖片顯示的dos指令,如果按照這個程式運行,將會出現”圖片不存在,無法發開圖片“,至少在我的電腦上是這樣的。
解決的辦法很簡單(花了好大力氣想到的辦法),只要做一下簡單的修改就可以了。
將return "start /wait %s && del /f %s" % (file,file) 修改為
  return "start /wait %s && del /wait /f %s" % (file,file)
    就是在del後面加個/wait 就可以了,其它都不需要改
 
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.