import numpy as np import struct from PIL import Image class ImageFile(): def getBMP(self, filepath): # 先將位圖打開 f = open(filepath,'rb') # 打開對應的文件 # 下面部分用來讀取BMP位圖的基礎信息 f_type = str(f.read(2)) # 這個就可以用來讀取 文件類型 需要讀取2個字節 file_size_byte = f.read(4) # 這個可以用來讀取文件的大小 需要讀取4個字節 f.seek(f.tell()+4) # 跳過中間無用的四個字節 file_ofset_byte = f.read(4) # 讀取位圖數據的偏移量 f.seek(f.tell()+4) # 跳過無用的兩個字節 file_wide_byte = f.read(4) # 讀取寬度字節 file_height_byte = f.read(4) # 讀取高度字節 f.seek(f.tell()+2) # 跳過中間無用的兩個字節 file_bitcount_byte = f.read(4) # 得到每個像素占位大小 #下面就是將讀取的字節轉換成指定的類型 f_size, = struct.unpack('i', file_size_byte) f_ofset, = struct.unpack('i', file_ofset_byte) f_wide, = struct.unpack('i', file_wide_byte) f_height, = struct.unpack('i', file_height_byte) f_bitcount, = struct.unpack('i', file_bitcount_byte) print("類型:", f_type, "大小:", f_size, "位圖數據偏移量:", f_ofset, "寬度:", f_wide, "高度:", f_height, "位圖:", f_bitcount) # 然后來讀取顏色表 color_table = np.empty(shape=[256, 4], dtype=int) f.seek(54) #跳過文件信息頭和位圖信息頭 for i in range(0, 256): b=struct.unpack('B', f.read(1))[0] g = struct.unpack('B', f.read(1))[0] r = struct.unpack('B', f.read(1))[0] alpha = struct.unpack('B', f.read(1))[0] color_table[i][0] = r color_table[i][1] = g color_table[i][2] = b color_table[i][3] = 255 # 下面部分用來讀取BMP位圖數據區域,將數據存入numpy數組 # 首先對文件指針進行偏移 f.seek(f_ofset) # 因為圖像是8位偽彩色圖像,所以一個像素點占一個字節,即8位 img = np.empty(shape=[f_height, f_wide, 4], dtype=int) cout = 0 """ 然后就是來讀取位圖數據了,讀取位圖數據的時候,我們一定要注意, 數據的排列方式是從左到右,從下到上! 還有一個while循環,是用來判斷行像素是否為4的倍數, 如果不是我們還要將填充的用字節給讀取扔掉 """ for y in range(0, f_height): for x in range(0,f_wide): cout = cout + 1 index = struct.unpack('B', f.read(1))[0] img[f_height - y - 1, x] = color_table[index] while cout % 4 != 0: f.read(1) cout = cout+1 f.close() return img def ndarry2image(self, ndarry): # ndarray 轉 圖片 ndarry = ndarry.astype("uint8") # ndarry = cv2.cvtColor(ndarry, cv2.COLOR_BGR2RGB) ndarry = Image.fromarray(ndarry) ndarry = ndarry.toqpixmap() return ndarry