|
@@ -15,7 +15,7 @@ __all__ = ["MicroBMP"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MicroBMP(object): |
|
|
class MicroBMP(object): |
|
|
def __init__(self, width=None, height=None, depth=None, palette=None, data_callback=None): |
|
|
|
|
|
|
|
|
def __init__(self, width=None, height=None, depth=None, palette=None, header_callback=None, data_callback=None): |
|
|
# BMP Header |
|
|
# BMP Header |
|
|
self.BMP_id = b"BM" |
|
|
self.BMP_id = b"BM" |
|
|
self.BMP_size = None |
|
|
self.BMP_size = None |
|
@@ -44,6 +44,7 @@ class MicroBMP(object): |
|
|
self.row_size = None |
|
|
self.row_size = None |
|
|
self.padded_row_size = None |
|
|
self.padded_row_size = None |
|
|
|
|
|
|
|
|
|
|
|
self.header_callback = header_callback |
|
|
self.data_callback = data_callback |
|
|
self.data_callback = data_callback |
|
|
|
|
|
|
|
|
self.initialised = False |
|
|
self.initialised = False |
|
@@ -211,7 +212,7 @@ class MicroBMP(object): |
|
|
x += 1 |
|
|
x += 1 |
|
|
|
|
|
|
|
|
def read_io(self, bf_io): |
|
|
def read_io(self, bf_io): |
|
|
print("BMP reading file") |
|
|
|
|
|
|
|
|
#print("BMP reading file") |
|
|
# BMP Header |
|
|
# BMP Header |
|
|
data = bf_io.read(14) |
|
|
data = bf_io.read(14) |
|
|
self.BMP_id = data[0:2] |
|
|
self.BMP_id = data[0:2] |
|
@@ -234,18 +235,7 @@ class MicroBMP(object): |
|
|
self.DIB_hres, |
|
|
self.DIB_hres, |
|
|
self.DIB_vres, |
|
|
self.DIB_vres, |
|
|
) = unpack("<iiHHIIii", data[0:28]) |
|
|
) = unpack("<iiHHIIii", data[0:28]) |
|
|
|
|
|
|
|
|
print("BMP metadata: ", str([ |
|
|
|
|
|
self.DIB_w, |
|
|
|
|
|
self.DIB_h, |
|
|
|
|
|
self.DIB_planes_num, |
|
|
|
|
|
self.DIB_depth, |
|
|
|
|
|
self.DIB_comp, |
|
|
|
|
|
self.DIB_raw_size, |
|
|
|
|
|
self.DIB_hres, |
|
|
|
|
|
self.DIB_vres, |
|
|
|
|
|
])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DIB_plt_num_info = unpack("<I", data[28:32])[0] |
|
|
DIB_plt_num_info = unpack("<I", data[28:32])[0] |
|
|
DIB_plt_important_num_info = unpack("<I", data[32:36])[0] |
|
|
DIB_plt_important_num_info = unpack("<I", data[32:36])[0] |
|
|
if self.DIB_len > 40: |
|
|
if self.DIB_len > 40: |
|
@@ -270,31 +260,52 @@ class MicroBMP(object): |
|
|
else: |
|
|
else: |
|
|
is_top_down = False |
|
|
is_top_down = False |
|
|
|
|
|
|
|
|
|
|
|
header = [ |
|
|
|
|
|
self.DIB_w, |
|
|
|
|
|
self.DIB_h, |
|
|
|
|
|
self.DIB_planes_num, |
|
|
|
|
|
self.DIB_depth, |
|
|
|
|
|
self.DIB_comp, |
|
|
|
|
|
self.DIB_raw_size, |
|
|
|
|
|
self.DIB_hres, |
|
|
|
|
|
self.DIB_vres, |
|
|
|
|
|
self.palette, |
|
|
|
|
|
] |
|
|
|
|
|
#print("BMP metadata: ", str(header)) |
|
|
|
|
|
|
|
|
|
|
|
if self.header_callback is not None: |
|
|
|
|
|
self.header_callback(header) |
|
|
self.parray = None |
|
|
self.parray = None |
|
|
assert self._init(), "Failed to initialize the image!" |
|
|
assert self._init(), "Failed to initialize the image!" |
|
|
|
|
|
|
|
|
# Pixels |
|
|
# Pixels |
|
|
print("BMP reading data") |
|
|
|
|
|
|
|
|
#print("BMP reading data") |
|
|
if self.DIB_comp == 0: |
|
|
if self.DIB_comp == 0: |
|
|
# BI_RGB |
|
|
# BI_RGB |
|
|
for h in range(self.DIB_h): |
|
|
for h in range(self.DIB_h): |
|
|
y = h if is_top_down else self.DIB_h - h - 1 |
|
|
y = h if is_top_down else self.DIB_h - h - 1 |
|
|
data = bf_io.read(self.padded_row_size) |
|
|
data = bf_io.read(self.padded_row_size) |
|
|
|
|
|
#pixels_row = [] |
|
|
for x in range(self.DIB_w): |
|
|
for x in range(self.DIB_w): |
|
|
if self.DIB_depth <= 8: |
|
|
if self.DIB_depth <= 8: |
|
|
#self[x, y] = self._extract_from_bytes(data, x) |
|
|
|
|
|
pixel_data = self._extract_from_bytes(data, x) |
|
|
|
|
|
|
|
|
##self[x, y] = self._extract_from_bytes(data, x) |
|
|
|
|
|
byte_index, pos_in_byte = divmod(x, self.ppb) |
|
|
|
|
|
shift = 8 - self.DIB_depth * (pos_in_byte + 1) |
|
|
|
|
|
pixel_data = (data[byte_index] >> shift) & self.pmask |
|
|
|
|
|
#pixel_data = self._extract_from_bytes(data, x) |
|
|
pixel = pixel_data if self.palette is None else self.palette[pixel_data] |
|
|
pixel = pixel_data if self.palette is None else self.palette[pixel_data] |
|
|
|
|
|
##pixels_row.append(pixel) |
|
|
self.data_callback(x, y, pixel) |
|
|
self.data_callback(x, y, pixel) |
|
|
else: |
|
|
else: |
|
|
v = x * 3 |
|
|
v = x * 3 |
|
|
# BMP colour is in BGR order. |
|
|
# BMP colour is in BGR order. |
|
|
self[x, y] = (data[v + 2], data[v + 1], data[v]) |
|
|
self[x, y] = (data[v + 2], data[v + 1], data[v]) |
|
|
|
|
|
#self.data_callback(0, y, pixels_row) |
|
|
else: |
|
|
else: |
|
|
# BI_RLE8 or BI_RLE4 |
|
|
# BI_RLE8 or BI_RLE4 |
|
|
self._decode_rle(bf_io) |
|
|
self._decode_rle(bf_io) |
|
|
|
|
|
|
|
|
print("BMP done") |
|
|
|
|
|
|
|
|
#print("BMP done") |
|
|
return self |
|
|
return self |
|
|
|
|
|
|
|
|
def write_io(self, bf_io, force_40B_DIB=False): |
|
|
def write_io(self, bf_io, force_40B_DIB=False): |
|
|