 c3ececcf96
			
		
	
	
		c3ececcf96
		
			
		
	
	
	
	
		
			
			* ufbt: added "dolphin_ext" target (expects "external" subfolder in cwd with dolphin assets); cleaned up unused code * ufbt: codestyle fixes * scripts: fixed style according to ruff linter * scripts: additional cleanup & codestyle fixes * github: pass target hw code when installing local SDK with ufbt * ufbt: added error message for missing folder in dolphin builder * scripts: more linter fixes * sdk: added flipper_format_stream; ufbt: support for --extra-define * fbt: reduced amount of global defines * scripts, fbt: rearranged imports Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
		
			
				
	
	
		
			108 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import logging
 | |
| import subprocess
 | |
| import io
 | |
| 
 | |
| ICONS_SUPPORTED_FORMATS = ["png"]
 | |
| 
 | |
| 
 | |
| class Image:
 | |
|     def __init__(self, width: int, height: int, data: bytes):
 | |
|         self.width = width
 | |
|         self.height = height
 | |
|         self.data = data
 | |
| 
 | |
|     def write(self, filename):
 | |
|         with open(filename, "wb") as file:
 | |
|             file.write(self.data)
 | |
| 
 | |
|     def data_as_carray(self):
 | |
|         return (
 | |
|             "{" + "".join("0x{:02x},".format(img_byte) for img_byte in self.data) + "}"
 | |
|         )
 | |
| 
 | |
| 
 | |
| def is_file_an_icon(filename):
 | |
|     extension = filename.lower().split(".")[-1]
 | |
|     return extension in ICONS_SUPPORTED_FORMATS
 | |
| 
 | |
| 
 | |
| class ImageTools:
 | |
|     __pil_unavailable = False
 | |
|     __hs2_unavailable = False
 | |
| 
 | |
|     @staticmethod
 | |
|     def is_processing_slow():
 | |
|         try:
 | |
|             return False
 | |
|         except ImportError:
 | |
|             return True
 | |
| 
 | |
|     def __init__(self):
 | |
|         self.logger = logging.getLogger()
 | |
| 
 | |
|     def png2xbm(self, file):
 | |
|         if self.__pil_unavailable:
 | |
|             return subprocess.check_output(["convert", file, "xbm:-"])
 | |
| 
 | |
|         try:
 | |
|             from PIL import Image, ImageOps
 | |
|         except ImportError:
 | |
|             self.__pil_unavailable = True
 | |
|             self.logger.info("pillow module is missing, using convert cli util")
 | |
|             return self.png2xbm(file)
 | |
| 
 | |
|         with Image.open(file) as im:
 | |
|             with io.BytesIO() as output:
 | |
|                 bw = im.convert("1")
 | |
|                 bw = ImageOps.invert(bw)
 | |
|                 bw.save(output, format="XBM")
 | |
|                 return output.getvalue()
 | |
| 
 | |
|     def xbm2hs(self, data):
 | |
|         if self.__hs2_unavailable:
 | |
|             return subprocess.check_output(
 | |
|                 ["heatshrink", "-e", "-w8", "-l4"], input=data
 | |
|             )
 | |
| 
 | |
|         try:
 | |
|             import heatshrink2
 | |
|         except ImportError:
 | |
|             self.__hs2_unavailable = True
 | |
|             self.logger.info("heatshrink2 module is missing, using heatshrink cli util")
 | |
|             return self.xbm2hs(data)
 | |
| 
 | |
|         return heatshrink2.compress(data, window_sz2=8, lookahead_sz2=4)
 | |
| 
 | |
| 
 | |
| __tools = ImageTools()
 | |
| 
 | |
| 
 | |
| def file2image(file):
 | |
|     output = __tools.png2xbm(file)
 | |
|     assert output
 | |
| 
 | |
|     # Extract data from text
 | |
|     f = io.StringIO(output.decode().strip())
 | |
|     width = int(f.readline().strip().split(" ")[2])
 | |
|     height = int(f.readline().strip().split(" ")[2])
 | |
|     data = f.read().strip().replace("\n", "").replace(" ", "").split("=")[1][:-1]
 | |
|     data_str = data[1:-1].replace(",", " ").replace("0x", "")
 | |
| 
 | |
|     data_bin = bytearray.fromhex(data_str)
 | |
| 
 | |
|     # Encode icon data with LZSS
 | |
|     data_encoded_str = __tools.xbm2hs(data_bin)
 | |
| 
 | |
|     assert data_encoded_str
 | |
| 
 | |
|     data_enc = bytearray(data_encoded_str)
 | |
|     data_enc = bytearray([len(data_enc) & 0xFF, len(data_enc) >> 8]) + data_enc
 | |
| 
 | |
|     # Use encoded data only if its length less than original, including header
 | |
|     if len(data_enc) + 2 < len(data_bin) + 1:
 | |
|         data = b"\x01\x00" + data_enc
 | |
|     else:
 | |
|         data = b"\x00" + data_bin
 | |
| 
 | |
|     return Image(width, height, data)
 |