playscii/formats/in_edscii.py

93 lines
3.4 KiB
Python

from art_import import ArtImporter
from ui_art_dialog import ImportOptionsDialog
from ui_dialog import Field, UIDialog
class EDSCIIImportOptionsDialog(ImportOptionsDialog):
title = "Import EDSCII (legacy format) art"
field0_label = "Width override (leave 0 to guess):"
field_width = UIDialog.default_short_field_width
fields = [Field(label=field0_label, type=int, width=field_width, oneline=False)]
invalid_width_error = "Invalid width override."
def get_initial_field_text(self, field_number):
if field_number == 0:
return "0"
return ""
def is_input_valid(self):
# valid widths: any >=0 int
try:
int(self.field_texts[0])
except:
return False, self.invalid_width_error
if int(self.field_texts[0]) < 0:
return False, self.invalid_width_error
return True, None
def confirm_pressed(self):
valid, reason = self.is_input_valid()
if not valid:
return
width = int(self.field_texts[0])
width = width if width > 0 else None
options = {"width_override": width}
self.dismiss()
# self.filename is set in our importer's file_chooser_dialog_class
ImportOptionsDialog.do_import(self.ui.app, self.filename, options)
class EDSCIIImporter(ArtImporter):
format_name = "EDSCII"
format_description = """
Binary format for EDSCII, Playscii's predecessor.
Assumes single frame, single layer document.
Current character set and palette will be used.
"""
options_dialog_class = EDSCIIImportOptionsDialog
def run_import(self, in_filename, options={}):
data = open(in_filename, "rb").read()
# document width = find longest stretch before a \n
longest_line = 0
for line in data.splitlines():
if len(line) > longest_line:
longest_line = len(line)
# user can override assumed document width, needed for a few files
width = options.get("width_override", None) or int(longest_line / 3)
# derive height from width
# 2-byte line breaks might produce non-int result, cast erases this
height = int(len(data) / width / 3)
self.art.resize(width, height)
# populate char/color arrays by scanning width-long chunks of file
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i : i + n]
# 3 bytes per tile, +1 for line ending
# BUT: files saved in windows may have 2 byte line breaks, try to detect
lb_length = 1
lines = chunks(data, (width * 3) + lb_length)
for line in lines:
if line[-2] == ord("\r") and line[-1] == ord("\n"):
# self.app.log('EDSCIIImporter: windows-style line breaks detected')
lb_length = 2
break
# recreate generator after first use
lines = chunks(data, (width * 3) + lb_length)
x, y = 0, 0
for line in lines:
index = 0
while index < len(line) - lb_length:
char = line[index]
# +1 to color indices; playscii color index 0 = transparent
fg = line[index + 1] + 1
bg = line[index + 2] + 1
self.art.set_tile_at(0, 0, x, y, char, fg, bg)
index += 3
x += 1
if x >= width:
x = 0
y += 1
return True