Performance optimization of image loading - inlining
This commit is contained in:
		
							parent
							
								
									c6ce9c6654
								
							
						
					
					
						commit
						c0eee33bec
					
				
							
								
								
									
										47
									
								
								microbmp.py
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								microbmp.py
									
									
									
									
									
								
							| @ -15,7 +15,7 @@ __all__ = ["MicroBMP"] | ||||
| 
 | ||||
| 
 | ||||
| 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 | ||||
|         self.BMP_id = b"BM" | ||||
|         self.BMP_size = None | ||||
| @ -44,6 +44,7 @@ class MicroBMP(object): | ||||
|         self.row_size = None | ||||
|         self.padded_row_size = None | ||||
| 
 | ||||
|         self.header_callback = header_callback | ||||
|         self.data_callback = data_callback | ||||
|          | ||||
|         self.initialised = False | ||||
| @ -211,7 +212,7 @@ class MicroBMP(object): | ||||
|                     x += 1 | ||||
| 
 | ||||
|     def read_io(self, bf_io): | ||||
|         print("BMP reading file") | ||||
|         #print("BMP reading file") | ||||
|         # BMP Header | ||||
|         data = bf_io.read(14) | ||||
|         self.BMP_id = data[0:2] | ||||
| @ -234,18 +235,7 @@ class MicroBMP(object): | ||||
|             self.DIB_hres, | ||||
|             self.DIB_vres, | ||||
|         ) = 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_important_num_info = unpack("<I", data[32:36])[0] | ||||
|         if self.DIB_len > 40: | ||||
| @ -270,31 +260,52 @@ class MicroBMP(object): | ||||
|         else: | ||||
|             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 | ||||
|         assert self._init(), "Failed to initialize the image!" | ||||
| 
 | ||||
|         # Pixels | ||||
|         print("BMP reading data") | ||||
|         #print("BMP reading data") | ||||
|         if self.DIB_comp == 0: | ||||
|             # BI_RGB | ||||
|             for h in range(self.DIB_h): | ||||
|                 y = h if is_top_down else self.DIB_h - h - 1 | ||||
|                 data = bf_io.read(self.padded_row_size) | ||||
|                 #pixels_row = [] | ||||
|                 for x in range(self.DIB_w): | ||||
|                     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] | ||||
|                         ##pixels_row.append(pixel) | ||||
|                         self.data_callback(x, y, pixel) | ||||
|                     else: | ||||
|                         v = x * 3 | ||||
|                         # BMP colour is in BGR order. | ||||
|                         self[x, y] = (data[v + 2], data[v + 1], data[v]) | ||||
|                 #self.data_callback(0, y, pixels_row) | ||||
|         else: | ||||
|             # BI_RLE8 or BI_RLE4 | ||||
|             self._decode_rle(bf_io) | ||||
| 
 | ||||
|         print("BMP done") | ||||
|         #print("BMP done") | ||||
|         return self | ||||
| 
 | ||||
|     def write_io(self, bf_io, force_40B_DIB=False): | ||||
|  | ||||
							
								
								
									
										77
									
								
								test.py
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								test.py
									
									
									
									
									
								
							| @ -1,9 +1,11 @@ | ||||
| import epaper | ||||
| import microbmp | ||||
| import time | ||||
| import random | ||||
| import gc | ||||
| 
 | ||||
| colormap = [ | ||||
| epd_resolution = [600, 448] | ||||
| epd_colormap = [ | ||||
|             [0x00, 0x00, 0x00], # black | ||||
|             [0xff, 0xff, 0xff], # white | ||||
|             [0x00, 0xdd, 0x00], # green | ||||
| @ -25,32 +27,63 @@ def init_display(): | ||||
| 
 | ||||
| def draw_image(filename): | ||||
|     global epd | ||||
|     global colormap | ||||
|     def color_distance(c1, c2): | ||||
|         def dist(a, b): | ||||
|             return abs(a - b) | ||||
|         return dist(c1[0], c2[0]) + dist(c1[1], c2[1]) + dist(c1[2], c2[2]) | ||||
|     def callback(x, y, color): | ||||
|     global epd_colormap | ||||
|     offset_x = 0 | ||||
|     offset_y = 0 | ||||
|     color_map = {} | ||||
|     def header_callback(header): | ||||
|         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 colormap | ||||
|         best_index = 0 | ||||
|         best_score = 256 | ||||
|         for index in range(len(colormap)): | ||||
|             c = colormap[index] | ||||
|             score = color_distance(c, color) | ||||
|             if score < best_score: | ||||
|                 best_score = score | ||||
|                 best_index = index | ||||
|         pixel = best_index | ||||
|         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_score = 1000 | ||||
|             for index in range(len(epd_colormap)): | ||||
|                 c1 = epd_colormap[index] | ||||
|                 c2 = color | ||||
|                 score = abs(c1[0] - c2[0]) + abs(c1[1] - c2[1]) + abs(c1[2] - c2[2]) | ||||
|                 if score < best_score: | ||||
|                     best_score = score | ||||
|                     best_index = index | ||||
|                 if score < 20: | ||||
|                     break | ||||
|             color_index = best_index | ||||
|             color_map[color_key] = color_index | ||||
|          | ||||
|         # 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])) | ||||
|         epd.pixel(x, y, pixel) | ||||
|         #for i in range(len(colors)): | ||||
|         #    epd.pixel(offset_x + x + i, offset_y + y, color_to_index(colors[i])) | ||||
| 
 | ||||
|     #print("BMP ", filename, " loading ", str(time.localtime())) | ||||
|     print(str(time.localtime()), " BMP ", filename, " loading") | ||||
|     epd.fill(epd.White) | ||||
|     microbmp.MicroBMP(data_callback=callback).load(filename) | ||||
|     #print("BMP loaded ", str(time.localtime())) | ||||
|     microbmp.MicroBMP(header_callback=header_callback, data_callback=pixel_callback).load(filename) | ||||
|     print(str(time.localtime()), " BMP loaded") | ||||
|     epd.EPD_5IN65F_Display(epd.buffer) | ||||
|     #print("ePaper printed ", str(time.localtime())) | ||||
|     print(str(time.localtime()), " ePaper printed") | ||||
| 
 | ||||
| 
 | ||||
| # MAIN | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user