ちまたに書籍が溢れているので,詳しくはそちらをどうぞ.
画像ファイルを読み込むだけなら,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()