2012-05-03 16 views
8

C'è un modo per leggere in un file bmp in Python che non implichi l'utilizzo di PIL? PIL non funziona con la versione 3, che è quella che ho. Ho provato ad usare l'oggetto Image da graphics.py, Image (anchorPoint, filename), ma sembra funzionare solo con i file gif.Lettura di file bmp in Python

+0

[Questa pagina] (http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil) afferma di avere versioni compatibili di Python 3 di PIL. –

risposta

0

Dipende da cosa stai cercando di raggiungere e su quale piattaforma?

Ad ogni modo, l'utilizzo di una libreria C per caricare BMP può funzionare ad es. http://code.google.com/p/libbmp/ o http://freeimage.sourceforge.net/ e le librerie C possono essere facilmente richiamate da python, ad es. usando i ctype o avvolgendoli come un modulo python.

oppure è possibile compilare questa versione del PIL https://github.com/sloonz/pil-py3k

+0

Ctypes è praticabile, e l'ho usato e bloccato con esso, ma tende a produrre soluzioni relativamente fragili - più di C stesso. Questo perché il controllo del tipo potrebbe essere migliore con i tipi. Per un'API molto stabile, i ctypes possono essere abbastanza carini (specialmente se si desidera indirizzare non solo cpython ma anche pypy), ma cython potrebbe effettivamente essere migliore per molte cose se si è disposti ad attaccare con cpython. – user1277476

1

La porta comune di PIL a Python 3.x si chiama "Cuscino". Inoltre suggerirei la libreria pygame per compiti semplici. È una libreria piena di funzionalità per la creazione di giochi, e tra questi anche la lettura da alcuni formati di immagine comuni. Funziona anche con Python 3.x.

10

In Python può essere semplicemente letto come:

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

Nota, in SciPy 1.0 [imread (ecc.) È ammortizzato e verrà rimosso in 1.2] (https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imsave.html#scipy. misc.imread); SciPy 1.2 userà 'imageio.imread' – uhoh

0

Mi rendo conto che questa è una vecchia questione, ma ho trovato quando la soluzione di questo problema me stesso e ho pensato che questo potrebbe aiutare qualcun altro in futuro .

In realtà è davvero facile leggere un file BMP come dati binari. A seconda di quanto ampio supporto e quanti casi d'angolo è necessario sostenere, naturalmente.

Di seguito è riportato un semplice parser che funziona SOLO per i BMP a 24 bit a 1920x1080 (come quelli salvati da MS Paint). Dovrebbe essere facile da estendere però. Spiega i valori dei pixel come un elenco python come (255, 0, 0, 255, 0, 0, ...) per un'immagine rossa come esempio.

Se è necessario un supporto più affidabile, sono disponibili informazioni su come leggere correttamente l'intestazione nelle risposte a questa domanda: How to read bmp file header in python?. Usando queste informazioni dovresti essere in grado di estendere il semplice parser qui sotto con tutte le funzionalità che ti servono.

Ci sono anche ulteriori informazioni sul formato di file BMP su wikipedia https://en.wikipedia.org/wiki/BMP_file_format se ne avete bisogno.

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)