2012-05-03 703 views
8

有沒有辦法在Python中讀取不涉及使用PIL的bmp文件? PIL不適用於我擁有的版本3。我試圖從graphics.py,Image(anchorPoint,filename)使用Image對象,但似乎只能使用gif文件。在Python中讀取bmp文件

+0

[本頁](http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil)聲稱有PIL的Python 3個的兼容版本。 –

回答

0

這取決於你想要達到的目標以及在哪個平臺上?

無論如何,使用C庫來加載BMP可能工作,例如, http://code.google.com/p/libbmp/http://freeimage.sourceforge.net/,並且可以從python容易地調用C庫,例如使用ctypes或將其封裝爲python模塊。

或者如果你在Windows這樣做,你可以編譯這個版本PIL https://github.com/sloonz/pil-py3k

+0

Ctypes是可行的,我已經使用它,並堅持下去,但它往往會產生相對脆弱的解決方案 - 比C本身更重要。這是因爲ctypes的類型檢查可能會更好。對於一個非常穩定的API,ctypes可以是相當不錯的(特別是如果你不想只針對cpython,而且還需要pypy),但是如果你願意堅持使用cpython,cython可能會對許多事情更好。 – user1277476

1

PIL到Python 3.x的公共端口被稱爲「Pillow」。 另外我會建議pygame庫的簡單任務。這是一個圖書館,充滿了創造遊戲的功能 - 其中包括一些常見圖像格式的閱讀。同樣適用於Python 3.x。

10

在Python可以簡單地理解爲:

import os 
from scipy import misc 
path = 'your_file_path' 
image= misc.imread(os.path.join(path,'image.bmp'), flatten= 0) 

## flatten=0 if image is required as it is 
## flatten=1 to flatten the color layers into a single gray-scale layer 
+0

請注意,在SciPy 1.0 [imread(etc.)已折舊並將在1.2中刪除](https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imsave.html#scipy。 misc.imread); SciPy 1.2將使用'imageio.imread' – uhoh

0

我意識到這是一個老問題,但我發現它解決這個問題我自己,當我想通這可能幫助別人,將來別人。

實際上,將BMP文件讀取爲二進制數據非常容易。取決於當然需要支持多大的支持和多少角落案例。

下面是一個簡單的解析器,僅適用於1920x1080 24位BMP(如從MS Paint保存的)。應該很容易擴展。作爲一個例子,它將像素值作爲一個像紅色圖像的(255, 0, 0, 255, 0, 0, ...)這樣的python列表進行吐出。

如果您需要更強大的支持,那麼有關於如何正確讀取此問題答案的標題的信息:How to read bmp file header in python?。使用這些信息,您應該可以使用您需要的任何功能擴展下面的簡單解析器。

如果您需要它,還可以在維基百科https://en.wikipedia.org/wiki/BMP_file_format上查看BMP文件格式的更多信息。

def read_rows(path): 
    image_file = open(path, "rb") 
    # Blindly skip the BMP header. 
    image_file.seek(54) 

    # We need to read pixels in as rows to later swap the order 
    # since BMP stores pixels starting at the bottom left. 
    rows = [] 
    row = [] 
    pixel_index = 0 

    while True: 
     if pixel_index == 1920: 
      pixel_index = 0 
      rows.insert(0, row) 
      if len(row) != 1920 * 3: 
       raise Exception("Row length is not 1920*3 but " + str(len(row)) + "/3.0 = " + str(len(row)/3.0)) 
      row = [] 
     pixel_index += 1 

     r_string = image_file.read(1) 
     g_string = image_file.read(1) 
     b_string = image_file.read(1) 

     if len(r_string) == 0: 
      # This is expected to happen when we've read everything. 
      if len(rows) != 1080: 
       print "Warning!!! Read to the end of the file at the correct sub-pixel (red) but we've not read 1080 rows!" 
      break 

     if len(g_string) == 0: 
      print "Warning!!! Got 0 length string for green. Breaking." 
      break 

     if len(b_string) == 0: 
      print "Warning!!! Got 0 length string for blue. Breaking." 
      break 

     r = ord(r_string) 
     g = ord(g_string) 
     b = ord(b_string) 

     row.append(b) 
     row.append(g) 
     row.append(r) 

    image_file.close() 

    return rows 

def repack_sub_pixels(rows): 
    print "Repacking pixels..." 
    sub_pixels = [] 
    for row in rows: 
     for sub_pixel in row: 
      sub_pixels.append(sub_pixel) 

    diff = len(sub_pixels) - 1920 * 1080 * 3 
    print "Packed", len(sub_pixels), "sub-pixels." 
    if diff != 0: 
     print "Error! Number of sub-pixels packed does not match 1920*1080: (" + str(len(sub_pixels)) + " - 1920 * 1080 * 3 = " + str(diff) +")." 

    return sub_pixels 

rows = read_rows("my image.bmp") 

# This list is raw sub-pixel values. A red image is for example (255, 0, 0, 255, 0, 0, ...). 
sub_pixels = repack_sub_pixels(rows)