Performance optimization of image loading - inlining
This commit is contained in:
parent
c6ce9c6654
commit
c0eee33bec
45
microbmp.py
45
microbmp.py
@ -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]
|
||||||
@ -235,17 +236,6 @@ class MicroBMP(object):
|
|||||||
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)
|
##self[x, y] = self._extract_from_bytes(data, x)
|
||||||
pixel_data = 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):
|
||||||
|
71
test.py
71
test.py
@ -1,9 +1,11 @@
|
|||||||
import epaper
|
import epaper
|
||||||
import microbmp
|
import microbmp
|
||||||
import time
|
import time
|
||||||
|
import random
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
colormap = [
|
epd_resolution = [600, 448]
|
||||||
|
epd_colormap = [
|
||||||
[0x00, 0x00, 0x00], # black
|
[0x00, 0x00, 0x00], # black
|
||||||
[0xff, 0xff, 0xff], # white
|
[0xff, 0xff, 0xff], # white
|
||||||
[0x00, 0xdd, 0x00], # green
|
[0x00, 0xdd, 0x00], # green
|
||||||
@ -25,32 +27,63 @@ def init_display():
|
|||||||
|
|
||||||
def draw_image(filename):
|
def draw_image(filename):
|
||||||
global epd
|
global epd
|
||||||
global colormap
|
global epd_colormap
|
||||||
def color_distance(c1, c2):
|
offset_x = 0
|
||||||
def dist(a, b):
|
offset_y = 0
|
||||||
return abs(a - b)
|
color_map = {}
|
||||||
return dist(c1[0], c2[0]) + dist(c1[1], c2[1]) + dist(c1[2], c2[2])
|
def header_callback(header):
|
||||||
def callback(x, y, color):
|
print("header callback: ", str(header))
|
||||||
|
global epd_resolution
|
||||||
|
w = header[0]
|
||||||
|
h = header[1]
|
||||||
|
offset_x = (epd_resolution[0] - w)//2
|
||||||
|
offset_y = (epd_resolution[1] - h)//2
|
||||||
|
print("offset: ", offset_x, offset_y)
|
||||||
|
def pixel_callback(x, y, color):
|
||||||
global epd
|
global epd
|
||||||
global colormap
|
global epd_colormap
|
||||||
|
|
||||||
|
# translate color to color index
|
||||||
|
color_index = 0
|
||||||
|
color_key = color[0] + color[1] << 8 + color[2] << 16
|
||||||
|
if color_key in color_map:
|
||||||
|
color_index = color_map[color_key]
|
||||||
|
else:
|
||||||
|
# search for the best color
|
||||||
best_index = 0
|
best_index = 0
|
||||||
best_score = 256
|
best_score = 1000
|
||||||
for index in range(len(colormap)):
|
for index in range(len(epd_colormap)):
|
||||||
c = colormap[index]
|
c1 = epd_colormap[index]
|
||||||
score = color_distance(c, color)
|
c2 = color
|
||||||
|
score = abs(c1[0] - c2[0]) + abs(c1[1] - c2[1]) + abs(c1[2] - c2[2])
|
||||||
if score < best_score:
|
if score < best_score:
|
||||||
best_score = score
|
best_score = score
|
||||||
best_index = index
|
best_index = index
|
||||||
pixel = best_index
|
if score < 20:
|
||||||
#print("PXL ", str([color, r,g,b, pixel]))
|
break
|
||||||
epd.pixel(x, y, pixel)
|
color_index = best_index
|
||||||
|
color_map[color_key] = color_index
|
||||||
|
|
||||||
#print("BMP ", filename, " loading ", str(time.localtime()))
|
# hack directly into the 4-bit color buffer instead of:
|
||||||
|
# epd.pixel(offset_x + x, offset_y + y, color_to_index(color))
|
||||||
|
buffer_pos = (offset_x + x + (offset_y + y) * epd_resolution[0])
|
||||||
|
buffer_index = buffer_pos // 2
|
||||||
|
if buffer_pos % 2 == 1:
|
||||||
|
buffer_pos = buffer_pos << 4
|
||||||
|
epd.buffer[buffer_index] = color_index
|
||||||
|
def pixel_row_callback(x, y, colors):
|
||||||
|
pass
|
||||||
|
#global epd
|
||||||
|
#print("PXL ", str([color, r,g,b, pixel]))
|
||||||
|
#for i in range(len(colors)):
|
||||||
|
# epd.pixel(offset_x + x + i, offset_y + y, color_to_index(colors[i]))
|
||||||
|
|
||||||
|
print(str(time.localtime()), " BMP ", filename, " loading")
|
||||||
epd.fill(epd.White)
|
epd.fill(epd.White)
|
||||||
microbmp.MicroBMP(data_callback=callback).load(filename)
|
microbmp.MicroBMP(header_callback=header_callback, data_callback=pixel_callback).load(filename)
|
||||||
#print("BMP loaded ", str(time.localtime()))
|
print(str(time.localtime()), " BMP loaded")
|
||||||
epd.EPD_5IN65F_Display(epd.buffer)
|
epd.EPD_5IN65F_Display(epd.buffer)
|
||||||
#print("ePaper printed ", str(time.localtime()))
|
print(str(time.localtime()), " ePaper printed")
|
||||||
|
|
||||||
|
|
||||||
# MAIN
|
# MAIN
|
||||||
|
Loading…
Reference in New Issue
Block a user