Skip to content

Instantly share code, notes, and snippets.

@dmopalmer
Created June 12, 2015 04:21
Show Gist options
  • Save dmopalmer/01c0a1b721165602a790 to your computer and use it in GitHub Desktop.
Save dmopalmer/01c0a1b721165602a790 to your computer and use it in GitHub Desktop.
"""
Tool to convert jpegs to and from editable hex files
Developed as part of effort to support LightsailA
See
http://swag.outpostbbs.net/GRAPHICS/0143.PAS.html
for information on the jpeg format
Change topdir to wherever you have the files.
Converts every file matching P0*.out.jpg into ASCII hex for editing.
Converts every file matching *.tryhex to binary .jpg to see if that works
"""
from __future__ import absolute_import, print_function, division
topdir='/Users/palmer/Desktop/lightsailA'
import os
import numpy as np
import glob
import re
__author__ = 'palmer'
segnames = {
0x01 : "TEM",
0xc0 : "SOF0",
0xc1 : "SOF1",
0xc2 : "SOF2",
0xc3 : "SOF3",
0xc5 : "SOF5",
0xc6 : "SOF6",
0xc7 : "SOF7",
0xc9 : "SOF9",
0xca : "SOF10",
0xcb : "SOF11",
0xcd : "SOF13",
0xce : "SOF14",
0xcf : "SOF15",
0xc4 : "DHT",
0xc8 : "JPG",
0xcc : "DAC",
0xd0 : "RST0",
0xd1 : "RST1",
0xd2 : "RST2",
0xd3 : "RST3",
0xd4 : "RST4",
0xd5 : "RST5",
0xd6 : "RST6",
0xd7 : "RST7",
0xd8 : "SOI",
0xd9 : "EOI",
0xda : "SOS",
0xdb : "DQT",
0xdc : "DNL",
0xdd : "DRI",
0xde : "DHP",
0xdf : "EXP",
0xe0 : "APP0",
0xef : "APP15",
0xf0 : "JPG0",
0xfd : "JPG13",
0xfe : "COM"
}
def jpegsplit(bytearr):
# Add a bogus segment header, then break into [header,contents,header,contents...]
splits = re.split(b'(\xff[^\0])',b'\xff\xff'+bytearr)
segs = [seghead+rest for seghead,rest in zip(splits[1::2],splits[2::2])]
if segs[0] == b'\xff\xff':
segs = segs[1:] # Nothing in file before first segment header
else:
segs[0] = segs[0][2:] # File does not start with 0xff
return segs
def seg2line(bytearr):
"""
Convert a segment to a line that can go into a .jpeghex file
Format:
F segtype explen readlen | hex
F is '!' if something is wrong
:param bytearr:
:return:
"""
explen = 0 if len(bytearr) < 4 else bytearr[2] * 256 + bytearr[3]
readlen = len(bytearr) - 2
try:
segtype = segnames[int(bytearr[1])]
if segtype.startswith('RST') :
flag = ' '
explen = 0
else:
flag = '!' if (readlen != explen) and segtype != 'SOS' else ' '
except:
segtype = "???"
flag = '!'
hexes = " ".join(["{:02x}".format(b) for b in bytearr])
return "{:1s} {:5s} {:5d} {:5d} | {:s}".format(flag,segtype,explen,readlen,hexes)
def lines2bytes(lines):
"""
Takes lines and returns a bytearray for the hex, where the lines are:
# this is a comment
anythingelse (ignored) | hex
:param lines:
:return:
"""
bytearr = b''
for l in lines:
l = l.strip()
try:
if not l.startswith('#'):
newbytes = bytearray([int(x,base=16) for x in l.split('|')[1].split() if len(x.strip()) > 0])
bytearr += newbytes
except:
pass
return bytearr
for filename in glob.glob(os.path.join(topdir,'P0*.out.jpg')):
outfilename = filename+'.hex'
# Don't overwrite the .hex file if it has changed more recnetly than th ejpeg
if os.path.exists(outfilename) and os.stat(filename).st_mtime < os.stat(outfilename).st_mtime:
continue
bytearr = open(filename,"rb").read()
segs = jpegsplit(bytearr)
lines = [seg2line(seg) for seg in segs]
open(outfilename,"w").write("\n".join(lines))
for filename in glob.glob(os.path.join('/Users/palmer/Desktop/lightsailA','*.tryhex')):
outfilename = filename+'.jpg'
# Don't overwrite the .jpg file if it has changed more recnetly than the tryhex
if os.path.exists(outfilename) and os.stat(filename).st_mtime < os.stat(outfilename).st_mtime:
continue
lines = open(filename).readlines()
bytearr = lines2bytes(lines)
open(outfilename,"wb").write(bytearr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment