a bunch of more fixes
This commit is contained in:
parent
d0a60081ac
commit
2a7f5da0d0
4 changed files with 148 additions and 83 deletions
20
common.py
Normal file
20
common.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import crcmod
|
||||||
|
import colorsys
|
||||||
|
|
||||||
|
from PIL import ImageFont
|
||||||
|
|
||||||
|
font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", 24)
|
||||||
|
|
||||||
|
def get_complement(r,g,b):
|
||||||
|
r = r/255.0
|
||||||
|
g = g/255.0
|
||||||
|
b = b/255.0
|
||||||
|
h,l,s = colorsys.rgb_to_hls(r, g, b)
|
||||||
|
if h > 0.5:
|
||||||
|
h -= 0.5
|
||||||
|
else:
|
||||||
|
h += 0.5
|
||||||
|
r,g,b = colorsys.hls_to_rgb(h, l, s)
|
||||||
|
return int(r*255), int(g*255), int(b*255)
|
||||||
|
|
||||||
|
crc24_func = crcmod.mkCrcFun(0x1864CFBL) # polynomial from libgcrypt
|
|
@ -8,8 +8,18 @@ from PIL import Image
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
def sanitize_filename(fname):
|
||||||
|
# find the first character outside range [32-126]
|
||||||
|
for i,c in enumerate(fname):
|
||||||
|
if ord(c) < 32 or ord(c) > 126:
|
||||||
|
break
|
||||||
|
return fname[:i]
|
||||||
|
|
||||||
def extract_def(infile,outdir):
|
def extract_def(infile,outdir):
|
||||||
f = open(infile)
|
f = open(infile)
|
||||||
|
bn = os.path.basename(infile)
|
||||||
|
bn = os.path.splitext(bn)[0]
|
||||||
|
|
||||||
# t - type
|
# t - type
|
||||||
# blocks - # of blocks
|
# blocks - # of blocks
|
||||||
# the second and third entry are width and height which are not used
|
# the second and third entry are width and height which are not used
|
||||||
|
@ -21,6 +31,7 @@ def extract_def(infile,outdir):
|
||||||
palette.extend((r,g,b))
|
palette.extend((r,g,b))
|
||||||
|
|
||||||
offsets = defaultdict(list)
|
offsets = defaultdict(list)
|
||||||
|
k = 0 # for naming bogus filename entries
|
||||||
for i in range(blocks):
|
for i in range(blocks):
|
||||||
# bid - block id
|
# bid - block id
|
||||||
# entries - number of images in this block
|
# entries - number of images in this block
|
||||||
|
@ -30,17 +41,23 @@ def extract_def(infile,outdir):
|
||||||
# a list of 13 character long filenames
|
# a list of 13 character long filenames
|
||||||
for j in range(entries):
|
for j in range(entries):
|
||||||
name, = struct.unpack("13s", f.read(13))
|
name, = struct.unpack("13s", f.read(13))
|
||||||
name = name[:name.index('\0')]
|
name = sanitize_filename(name)
|
||||||
|
# if nothing remains, create bogus name
|
||||||
|
if len(name) == 0:
|
||||||
|
num = "%02d"%k
|
||||||
|
if len(bn)+len(num) > 9: # truncate name
|
||||||
|
name = bn[:9-len(num)]+num
|
||||||
|
else:
|
||||||
|
name = bn+num
|
||||||
|
k+=1
|
||||||
names.append(name)
|
names.append(name)
|
||||||
# a list of offsets
|
# a list of offsets
|
||||||
for n in names:
|
for n in names:
|
||||||
offs, = struct.unpack("<I", f.read(4))
|
offs, = struct.unpack("<I", f.read(4))
|
||||||
offsets[bid].append((n,offs))
|
offsets[bid].append((n,offs))
|
||||||
|
|
||||||
bn = os.path.basename(infile)
|
|
||||||
bn = os.path.splitext(bn)[0]
|
|
||||||
for bid,l in offsets.items():
|
for bid,l in offsets.items():
|
||||||
for n,offs in l:
|
for j,(n,offs) in enumerate(l):
|
||||||
f.seek(offs)
|
f.seek(offs)
|
||||||
pixeldata = ""
|
pixeldata = ""
|
||||||
# first entry is the size which is unused
|
# first entry is the size which is unused
|
||||||
|
@ -50,11 +67,11 @@ def extract_def(infile,outdir):
|
||||||
# lm,tm - left and top margin
|
# lm,tm - left and top margin
|
||||||
_,fmt,fw,fh,w,h,lm,tm = struct.unpack("<IIIIIIii", f.read(32))
|
_,fmt,fw,fh,w,h,lm,tm = struct.unpack("<IIIIIIii", f.read(32))
|
||||||
n = os.path.splitext(n)[0]
|
n = os.path.splitext(n)[0]
|
||||||
outname = "%s"%outdir+os.sep+"%s_%02d_%s_%dx%d_%dx%d.png"%(bn,bid,n,fw,fh,lm,tm)
|
outname = "%s"%outdir+os.sep+"%02d_%s_%02d_%02d_%s_%dx%d_%dx%d.png"%(t,bn,bid,j,n,fw,fh,lm,tm)
|
||||||
print "writing to %s"%outname
|
print "writing to %s"%outname
|
||||||
|
|
||||||
|
if w != 0 and h != 0:
|
||||||
if fmt == 0:
|
if fmt == 0:
|
||||||
# uncompressed, so the following *should* work but there is no
|
|
||||||
# test data
|
|
||||||
pixeldata = f.read(w*h)
|
pixeldata = f.read(w*h)
|
||||||
elif fmt == 1:
|
elif fmt == 1:
|
||||||
# SGTWMTA.def and SGTWMTB.def fail here
|
# SGTWMTA.def and SGTWMTB.def fail here
|
||||||
|
@ -111,6 +128,13 @@ def extract_def(infile,outdir):
|
||||||
print "unknown format: %d"%fmt
|
print "unknown format: %d"%fmt
|
||||||
return False
|
return False
|
||||||
im = Image.fromstring('P', (w,h),pixeldata)
|
im = Image.fromstring('P', (w,h),pixeldata)
|
||||||
|
else: # either width or height is zero
|
||||||
|
if w == 0:
|
||||||
|
w = 1
|
||||||
|
if h == 0:
|
||||||
|
h = 1
|
||||||
|
# TODO: encode this information correctly and dont create a fake 1px image
|
||||||
|
im = Image.new('P', (w,h))
|
||||||
im.putpalette(palette)
|
im.putpalette(palette)
|
||||||
im.save(outname)
|
im.save(outname)
|
||||||
return True
|
return True
|
||||||
|
@ -120,7 +144,7 @@ if __name__ == '__main__':
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print "usage: %s input.def ./outdir"%sys.argv[0]
|
print "usage: %s input.def ./outdir"%sys.argv[0]
|
||||||
print "to process all files:"
|
print "to process all files:"
|
||||||
print " for f in *.def; do n=`basename $f .def`; mkdir -p defs/$n; $s defextract.py $f defs/$n; done"%sys.argv[0]
|
print " for f in *.def; do n=`basename $f .def`; mkdir -p defs/$n; %s defextract.py $f defs/$n; done"%sys.argv[0]
|
||||||
exit(1)
|
exit(1)
|
||||||
ret = extract_def(sys.argv[1], sys.argv[2])
|
ret = extract_def(sys.argv[1], sys.argv[2])
|
||||||
exit(0 if ret else 1)
|
exit(0 if ret else 1)
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
import zlib
|
import zlib
|
||||||
import struct
|
import struct
|
||||||
import os
|
import os
|
||||||
from PIL import Image
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
|
from common import crc24_func, get_complement, font
|
||||||
|
|
||||||
def is_pcx(data):
|
def is_pcx(data):
|
||||||
size,width,height = struct.unpack("<III",data[:12])
|
size,width,height = struct.unpack("<III",data[:12])
|
||||||
|
@ -25,7 +27,7 @@ def read_pcx(data):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def unpack_lod(infile,outdir):
|
def unpack_lod(infile,outdir,shred=True):
|
||||||
f = open(infile)
|
f = open(infile)
|
||||||
|
|
||||||
if f.read(4) != 'LOD\0':
|
if f.read(4) != 'LOD\0':
|
||||||
|
@ -54,6 +56,16 @@ def unpack_lod(infile,outdir):
|
||||||
if is_pcx(data):
|
if is_pcx(data):
|
||||||
im = read_pcx(data)
|
im = read_pcx(data)
|
||||||
if im:
|
if im:
|
||||||
|
if shred:
|
||||||
|
crc = crc24_func(filename)
|
||||||
|
r = crc>>16
|
||||||
|
g = (crc&0xff00)>>8
|
||||||
|
b = crc&0xff
|
||||||
|
w,h = im.size
|
||||||
|
im = Image.new("RGB", (w*3,h*3), (r,g,b))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
draw.text((0,0),os.path.basename(filename),get_complement(r,g,b),font=font)
|
||||||
|
im = im.resize((w,h),Image.ANTIALIAS)
|
||||||
im.save(filename, "PNG")
|
im.save(filename, "PNG")
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
43
makedef.py
43
makedef.py
|
@ -4,12 +4,18 @@ import os
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from PIL import Image
|
from PIL import Image, ImageDraw
|
||||||
|
from common import crc24_func, font
|
||||||
|
|
||||||
def makedef(indir, outdir):
|
def get_color(fname):
|
||||||
|
crc = crc24_func(fname)
|
||||||
|
# values 0-7 must not be used as they might represent transparency
|
||||||
|
# so we are left with 248 values
|
||||||
|
return 8+crc%248
|
||||||
|
|
||||||
|
def makedef(indir, outdir, shred=True):
|
||||||
infiles = defaultdict(list)
|
infiles = defaultdict(list)
|
||||||
sig = None
|
sig = None
|
||||||
fnames = set()
|
|
||||||
# sanity checks and fill infiles dict
|
# sanity checks and fill infiles dict
|
||||||
for f in os.listdir(indir):
|
for f in os.listdir(indir):
|
||||||
m = re.match('(\d+)_([A-Za-z0-9_]+)_(\d\d)_(\d\d)_([A-Za-z0-9_]+)_(\d+)x(\d+)_(\d+)x(\d+).png', f)
|
m = re.match('(\d+)_([A-Za-z0-9_]+)_(\d\d)_(\d\d)_([A-Za-z0-9_]+)_(\d+)x(\d+)_(\d+)x(\d+).png', f)
|
||||||
|
@ -22,7 +28,7 @@ def makedef(indir, outdir):
|
||||||
if im.mode != 'P':
|
if im.mode != 'P':
|
||||||
print "input images must have a palette"
|
print "input images must have a palette"
|
||||||
return False
|
return False
|
||||||
cursig =(t,p,fw,fh,im.getpalette())
|
cursig =(t,p,im.getpalette())
|
||||||
if not sig:
|
if not sig:
|
||||||
sig = cursig
|
sig = cursig
|
||||||
else:
|
else:
|
||||||
|
@ -31,30 +37,29 @@ def makedef(indir, outdir):
|
||||||
print sig
|
print sig
|
||||||
print cursig
|
print cursig
|
||||||
return False
|
return False
|
||||||
if fn in fnames:
|
|
||||||
print "duplicate filename: %s"%fn
|
|
||||||
return False
|
|
||||||
if w%16 != 0:
|
|
||||||
print "width must be divisible by 16"
|
|
||||||
return False
|
|
||||||
if len(fn) > 9:
|
if len(fn) > 9:
|
||||||
print "filename can't be longer than 9 bytes"
|
print "filename can't be longer than 9 bytes"
|
||||||
return False
|
return False
|
||||||
fnames.add(fn)
|
|
||||||
infiles[bid].append((im,t,p,j,fn,fw,fh,lm,tm))
|
infiles[bid].append((im,t,p,j,fn,fw,fh,lm,tm))
|
||||||
|
|
||||||
|
if len(infiles) == 0:
|
||||||
|
print "no input files detected"
|
||||||
|
return False
|
||||||
|
|
||||||
# check if j values for all bids are correct and sort them in j order in the process
|
# check if j values for all bids are correct and sort them in j order in the process
|
||||||
for bid in infiles:
|
for bid in infiles:
|
||||||
infiles[bid].sort(key=lambda t: t[3])
|
infiles[bid].sort(key=lambda t: t[3])
|
||||||
for k,(_,_,bid,j,_,_,_,_,_) in enumerate(infiles[bid]):
|
for k,(_,_,_,j,_,_,_,_,_) in enumerate(infiles[bid]):
|
||||||
if k != j:
|
if k != j:
|
||||||
print "incorrect j value %d for bid %d should be %d"%(j,bid,k)
|
print "incorrect j value %d for bid %d should be %d"%(j,bid,k)
|
||||||
|
|
||||||
t,p,fw,fh,pal = cursig
|
t,p,pal = cursig
|
||||||
outf = open(outdir+"/"+p+".def", "w+")
|
outf = open(outdir+"/"+p+".def", "w+")
|
||||||
|
|
||||||
# write the header
|
# write the header
|
||||||
outf.write(struct.pack("<IIII", t,fw,fh,len(infiles)))
|
# full width and height are not used and not the same for all frames
|
||||||
|
# in some defs, so setting to zero
|
||||||
|
outf.write(struct.pack("<IIII", t,0,0,len(infiles)))
|
||||||
# write the palette
|
# write the palette
|
||||||
outf.write(struct.pack("768B", *pal))
|
outf.write(struct.pack("768B", *pal))
|
||||||
|
|
||||||
|
@ -65,6 +70,7 @@ def makedef(indir, outdir):
|
||||||
|
|
||||||
for bid,l in infiles.items():
|
for bid,l in infiles.items():
|
||||||
# write bid and number of frames
|
# write bid and number of frames
|
||||||
|
# the last two values have unknown meaning
|
||||||
outf.write(struct.pack("<IIII",bid,len(l),0,0))
|
outf.write(struct.pack("<IIII",bid,len(l),0,0))
|
||||||
# write filenames
|
# write filenames
|
||||||
for _,_,_,_,fn,_,_,_,_ in l:
|
for _,_,_,_,fn,_,_,_,_ in l:
|
||||||
|
@ -73,17 +79,20 @@ def makedef(indir, outdir):
|
||||||
for im,_,_,_,_,_,_,_,_ in l:
|
for im,_,_,_,_,_,_,_,_ in l:
|
||||||
outf.write(struct.pack("<I",curoffset))
|
outf.write(struct.pack("<I",curoffset))
|
||||||
w,h = im.size
|
w,h = im.size
|
||||||
print curoffset
|
|
||||||
# every image occupies one byte per pixel plus 32 byte header
|
# every image occupies one byte per pixel plus 32 byte header
|
||||||
curoffset += w*h+32
|
curoffset += w*h+32
|
||||||
|
|
||||||
for bid,l in infiles.items():
|
for bid,l in infiles.items():
|
||||||
for im,_,_,_,_,fw,fh,lm,tm in l:
|
for im,_,p,j,_,fw,fh,lm,tm in l:
|
||||||
w,h = im.size
|
w,h = im.size
|
||||||
outf.write(struct.pack("<IIIIIIii",w*h,0,fw,fh,w,h,lm,tm))
|
outf.write(struct.pack("<IIIIIIii",w*h,0,fw,fh,w,h,lm,tm))
|
||||||
|
if shred:
|
||||||
|
im = Image.new("P", (w*3,h*3), get_color(p))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
draw.text((0,0),"%d%s"%(j,p),font=font)
|
||||||
|
im = im.resize((w,h),Image.ANTIALIAS)
|
||||||
buf = ''.join([chr(i) for i in list(im.getdata())])
|
buf = ''.join([chr(i) for i in list(im.getdata())])
|
||||||
outf.write(buf)
|
outf.write(buf)
|
||||||
print outf.tell()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in a new issue