2012-05-03 26 views
8

¿Hay alguna manera de leer en un archivo bmp en Python que no implique el uso de PIL? PIL no funciona con la versión 3, que es la que tengo. Traté de usar el objeto Image desde graphics.py, Image (anchorPoint, filename), pero eso solo parece funcionar con archivos gif.Lectura de archivos bmp en Python

+0

[Esta página] (http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil) dice tener Python 3 versiones compatibles de PIL. –

Respuesta

0

Depende de lo que intente lograr y en qué plataforma?

De todos modos, el uso de una biblioteca C para cargar BMP puede funcionar, p. http://code.google.com/p/libbmp/ o http://freeimage.sourceforge.net/, y las bibliotecas C se pueden llamar fácilmente desde python, p. usando ctypes o envolviéndolo como un módulo de python.

o se puede compilar esta versión del PIL https://github.com/sloonz/pil-py3k

+0

Ctypes es viable, y lo he usado y atado con él, pero tiende a producir soluciones relativamente frágiles, más que C en sí. Eso es porque la verificación de tipos podría ser mejor con ctypes. Para una API muy estable, los ctypes pueden ser bastante agradables (especialmente si quieres apuntar no solo a cpython sino también a pypy), pero cython podría ser mejor para muchas cosas si estás dispuesto a seguir con cpython. – user1277476

1

El puerto común de PIL a Python 3.x se llama "Pillow". También sugeriría la biblioteca pygame para tareas simples. Es una biblioteca, llena de funciones para crear juegos, y la lectura de algunos formatos de imagen comunes se encuentra entre ellos. Funciona con Python 3.x también.

10

En Python, simplemente se puede leer como:

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, en SciPy 1.0 [imread (etc.) se depreció y se eliminará en 1.2] (https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imsave.html#scipy. misc.imread); SciPy 1.2 usará 'imageio.imread' – uhoh

0

Soy consciente de que esto es una vieja pregunta, pero lo encontré en la resolución de este problema a mí mismo y me di cuenta de que esto podría ayudar a alguien más en el futuro .

En realidad es bastante fácil leer un archivo BMP como datos binarios. Dependiendo de qué tan amplio sea el soporte y la cantidad de casos de esquina que necesite para respaldar, por supuesto.

A continuación se muestra un analizador simple que SOLAMENTE funciona para 1920x1080 BMP de 24 bits (como los guardados de MS Paint). Sin embargo, debería ser fácil de ampliar. Escupe los valores de píxel como una lista de Python como (255, 0, 0, 255, 0, 0, ...) para una imagen roja como ejemplo.

Si necesita un soporte más robusto, hay información sobre cómo leer correctamente el encabezado en las respuestas a esta pregunta: How to read bmp file header in python?. Usando esa información, debería poder extender el analizador simple a continuación con cualquier característica que necesite.

También hay más información sobre el formato de archivo BMP en wikipedia https://en.wikipedia.org/wiki/BMP_file_format si lo necesita.

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)