2012-05-03 15 views
8

Gibt es eine Möglichkeit, in Python eine BMP-Datei einzulesen, die keine Verwendung von PIL erfordert? PIL funktioniert nicht mit der Version 3, die ich habe. Ich habe versucht, das Image-Objekt von graphics.py, Image (anchorPoint, Dateiname) zu verwenden, aber das scheint nur mit gif-Dateien zu funktionieren.Lesen von BMP-Dateien in Python

+0

[Diese Seite] (http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil) behauptet, Python 3 kompatible Versionen von PIL zu haben. –

Antwort

0

Es hängt davon ab, was Sie erreichen möchten und auf welcher Plattform?

Anyway mit einer C-Bibliothek zum Laden BMP kann funktionieren, z. http://code.google.com/p/libbmp/ oder http://freeimage.sourceforge.net/, und C-Bibliotheken können leicht von Python aufgerufen werden, z.B. Ctypes verwenden oder es als Python-Modul umschließen.

oder Sie können diese Version von PIL kompilieren https://github.com/sloonz/pil-py3k

+0

Ctypes ist lebensfähig, und ich habe es verwendet und bin dabei geblieben, aber es neigt dazu, relativ spröde Lösungen zu produzieren - mehr als C selbst. Das liegt daran, dass die Typprüfung bei Ctypes besser sein könnte. Für eine sehr stabile API können ctypes ziemlich nett sein (besonders wenn Sie nicht nur cpython, sondern auch pypy zielen wollen), aber Cython könnte eigentlich für viele Dinge besser sein, wenn Sie bereit sind, bei cpython zu bleiben. – user1277476

1

Der gemeinsame Port von PIL zu Python 3.x heißt "Pillow". Auch ich würde Pygame-Bibliothek für einfache Aufgaben vorschlagen. Es ist eine Bibliothek, voll von Funktionen zum Erstellen von Spielen - und Lesen von einigen gängigen Bildformaten ist unter ihnen. Funktioniert auch mit Python 3.x.

10

In Python kann es einfach als gelesen werden:

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

Hinweis, in SciPy 1.0 [imread (etc.) wird abgeschrieben und wird in 1.2 entfernt] (https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imsave.html#scipy. misc.imread); SciPy 1.2 wird 'imageio.imread' verwenden – uhoh

0

Ich weiß, dass dies eine alte Frage, aber ich fand es, wenn dieses Problem selbst zu lösen, und ich dachte, dass dies jemand anderes in der Zukunft helfen könnte .

Es ist ziemlich einfach, tatsächlich eine BMP-Datei als Binärdaten zu lesen. Abhängig davon, wie breit Support und wie viele Corner-Cases Sie natürlich unterstützen müssen.

Unten ist ein einfacher Parser, der NUR für 1920x1080 24-Bit-BMPs funktioniert (wie von MS Paint gespeichert). Es sollte jedoch einfach zu erweitern sein. Es spuckt die Pixelwerte als eine Python-Liste wie (255, 0, 0, 255, 0, 0, ...) für ein rotes Bild als Beispiel aus.

Wenn Sie robustere Unterstützung benötigen, gibt es Informationen darüber, wie Sie die Kopfzeile in Antworten auf diese Frage richtig lesen können: How to read bmp file header in python?. Mit diesen Informationen sollten Sie in der Lage sein, den unten stehenden einfachen Parser mit den von Ihnen benötigten Funktionen zu erweitern.

Es gibt auch mehr Informationen über das BMP-Dateiformat über bei Wikipedia https://en.wikipedia.org/wiki/BMP_file_format, wenn Sie es brauchen.

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)