2024-03-04 21:01:14 +01:00
|
|
|
import base64
|
2024-03-02 12:28:14 +01:00
|
|
|
import json
|
2024-03-04 21:01:14 +01:00
|
|
|
import PIL.Image
|
|
|
|
|
|
|
|
def create_zeroed_array(length):
|
|
|
|
output=[]
|
|
|
|
for _ in range(length):
|
|
|
|
output.append(0)
|
|
|
|
return output
|
2024-03-02 12:28:14 +01:00
|
|
|
|
|
|
|
class Project:
|
|
|
|
def __init__(self):
|
|
|
|
self.chars={}
|
|
|
|
self.char_res=(0,0)
|
|
|
|
self.path=None
|
2024-03-04 21:01:14 +01:00
|
|
|
self.export_path=None
|
2024-03-02 12:28:14 +01:00
|
|
|
self.loaded=False
|
2024-03-03 20:17:42 +01:00
|
|
|
self.modified=False
|
2024-03-02 12:28:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
def load(self,path):
|
|
|
|
with open(path, "r") as f:
|
|
|
|
project_data = json.load(f)
|
|
|
|
if not "char_width" in project_data or not "char_height" in project_data:
|
|
|
|
raise AttributeError("Character metrics information not found")
|
|
|
|
if not isinstance(project_data["char_width"],int) or not isinstance(project_data["char_height"],int):
|
|
|
|
raise AttributeError("Invalid character metrics type, expected int")
|
|
|
|
if not "chars" in project_data:
|
|
|
|
raise AttributeError("Character data not found")
|
|
|
|
if not isinstance(project_data["chars"],dict):
|
|
|
|
raise AttributeError("Invalid character data type, expected object")
|
|
|
|
self.chars=project_data["chars"]
|
|
|
|
self.char_res=(project_data["char_width"],project_data["char_height"])
|
|
|
|
self.path=path
|
|
|
|
self.loaded=True
|
|
|
|
|
|
|
|
|
2024-03-02 22:35:58 +01:00
|
|
|
def save(self,path):
|
|
|
|
# save project data to file
|
|
|
|
with open(path, "w") as f:
|
|
|
|
json.dump({
|
|
|
|
"char_width": self.char_res[0],
|
|
|
|
"char_height": self.char_res[1],
|
|
|
|
"chars": self.chars
|
|
|
|
}, f, indent=4)
|
|
|
|
self.path=path
|
|
|
|
self.loaded=True
|
|
|
|
|
|
|
|
|
2024-03-04 21:01:14 +01:00
|
|
|
def export(self,path):
|
|
|
|
chars = tuple(self.chars.items())
|
|
|
|
|
|
|
|
# there will be 256 characters per page
|
|
|
|
last_char_idx = len(chars) - 1
|
|
|
|
|
|
|
|
page_res = (self.char_res[0] * 16,self.char_res[1] * 16)
|
2024-03-05 11:20:11 +01:00
|
|
|
pages={}
|
2024-03-04 21:01:14 +01:00
|
|
|
|
|
|
|
for char_idx, char in enumerate(chars):
|
2024-03-05 11:20:11 +01:00
|
|
|
char_id=ord(char[0])
|
|
|
|
page=char_id//256
|
|
|
|
char_offset_in_page=char_id-page*256
|
|
|
|
if not page in pages:
|
|
|
|
pages[page] = create_zeroed_array(page_res[0]*page_res[1])
|
2024-03-04 21:01:14 +01:00
|
|
|
|
|
|
|
char_bitmap=self.decode_char(char[0])
|
2024-03-05 11:20:11 +01:00
|
|
|
char_x=char_offset_in_page%16*self.char_res[0]
|
|
|
|
char_y=char_offset_in_page//16*self.char_res[1]
|
2024-03-04 21:01:14 +01:00
|
|
|
|
|
|
|
# put char_bitmap onto page_img at correct position
|
|
|
|
for i in range(len(char_bitmap)):
|
2024-03-05 11:20:11 +01:00
|
|
|
x=i//self.char_res[1]+char_x
|
|
|
|
y=i%self.char_res[1]+char_y
|
|
|
|
pages[page][y*page_res[0]+x]=char_bitmap[i]
|
2024-03-04 21:01:14 +01:00
|
|
|
|
2024-03-05 11:20:11 +01:00
|
|
|
## save page
|
|
|
|
for page,page_data in pages.items():
|
|
|
|
for x in range(len(page_data)):
|
|
|
|
page_data[x]*=255
|
|
|
|
page_img = PIL.Image.frombytes("L",page_res,bytes(page_data))
|
|
|
|
page_img.save(f"{path}/page_{page}.png")
|
2024-03-04 21:01:14 +01:00
|
|
|
|
|
|
|
self.export_path=path
|
|
|
|
|
|
|
|
|
|
|
|
def decode_char(self,char):
|
|
|
|
result=[0 for _ in range(self.char_res[0]*self.char_res[1])]
|
|
|
|
pixels=base64.b64decode(self.chars[char].encode("ascii"))
|
|
|
|
pixel_index=0
|
|
|
|
for pixel in pixels:
|
|
|
|
if pixel_index>=len(result):
|
|
|
|
break
|
|
|
|
for x in range(8):
|
|
|
|
if pixel_index>=len(result):
|
|
|
|
break
|
|
|
|
result[pixel_index]=(pixel>>(7-x))&1
|
|
|
|
pixel_index+=1
|
|
|
|
return result
|
|
|
|
|
2024-03-02 12:28:14 +01:00
|
|
|
def does_char_exist(self,c):
|
|
|
|
return chr(c) in self.chars
|