Reading bmp files in Python

前端 未结 7 1276
北荒
北荒 2021-02-19 01:41

Is there a way to read in a bmp file in Python that does not involve using PIL? PIL doesn\'t work with version 3, which is the one I have. I tried to use the Image object from g

7条回答
  •  别那么骄傲
    2021-02-19 02:04

    I realize that this is an old question, but I found it when solving this problem myself and I figured that this might help someone else in the future.

    It's pretty easy actually to read a BMP file as binary data. Depending on how broad support and how many corner-cases you need to support of course.

    Below is a simple parser that ONLY works for 1920x1080 24-bit BMP's (like ones saved from MS Paint). It should be easy to extend though. It spits out the pixel values as a python list like (255, 0, 0, 255, 0, 0, ...) for a red image as an example.

    If you need more robust support there's information on how to properly read the header in answers to this question: How to read bmp file header in python?. Using that information you should be able to extend the simple parser below with any features you need.

    There's also more information on the BMP file format over at wikipedia https://en.wikipedia.org/wiki/BMP_file_format if you need it.

    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)
    

提交回复
热议问题