ちまたに書籍が溢れているので,詳しくはそちらをどうぞ.
画像ファイルを読み込むだけなら,OpenCVなどのパッケージを使いましょう.
ここでは,.bmp ファイルの構造のお勉強目的でのサンプルです.
以下は,ヘッダをファイルからまともに読み込む例.
これを応用すれば,構造さえわかればいかなるデータフォーマットでも読み込める.
参考データ:windows bmp file のヘッダを表すC構造体.詳しくは Windows SDK などの wingdi.h を参照.
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
structでファイル読み込み解析. bufをunpack()
# find every bmp files in directory, open and read it # using Structure # x padding a byte 1 # c char 1 # b signed char 1 # B uchar, BYTE 1 # ? _Bool 1 # h short 2 # H ushort, WORD 2 # i int 4 # I uint, DWORD 4 # l long, LONG 4 # L ulong, ULONG 4 # q long long, LONGLONG 8 # Q ulong long, ULONGLONG 8 # f float 4 # d double 8 import os import struct BMFH = struct.Struct("=HIHHI") BMIH = struct.Struct("=IllHHIIllII") RGBQ = struct.Struct("=BBBB") print('Start reading bmp files...') for img_fname in os.listdir('.'): if not img_fname.endswith('.bmp'): continue print('filename is', img_fname) with open(img_fname, mode='rb') as f: # read bmfh buf = f.read(14) # sizeof(BITMAPFILEHEADER) bmfh = BMFH.unpack(buf) print('bfType =', hex(bmfh[0])) print('bfOffBits =', bmfh[4]) # read bmih buf = f.read(40) # sizeof(BITMAPINFOHEADER) bmih = BMIH.unpack(buf) w = bmih[1] h = bmih[2] bpp = bmih[4] print('biSize =', bmih[0]) print('Width =', w) print('Height =', h) print('BPP =', bpp) # read image body f.seek(bmfh[4]) img = f.read(w*h) print(img[0]) f.close()
classでデータストラクチャを定義, メンバ名でアクセスできる.
# find every bmp files in directory, open and read it # using ctypes ans class definition. # Image is shown by using matplotlib # import os from ctypes import * import numpy as np import matplotlib.pyplot as plt class BITMAPFILEHEADER(Structure): _fields_ = [ ('bfType', c_uint16), ('bfSize', c_uint32), ('bfReserved1', c_uint16), ('bfReserved2', c_uint16), ('bfOffBits', c_uint32), ] _pack_ = 1 class BITMAPINFOHEADER(Structure): _fields_ = [ ('biSize', c_uint32), ('biWidth', c_int32), ('biHeight', c_int32), ('biPlanes', c_uint16), ('biBitCount', c_uint16), ('biCompression', c_uint32), ('biSizeImage', c_uint32), ('biXPPM', c_int32), ('biYPP', c_int32), ('biClrUsed', c_uint32), ('biClrImportant',c_uint32), ('bfType', c_uint16), ('bfSize', c_uint32), ('bfReserved1', c_uint16), ('bfReserved2', c_uint16), ('bfOffBits', c_uint32), ] _pack_ = 1 print('Start reading bmp files...') for img_fname in os.listdir('.'): if not img_fname.endswith('.bmp'): continue print('filename is', img_fname) with open(img_fname, mode='rb') as f: # read and parse bmfh bmfh = BITMAPFILEHEADER() f.readinto(bmfh) if(bmfh.bfType != 0x4d42): print('ERROR : wrong bmfh.bfType') continue; if(bmfh.bfOffBits != 1078): print('ERROR : wrong bmfh') continue; # read and parse bmih bmih = BITMAPINFOHEADER() f.readinto(bmih) print('w , h =', str(bmih.biWidth), 'x', str(bmih.biHeight)+' pixel') if(bmih.biBitCount != 8): print('ERROR : wrong bit count') continue; w = bmih.biWidth h = bmih.biHeight f.seek(bmfh.bfOffBits) img = f.read(w*h) dt = np.dtype(('<u1', (w, h))) x = np.frombuffer(img, dt) #Remove unnecessary dimension that numpy gave us x = x[0,:,:] # print(x[0][0]) plt.imshow(x, extent=[0,w,0,h], aspect="auto") plt.show() f.close()