diff --git a/common.py b/common.py new file mode 100644 index 0000000..5799a84 --- /dev/null +++ b/common.py @@ -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 diff --git a/defextract.py b/defextract.py index 9779445..3f6ce94 100644 --- a/defextract.py +++ b/defextract.py @@ -8,8 +8,18 @@ from PIL import Image from collections import defaultdict 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): f = open(infile) + bn = os.path.basename(infile) + bn = os.path.splitext(bn)[0] + # t - type # blocks - # of blocks # 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)) offsets = defaultdict(list) + k = 0 # for naming bogus filename entries for i in range(blocks): # bid - block id # entries - number of images in this block @@ -30,17 +41,23 @@ def extract_def(infile,outdir): # a list of 13 character long filenames for j in range(entries): 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) # a list of offsets for n in names: offs, = struct.unpack(" fw or tm > fh: - print "margins (%dx%d) are higher than dimensions (%dx%d)"%(lm,tm,fw,fh) - return False - lineoffs = struct.unpack("<"+"I"*h, f.read(4*h)) - for lineoff in lineoffs: - f.seek(offs+32+lineoff) - totalrowlength=0 - while totalrowlength fw or tm > fh: + print "margins (%dx%d) are higher than dimensions (%dx%d)"%(lm,tm,fw,fh) + return False + lineoffs = struct.unpack("<"+"I"*h, f.read(4*h)) + for lineoff in lineoffs: + f.seek(offs+32+lineoff) + totalrowlength=0 + while totalrowlength>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") else: return False diff --git a/makedef.py b/makedef.py index 4a2ec16..8eec14f 100644 --- a/makedef.py +++ b/makedef.py @@ -4,12 +4,18 @@ import os import re import struct 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) sig = None - fnames = set() # sanity checks and fill infiles dict 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) @@ -22,7 +28,7 @@ def makedef(indir, outdir): if im.mode != 'P': print "input images must have a palette" return False - cursig =(t,p,fw,fh,im.getpalette()) + cursig =(t,p,im.getpalette()) if not sig: sig = cursig else: @@ -31,30 +37,29 @@ def makedef(indir, outdir): print sig print cursig 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: print "filename can't be longer than 9 bytes" return False - fnames.add(fn) 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 for bid in infiles: 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: 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+") # write the header - outf.write(struct.pack("