在Python中读取bmp文件

Xin*_*min 11 python python-3.x

有没有办法在Python中读取不涉及使用PIL的bmp文件?PIL不适用于我拥有的版本3.我试图使用来自graphics.py,Image(anchorPoint,filename)的Image对象,但这似乎只适用于gif文件.

Ash*_*ish 13

在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
Run Code Online (Sandbox Code Playgroud)

  • 注意,在SciPy 1.0中[imread(等)被折旧并将在1.2中删除](https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imsave.html#scipy.misc .imread); SciPy 1.2将使用`imageio.imread` (3认同)

Seb*_*ryd 7

我意识到这是一个老问题,但我在自己解决这个问题时发现了它,我认为这可能会在未来帮助其他人。

实际上将 BMP 文件作为二进制数据读取非常容易。当然,这取决于支持的广泛程度和您需要支持的极端情况的数量。

下面是一个简单的解析器,它只适用于 1920x1080 24 位 BMP(就像从 MS Paint 中保存的那些)。不过应该很容易扩展。它以 python 列表的形式输出像素值,例如(255, 0, 0, 255, 0, 0, ...)以红色图像为例。

如果您需要更强大的支持,可以在以下问题的答案中找到有关如何正确读取标头的信息: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)
Run Code Online (Sandbox Code Playgroud)


Chr*_*ein 7

为此使用枕头。安装后只需导入它

from PIL import Image
Run Code Online (Sandbox Code Playgroud)

然后就可以加载BMP文件了

img = Image.open('path_to_file\file.bmp')
Run Code Online (Sandbox Code Playgroud)

如果您需要图像是 numpy 数组,请使用np.array

img = np.array(Image.open('path_to_file\file.bmp'))
Run Code Online (Sandbox Code Playgroud)

numpy 数组只是一维的。reshape()如果您的图像是 RGB,则用于将其调整为正确的形状。例如:

np.array(Image.open('path_to_file\file.bmp')).reshape(512,512,3)
Run Code Online (Sandbox Code Playgroud)


Anu*_*yal 1

这取决于您想要实现的目标以及在哪个平台上实现?

无论如何,使用 C 库加载 BMP 可能会起作用,例如http://code.google.com/p/libbmp/http://freeimage.sourceforge.net/,并且可以轻松地从 python 调用 C 库,例如使用 ctypes 或将其包装为 python 模块。

或者你可以编译这个版本的PIL https://github.com/sloonz/pil-py3k